adds dark mode and logs errors in message response

This commit is contained in:
Danny Avila 2023-02-08 09:15:47 -05:00
parent 58498ed951
commit b5042a738e
13 changed files with 13873 additions and 536 deletions

View file

@ -4,6 +4,7 @@ import { createRoot } from 'react-dom/client';
import { Provider } from 'react-redux';
import { store } from './src/store';
import App from './src/App';
import { ThemeProvider } from './src/hooks/ThemeContext';
import './src/style.css';
const container = document.getElementById('root');
@ -11,6 +12,8 @@ const root = createRoot(container); // createRoot(container!) if you use TypeScr
// reactDom.render(<App />, document.getElementById('root'));
root.render(
<Provider store={store}>
<App />
<ThemeProvider>
<App />
</ThemeProvider>
</Provider>
);

14240
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,12 +1,39 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta charset="utf-8" />
<title>ChatGPT Clone</title>
<link rel="shortcut icon" href="#">
<meta name="viewport" content="width=device-width, initial-scale=1"><script defer src="main.js"></script></head>
<link
rel="shortcut icon"
href="#"
/>
<meta
name="viewport"
content="width=device-width, initial-scale=1"
/>
<script
defer
src="main.js"
></script>
<!-- <script>
// It's best to inline this in `head` to avoid FOUC (flash of unstyled content) when changing pages or themes
if (
localStorage.getItem('color-theme') === 'dark' ||
(!('color-theme' in localStorage) &&
window.matchMedia('(prefers-color-scheme: dark)').matches)
) {
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark');
}
</script> -->
</head>
<body>
<div id="root"></div>
<script type="text/javascript" src="main.js"></script>
<script
type="text/javascript"
src="main.js"
></script>
</body>
</html>
</html>

View file

@ -19,14 +19,15 @@ const App = () => {
<Nav conversations={data} />
{/* <div className="flex h-full flex-1 flex-col md:pl-[260px]"> */}
<div className="flex h-full w-full flex-1 flex-col bg-gray-50 md:pl-[260px]">
{/* <main className="relative h-full w-full transition-width flex flex-col overflow-hidden items-stretch flex-1"> */}
<div className="relative h-full w-full transition-width flex flex-col overflow-hidden items-stretch flex-1">
<MobileNav />
<Messages messages={messages} />
<TextChat
messages={messages}
reloadConvos={mutate}
/>
{/* </main> */}
</div>
</div>
</div>
);

View file

@ -1,5 +1,4 @@
import React from 'react';
import NavLink from './NavLink';
import TrashIcon from '../svg/TrashIcon';
import manualSWR from '~/utils/fetchers';
import { useDispatch } from 'react-redux';

View file

@ -0,0 +1,19 @@
import React, { useState, useContext } from 'react';
import DarkModeIcon from '../svg/DarkModeIcon';
import { ThemeContext } from '~/hooks/ThemeContext';
export default function DarkMode() {
const { theme, setTheme } = useContext(ThemeContext);
const clickHandler = () => setTheme(theme === 'dark' ? 'light' : 'dark');
return (
<a
className="flex cursor-pointer items-center gap-3 rounded-md py-3 px-3 text-sm text-white transition-colors duration-200 hover:bg-gray-500/10"
onClick={clickHandler}
>
<DarkModeIcon />
Dark mode
</a>
);
}

View file

@ -1,17 +1,14 @@
import React from 'react';
import ClearConvos from './ClearConvos';
import NavLink from './NavLink';
import DarkModeIcon from '../svg/DarkModeIcon';
import LogOutIcon from '../svg/LogOutIcon';
import ClearConvos from './ClearConvos';
import DarkMode from './DarkMode';
export default function NavLinks() {
return (
<>
<ClearConvos />
<NavLink
svg={DarkModeIcon}
text="Dark mode"
/>
<DarkMode />
<NavLink
svg={LogOutIcon}
text="Log out"

View file

@ -5,12 +5,12 @@ export default function Message({ sender, text, last = false, error = false }) {
const { isSubmitting } = useSelector((state) => state.submit);
const props = {
className:
'group w-full border-b border-black/10 text-gray-800 dark:border-gray-900/50 dark:bg-gray-800 dark:text-gray-100'
'w-full border-b border-black/10 dark:border-gray-900/50 text-gray-800 dark:text-gray-100 group dark:bg-gray-800'
};
if (sender === 'GPT') {
props.className =
'group w-full border-b border-black/10 bg-gray-100 text-gray-800 dark:border-gray-900/50 dark:bg-[#444654] dark:text-gray-100';
'w-full border-b border-black/10 dark:border-gray-900/50 text-gray-800 dark:text-gray-100 group bg-gray-50 dark:bg-[#444654]';
}
return (

View file

@ -3,10 +3,9 @@ import Message from './Message';
import Landing from './Landing';
export default function Messages({ messages }) {
if (messages.length === 0) {
return <Landing />
};
return <Landing />;
}
const messagesEndRef = useRef(null);
@ -25,17 +24,22 @@ export default function Messages({ messages }) {
// </div>
// <div className="flex h-full text-sm dark:bg-gray-800"></div>;
return (
<div className="flex-1 overflow-y-auto ">
{messages.map((message, i) => (
<Message
key={i}
sender={message.sender}
text={message.text}
last={i === messages.length - 1}
error={!!message.error ? true : false}
/>
))}
<div ref={messagesEndRef} />
// <div className="flex-1 overflow-y-auto ">
<div className="flex-1 overflow-hidden">
<div className="h-full dark:bg-gray-800">
<div className="flex h-full flex-col items-center text-sm dark:bg-gray-800">
{messages.map((message, i) => (
<Message
key={i}
sender={message.sender}
text={message.text}
last={i === messages.length - 1}
error={!!message.error ? true : false}
/>
))}
<div ref={messagesEndRef} />
</div>
</div>
</div>
);
}

View file

@ -36,11 +36,11 @@ export default function TextChat({ messages, reloadConvos }) {
dispatch(setSubmitState(false));
};
const errorHandler = (data) => {
console.log('Error:', data);
const errorHandler = (event) => {
console.log('Error:', event);
const errorResponse = {
...initialResponse,
text: 'An error occurred. Please try again in a few moments.',
text: `An error occurred. Please try again in a few moments.\n\nError message: ${event.data}`,
error: true
};
dispatch(setSubmitState(false));
@ -80,7 +80,7 @@ export default function TextChat({ messages, reloadConvos }) {
};
return (
<div className="md:bg-vert-light-gradient dark:md:bg-vert-dark-gradient w-full border-t bg-white dark:border-white/20 dark:bg-gray-800 md:border-t-0 md:border-transparent md:!bg-transparent md:dark:border-transparent">
<div className="md:bg-vert-light-gradient dark:md:bg-vert-dark-gradient absolute bottom-0 left-0 w-full border-t bg-white dark:border-white/20 dark:bg-gray-800 md:border-t-0 md:border-transparent md:!bg-transparent md:dark:border-transparent">
<form className="stretch mx-2 flex flex-row gap-3 pt-2 last:mb-2 md:last:mb-6 lg:mx-auto lg:max-w-3xl lg:pt-6">
<div className="relative flex h-full flex-1 md:flex-col">
<div className="ml-1 mt-1.5 flex justify-center gap-0 md:m-auto md:mb-2 md:w-full md:gap-2" />

45
src/hooks/ThemeContext.js Normal file
View file

@ -0,0 +1,45 @@
//ThemeContext.js
import React, { createContext, useState, useEffect } from 'react';
const getInitialTheme = () => {
if (typeof window !== 'undefined' && window.localStorage) {
const storedPrefs = window.localStorage.getItem('color-theme');
if (typeof storedPrefs === 'string') {
return storedPrefs;
}
const userMedia = window.matchMedia('(prefers-color-scheme: dark)');
if (userMedia.matches) {
return 'dark';
}
}
return 'light'; // light theme as the default;
};
export const ThemeContext = createContext();
export const ThemeProvider = ({ initialTheme, children }) => {
const [theme, setTheme] = useState(getInitialTheme);
const rawSetTheme = (rawTheme) => {
const root = window.document.documentElement;
const isDark = rawTheme === 'dark';
root.classList.remove(isDark ? 'light' : 'dark');
root.classList.add(rawTheme);
localStorage.setItem('color-theme', rawTheme);
};
if (initialTheme) {
rawSetTheme(initialTheme);
}
useEffect(() => {
rawSetTheme(theme);
}, [theme]);
return <ThemeContext.Provider value={{ theme, setTheme }}>{children}</ThemeContext.Provider>;
};

View file

@ -38,7 +38,7 @@ export default function handleSubmit({
};
events.onerror = function (e) {
console.log(e, 'error in opening conn.');
console.log('error in opening conn.');
events.close();
errorHandler(e);
};

View file

@ -1,8 +1,10 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{js,jsx,ts,tsx}'],
darkMode: 'class',
theme: {
extend: {}
},
// plugins: [require('flowbite/plugin')]
plugins: []
};