From 77c1fcfbdee98c399e4f5b19bdcef5db468b0562 Mon Sep 17 00:00:00 2001 From: Visakh Vijayan Date: Sat, 25 May 2024 13:21:07 +0530 Subject: [PATCH 1/5] added react router --- package-lock.json | 42 +++++++++++++++++++++++++++++++++++ package.json | 1 + src/App.tsx | 47 ++++++++++++++++++++++++---------------- src/index.css | 1 + src/pages/Categories.tsx | 7 ++++++ src/pages/Login.tsx | 7 ++++++ src/pages/NotFound.tsx | 7 ++++++ src/pages/index.ts | 5 +++++ 8 files changed, 98 insertions(+), 19 deletions(-) create mode 100644 src/pages/Categories.tsx create mode 100644 src/pages/Login.tsx create mode 100644 src/pages/NotFound.tsx create mode 100644 src/pages/index.ts diff --git a/package-lock.json b/package-lock.json index 53cde67..c108b82 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "eslint": "^8.57.0", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.6", + "react-router-dom": "^6.23.1", "tailwindcss": "^3.4.3", "typescript": "^5.2.2", "vite": "^5.2.0" @@ -1092,6 +1093,15 @@ "node": ">=14" } }, + "node_modules/@remix-run/router": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.16.1.tgz", + "integrity": "sha512-es2g3dq6Nb07iFxGk5GuHN20RwBZOsuDQN7izWIisUcv9r+d2C5jQxqmgkdebXgReWfiyUabcki6Fg77mSNrig==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.17.2", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz", @@ -3435,6 +3445,38 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "6.23.1", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.23.1.tgz", + "integrity": "sha512-fzcOaRF69uvqbbM7OhvQyBTFDVrrGlsFdS3AL+1KfIBtGETibHzi3FkoTRyiDJnWNc2VxrfvR+657ROHjaNjqQ==", + "dev": true, + "dependencies": { + "@remix-run/router": "1.16.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.23.1", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.23.1.tgz", + "integrity": "sha512-utP+K+aSTtEdbWpC+4gxhdlPFwuEfDKq8ZrPFU65bbRJY+l706qjR7yaidBpo3MSeA/fzwbXWbKBI6ftOnP3OQ==", + "dev": true, + "dependencies": { + "@remix-run/router": "1.16.1", + "react-router": "6.23.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", diff --git a/package.json b/package.json index 362b2dd..99ad920 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "eslint": "^8.57.0", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.6", + "react-router-dom": "^6.23.1", "tailwindcss": "^3.4.3", "typescript": "^5.2.2", "vite": "^5.2.0" diff --git a/src/App.tsx b/src/App.tsx index a1b5998..2c42c6d 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,27 +1,36 @@ import "./App.css"; -import BrainIcon from './assets/brain_ai.svg'; +// import BrainIcon from './assets/brain_ai.svg'; +import { BrowserRouter, Routes, Route } from 'react-router-dom'; +import { Categories, Login, NotFound } from "./pages"; -import { Coin, Header, Hero, Logo, Trivia } from "./components/index"; +// import { Coin, Header, Hero, Logo, Trivia } from "./components/index"; function App() { return ( -
-
-
- - -
-
- -
- -  trivia.ai -
-
-
- -
-
+ + + } /> + } /> + } /> + + + //
+ //
+ //
+ // + // + //
+ //
+ // + //
+ // + //  trivia.ai + //
+ //
+ //
+ // + //
+ //
); } diff --git a/src/index.css b/src/index.css index 29a2ea2..d4ea29a 100644 --- a/src/index.css +++ b/src/index.css @@ -33,6 +33,7 @@ body { min-width: 320px; min-height: 100vh; background-color: white; + color: black; } h1 { diff --git a/src/pages/Categories.tsx b/src/pages/Categories.tsx new file mode 100644 index 0000000..d6d72ca --- /dev/null +++ b/src/pages/Categories.tsx @@ -0,0 +1,7 @@ +import React from 'react'; + +const Categories: React.FC = () => { + return
Categories
; +}; + +export default Categories; \ No newline at end of file diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx new file mode 100644 index 0000000..654f782 --- /dev/null +++ b/src/pages/Login.tsx @@ -0,0 +1,7 @@ +import React from 'react'; + +const Login: React.FC = () => { + return
Login
; +}; + +export default Login; \ No newline at end of file diff --git a/src/pages/NotFound.tsx b/src/pages/NotFound.tsx new file mode 100644 index 0000000..85c52ac --- /dev/null +++ b/src/pages/NotFound.tsx @@ -0,0 +1,7 @@ +import React from 'react'; + +const NotFound: React.FC = () => { + return
NotFound
; +}; + +export default NotFound; \ No newline at end of file diff --git a/src/pages/index.ts b/src/pages/index.ts new file mode 100644 index 0000000..e9da888 --- /dev/null +++ b/src/pages/index.ts @@ -0,0 +1,5 @@ +import Categories from "./Categories"; +import Login from "./Login"; +import NotFound from "./NotFound"; + +export { Categories, Login, NotFound }; \ No newline at end of file From 01885616126c8f3a6d91d68222e7c7c120ac744e Mon Sep 17 00:00:00 2001 From: Visakh Vijayan Date: Sat, 25 May 2024 19:57:48 +0530 Subject: [PATCH 2/5] added categories page --- .eslintrc.cjs | 1 + src/assets/index.ts | 3 + src/components/auth0-login-button/index.tsx | 8 ++- src/components/logo/index.tsx | 14 ++++- src/index.css | 2 - src/pages/Categories.tsx | 63 ++++++++++++++++++++- src/pages/Login.tsx | 27 ++++++++- src/services/gemini.ts | 43 ++++++++++++++ 8 files changed, 150 insertions(+), 11 deletions(-) create mode 100644 src/assets/index.ts diff --git a/.eslintrc.cjs b/.eslintrc.cjs index d6c9537..c629ac6 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -10,6 +10,7 @@ module.exports = { parser: '@typescript-eslint/parser', plugins: ['react-refresh'], rules: { + 'react-hooks/exhaustive-deps': 'off', 'react-refresh/only-export-components': [ 'warn', { allowConstantExport: true }, diff --git a/src/assets/index.ts b/src/assets/index.ts new file mode 100644 index 0000000..9cf2bd5 --- /dev/null +++ b/src/assets/index.ts @@ -0,0 +1,3 @@ +import BrainIcon from './brain_ai.svg'; + +export { BrainIcon }; diff --git a/src/components/auth0-login-button/index.tsx b/src/components/auth0-login-button/index.tsx index ff1ae20..09ad925 100644 --- a/src/components/auth0-login-button/index.tsx +++ b/src/components/auth0-login-button/index.tsx @@ -21,8 +21,12 @@ const Auth0LoginButton: React.FC = ({ onLogin }) => { return (
-
); diff --git a/src/components/logo/index.tsx b/src/components/logo/index.tsx index ccf5b22..19ce869 100644 --- a/src/components/logo/index.tsx +++ b/src/components/logo/index.tsx @@ -1,7 +1,19 @@ import React from "react"; +import { BrainIcon } from "../../assets"; const Logo: React.FC = () => { - return
; + return ( +
+ +
+
+ +  trivia.ai + + Discover Smart, Fun, Endless Knowledge +
+
+ ); }; export default Logo; diff --git a/src/index.css b/src/index.css index d4ea29a..78efb4e 100644 --- a/src/index.css +++ b/src/index.css @@ -44,11 +44,9 @@ h1 { button { border-radius: 8px; border: 1px solid transparent; - padding: 0.6em 1.2em; font-size: 1em; font-weight: 500; font-family: inherit; - background-color: #1a1a1a; cursor: pointer; transition: border-color 0.25s; } diff --git a/src/pages/Categories.tsx b/src/pages/Categories.tsx index d6d72ca..a3f153e 100644 --- a/src/pages/Categories.tsx +++ b/src/pages/Categories.tsx @@ -1,7 +1,64 @@ -import React from 'react'; +import React, { useEffect, useState } from "react"; +import { getTriviaCategoriesFromGemini } from "../services/gemini"; const Categories: React.FC = () => { - return
Categories
; + const [categories, setCategories] = useState( + (JSON.parse(localStorage.getItem("categories") as string) as string[]) || [] + ); + const [selectedCategories, setSelectedCategories] = useState([]); + + useEffect(() => { + if (!categories.length) { + getTriviaCategoriesFromGemini().then((result) => { + localStorage.setItem("categories", JSON.stringify(result)); + setCategories(result.sort()); + }); + } + }, []); + + const onClickCategory = (category: string) => { + if (!selectedCategories.includes(category)) { + setSelectedCategories([...selectedCategories, category]); + } else { + setSelectedCategories( + selectedCategories.filter((_category) => _category !== category) + ); + } + }; + + return ( +
+ Categories + Choose the one(s) you think you are good at +
+ {categories.map((category, _index) => { + return ( + + ); + })} +
+
+ +
+
+ ); }; -export default Categories; \ No newline at end of file +export default Categories; diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx index 654f782..db2d7c4 100644 --- a/src/pages/Login.tsx +++ b/src/pages/Login.tsx @@ -1,7 +1,28 @@ -import React from 'react'; +import React, { useEffect } from "react"; +import { Auth0LoginButton, Logo } from "../components"; +import { useNavigate } from "react-router-dom"; +import { useAuth0 } from "@auth0/auth0-react"; const Login: React.FC = () => { - return
Login
; + const navigate = useNavigate(); + const { isAuthenticated } = useAuth0(); + + const onLogin = () => { + navigate("/categories"); + }; + + useEffect(() => { + if (isAuthenticated) { + navigate("/categories"); + } + }, []); + + return ( +
+ + +
+ ); }; -export default Login; \ No newline at end of file +export default Login; diff --git a/src/services/gemini.ts b/src/services/gemini.ts index aaa097e..f396b31 100644 --- a/src/services/gemini.ts +++ b/src/services/gemini.ts @@ -46,3 +46,46 @@ export const getTriviaFromGemini = async (): Promise => { const response = result.response; return JSON.parse(response.text().replace(/^```json|```$/g, '')) as Trivia; }; + +export const getTriviaCategoriesFromGemini = async (): Promise => { + const genAI = new GoogleGenerativeAI(API_KEY); + const model = genAI.getGenerativeModel({ model: MODEL_NAME }); + + const generationConfig = { + temperature: 0.9, + topK: 1, + topP: 1, + maxOutputTokens: 2048, + }; + + const safetySettings = [ + { + category: HarmCategory.HARM_CATEGORY_HARASSMENT, + threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE, + }, + { + category: HarmCategory.HARM_CATEGORY_HATE_SPEECH, + threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE, + }, + { + category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT, + threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE, + }, + { + category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, + threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE, + }, + ]; + + const chat = await model.startChat({ + generationConfig, + safetySettings, + }); + + const result = await chat.sendMessage( + "Give me a list of 20 trivia categories as an array of strings", + ); + + const response = result.response; + return JSON.parse(response.text().replace(/^```json|```$/g, '')) as string[]; +} From f4f550a3715d58af27fcb73b2f0a40e044572752 Mon Sep 17 00:00:00 2001 From: Visakh Vijayan Date: Sat, 25 May 2024 20:06:48 +0530 Subject: [PATCH 3/5] fix for categories not sorted --- src/pages/Categories.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pages/Categories.tsx b/src/pages/Categories.tsx index a3f153e..d53f0d1 100644 --- a/src/pages/Categories.tsx +++ b/src/pages/Categories.tsx @@ -10,8 +10,10 @@ const Categories: React.FC = () => { useEffect(() => { if (!categories.length) { getTriviaCategoriesFromGemini().then((result) => { - localStorage.setItem("categories", JSON.stringify(result)); - setCategories(result.sort()); + const sortedResults = result.sort(); + + localStorage.setItem("categories", JSON.stringify(sortedResults)); + setCategories(sortedResults); }); } }, []); From fabfa31cb18610634f1d23ff174dfcf87948bb6c Mon Sep 17 00:00:00 2001 From: Visakh Vijayan Date: Sat, 25 May 2024 22:11:35 +0530 Subject: [PATCH 4/5] added trivia page --- src/App.tsx | 7 ++- src/components/trivia/index.tsx | 10 ++-- src/index.css | 3 - src/pages/Categories.tsx | 32 ++++++++-- src/pages/Trivia.tsx | 103 ++++++++++++++++++++++++++++++++ src/pages/index.ts | 3 +- src/services/gemini.ts | 14 +++-- 7 files changed, 151 insertions(+), 21 deletions(-) create mode 100644 src/pages/Trivia.tsx diff --git a/src/App.tsx b/src/App.tsx index 2c42c6d..64641cc 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,7 +1,7 @@ import "./App.css"; // import BrainIcon from './assets/brain_ai.svg'; -import { BrowserRouter, Routes, Route } from 'react-router-dom'; -import { Categories, Login, NotFound } from "./pages"; +import { BrowserRouter, Routes, Route } from "react-router-dom"; +import { Categories, Login, NotFound, Trivia } from "./pages"; // import { Coin, Header, Hero, Logo, Trivia } from "./components/index"; @@ -11,9 +11,10 @@ function App() { } /> } /> + } /> } /> - + //
//
//
diff --git a/src/components/trivia/index.tsx b/src/components/trivia/index.tsx index 117c69f..92744c7 100644 --- a/src/components/trivia/index.tsx +++ b/src/components/trivia/index.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react-hooks/exhaustive-deps */ import React, { useEffect, useState } from "react"; import { getTriviaFromGemini } from "../../services/gemini"; import Loader from "../loader"; @@ -71,15 +70,16 @@ const Trivia: React.FC = () => { onClick={() => onOptionClick(index)} key={index} disabled={isAttempted} - className={`p-4 text-white ${!isAttempted && "bg-black"} ${isAttempted && + className={`p-4 text-white ${!isAttempted && "bg-black"} ${ + isAttempted && (index === clickedOptionIndex ? clickedOptionIndex === correctOptionIndex ? "bg-green-500" : "bg-red-500" : index === correctOptionIndex - ? "bg-green-500" - : "") - }`} + ? "bg-green-500" + : "") + }`} > {option} diff --git a/src/index.css b/src/index.css index 78efb4e..5887508 100644 --- a/src/index.css +++ b/src/index.css @@ -66,7 +66,4 @@ button:focus-visible { a:hover { color: #747bff; } - button { - background-color: #f9f9f9; - } } diff --git a/src/pages/Categories.tsx b/src/pages/Categories.tsx index d53f0d1..3061550 100644 --- a/src/pages/Categories.tsx +++ b/src/pages/Categories.tsx @@ -1,5 +1,6 @@ import React, { useEffect, useState } from "react"; import { getTriviaCategoriesFromGemini } from "../services/gemini"; +import { useNavigate } from "react-router-dom"; const Categories: React.FC = () => { const [categories, setCategories] = useState( @@ -7,7 +8,12 @@ const Categories: React.FC = () => { ); const [selectedCategories, setSelectedCategories] = useState([]); + const navigate = useNavigate(); + useEffect(() => { + // So that selected categories are removed from cache. + localStorage.removeItem("selectedCategories"); + if (!categories.length) { getTriviaCategoriesFromGemini().then((result) => { const sortedResults = result.sort(); @@ -19,13 +25,26 @@ const Categories: React.FC = () => { }, []); const onClickCategory = (category: string) => { - if (!selectedCategories.includes(category)) { - setSelectedCategories([...selectedCategories, category]); + let _selectedCategories = selectedCategories; + + if (!_selectedCategories.includes(category)) { + _selectedCategories.push(category); } else { - setSelectedCategories( - selectedCategories.filter((_category) => _category !== category) + _selectedCategories = _selectedCategories.filter( + (_category) => _category !== category ); } + + localStorage.setItem( + "selectedCategories", + JSON.stringify(_selectedCategories) + ); + + setSelectedCategories([..._selectedCategories]); + }; + + const onGetStarted = () => { + navigate("/trivia"); }; return ( @@ -50,7 +69,10 @@ const Categories: React.FC = () => { })}
- + ))} +
+ {isAttempted && ( +
+
+

{data?.summary}

+
+
+ +
+
+ )} +
+ )} + + ); +}; + +export default Trivia; diff --git a/src/pages/index.ts b/src/pages/index.ts index e9da888..6dbcad0 100644 --- a/src/pages/index.ts +++ b/src/pages/index.ts @@ -1,5 +1,6 @@ import Categories from "./Categories"; import Login from "./Login"; import NotFound from "./NotFound"; +import Trivia from "./Trivia"; -export { Categories, Login, NotFound }; \ No newline at end of file +export { Categories, Login, NotFound, Trivia }; \ No newline at end of file diff --git a/src/services/gemini.ts b/src/services/gemini.ts index f396b31..c0e5de9 100644 --- a/src/services/gemini.ts +++ b/src/services/gemini.ts @@ -4,7 +4,7 @@ import { Trivia } from "../types"; const MODEL_NAME = "gemini-1.0-pro"; const API_KEY = import.meta.env.VITE_GEMINI_API_KEY; -export const getTriviaFromGemini = async (): Promise => { +export const getTriviaFromGemini = async (categories: string[] = []): Promise => { const genAI = new GoogleGenerativeAI(API_KEY); const model = genAI.getGenerativeModel({ model: MODEL_NAME }); @@ -39,9 +39,15 @@ export const getTriviaFromGemini = async (): Promise => { safetySettings, }); - const result = await chat.sendMessage( - "Give me a unique question with 4 options and one correct option and a medium summary about the correct option. The json should have keys question, options (array of strings with no option number), correctOption, summary and category", - ); + let message = ''; + + if (categories.length) { + message = `Give me a unique question that belongs to categories=${categories.join(',')} with 4 options and one correct option and a medium summary about the correct option. The json should have keys question, options (array of strings with no option number), correctOption, summary and category`; + } else { + message = `Give me a unique question with 4 options and one correct option and a medium summary about the correct option. The json should have keys question, options (array of strings with no option number), correctOption, summary and category`; + } + + const result = await chat.sendMessage(message); const response = result.response; return JSON.parse(response.text().replace(/^```json|```$/g, '')) as Trivia; From 7378bf338a07bc0aa15bef26fc44706d3b41ec68 Mon Sep 17 00:00:00 2001 From: Visakh Vijayan Date: Sun, 26 May 2024 01:10:42 +0530 Subject: [PATCH 5/5] final changes for the loading state --- src/App.tsx | 50 ++++----- src/components/app-header/index.tsx | 37 +++++++ src/components/auth0-login-button/index.tsx | 2 +- src/components/auth0-logout-button/index.tsx | 6 +- src/components/header/index.tsx | 2 +- src/components/index.ts | 4 +- src/components/loader/index.tsx | 2 +- src/index.css | 8 -- src/pages/Categories.tsx | 80 ++++++++------ src/pages/Login.tsx | 13 ++- src/pages/Trivia.tsx | 109 +++++++++++-------- src/services/gemini.ts | 4 +- 12 files changed, 195 insertions(+), 122 deletions(-) create mode 100644 src/components/app-header/index.tsx diff --git a/src/App.tsx b/src/App.tsx index 64641cc..fd40ac9 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,37 +1,35 @@ import "./App.css"; // import BrainIcon from './assets/brain_ai.svg'; -import { BrowserRouter, Routes, Route } from "react-router-dom"; +import { BrowserRouter, Routes, Route, Navigate } from "react-router-dom"; import { Categories, Login, NotFound, Trivia } from "./pages"; +import { useAuth0 } from "@auth0/auth0-react"; +import { Loader } from "./components"; // import { Coin, Header, Hero, Logo, Trivia } from "./components/index"; function App() { + const { isLoading, isAuthenticated } = useAuth0(); + return ( - - - } /> - } /> - } /> - } /> - - - //
- //
- //
- // - // - //
- //
- // - //
- // - //  trivia.ai - //
- //
- //
- // - //
- //
+ <> + {isLoading && } + {!isLoading && ( + + + } /> + : } + /> + : } + /> + } /> + + + )} + ); } diff --git a/src/components/app-header/index.tsx b/src/components/app-header/index.tsx new file mode 100644 index 0000000..a4639b4 --- /dev/null +++ b/src/components/app-header/index.tsx @@ -0,0 +1,37 @@ +import React from "react"; +import Header from "../header"; +import { BrainIcon } from "../../assets"; +import Auth0LogoutButton from "../auth0-logout-button"; +import { useNavigate } from "react-router-dom"; + +const AppHeader: React.FC = () => { + const navigate = useNavigate(); + + const onLogout = () => { + localStorage.clear(); + navigate("/"); + }; + + return ( +
+
+
+ navigate("/categories")} + className="border border-black rounded-full p-1 h-10 cursor-pointer" + src={BrainIcon} + /> +
+ trivia.ai + Endless Knowledge +
+
+
+ +
+
+
+ ); +}; + +export default AppHeader; diff --git a/src/components/auth0-login-button/index.tsx b/src/components/auth0-login-button/index.tsx index 09ad925..e8be7b4 100644 --- a/src/components/auth0-login-button/index.tsx +++ b/src/components/auth0-login-button/index.tsx @@ -22,7 +22,7 @@ const Auth0LoginButton: React.FC = ({ onLogin }) => { return (
diff --git a/src/components/header/index.tsx b/src/components/header/index.tsx index 9d528f5..5673ffa 100644 --- a/src/components/header/index.tsx +++ b/src/components/header/index.tsx @@ -2,7 +2,7 @@ import React, { PropsWithChildren } from "react"; const Header: React.FC = ({ children }) => { return ( -
+
{children}
); diff --git a/src/components/index.ts b/src/components/index.ts index 2939ef8..f08885b 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -1,3 +1,4 @@ +import AppHeader from "./app-header"; import Auth0LoginButton from "./auth0-login-button"; import Auth0LogoutButton from "./auth0-logout-button"; import Coin from "./coin"; @@ -7,4 +8,5 @@ import Loader from "./loader"; import Logo from "./logo"; import Trivia from "./trivia"; -export { Auth0LoginButton, Hero, Auth0LogoutButton, Trivia, Loader, Header, Coin, Logo }; + +export { Auth0LoginButton, Hero, Auth0LogoutButton, Trivia, Loader, Header, Coin, Logo, AppHeader }; diff --git a/src/components/loader/index.tsx b/src/components/loader/index.tsx index 0dd3c99..dc30dfe 100644 --- a/src/components/loader/index.tsx +++ b/src/components/loader/index.tsx @@ -6,7 +6,7 @@ const Loader: React.FC = () => {

- Getting the Next Question + Sit Tight! Loading

diff --git a/src/index.css b/src/index.css index 5887508..3c77058 100644 --- a/src/index.css +++ b/src/index.css @@ -43,20 +43,12 @@ h1 { button { border-radius: 8px; - border: 1px solid transparent; font-size: 1em; font-weight: 500; font-family: inherit; cursor: pointer; transition: border-color 0.25s; } -button:hover { - border-color: #646cff; -} -button:focus, -button:focus-visible { - outline: 4px auto -webkit-focus-ring-color; -} @media (prefers-color-scheme: light) { :root { diff --git a/src/pages/Categories.tsx b/src/pages/Categories.tsx index 3061550..3832caa 100644 --- a/src/pages/Categories.tsx +++ b/src/pages/Categories.tsx @@ -1,12 +1,14 @@ import React, { useEffect, useState } from "react"; import { getTriviaCategoriesFromGemini } from "../services/gemini"; import { useNavigate } from "react-router-dom"; +import { AppHeader, Loader } from "../components"; const Categories: React.FC = () => { const [categories, setCategories] = useState( (JSON.parse(localStorage.getItem("categories") as string) as string[]) || [] ); const [selectedCategories, setSelectedCategories] = useState([]); + const [isLoading, setIsLoading] = useState(false); const navigate = useNavigate(); @@ -15,11 +17,13 @@ const Categories: React.FC = () => { localStorage.removeItem("selectedCategories"); if (!categories.length) { + setIsLoading(true); getTriviaCategoriesFromGemini().then((result) => { const sortedResults = result.sort(); localStorage.setItem("categories", JSON.stringify(sortedResults)); setCategories(sortedResults); + setIsLoading(false); }); } }, []); @@ -48,40 +52,50 @@ const Categories: React.FC = () => { }; return ( -
- Categories - Choose the one(s) you think you are good at -
- {categories.map((category, _index) => { - return ( - - ); - })} + <> + +
+ Categories + + Pick Your Strengths and Showcase Your Knowledge + + {isLoading && } + {!isLoading && ( + <> +
+ {categories.map((category, _index) => { + return ( + + ); + })} +
+
+ +
+ + )}
-
- -
-
+ ); }; diff --git a/src/pages/Login.tsx b/src/pages/Login.tsx index db2d7c4..4210ed4 100644 --- a/src/pages/Login.tsx +++ b/src/pages/Login.tsx @@ -1,7 +1,8 @@ import React, { useEffect } from "react"; -import { Auth0LoginButton, Logo } from "../components"; +import { Auth0LoginButton } from "../components"; import { useNavigate } from "react-router-dom"; import { useAuth0 } from "@auth0/auth0-react"; +import { BrainIcon } from "../assets/index"; const Login: React.FC = () => { const navigate = useNavigate(); @@ -18,8 +19,14 @@ const Login: React.FC = () => { }, []); return ( -
- +
+ +
+ +  trivia.ai + + Discover Smart, Fun & Endless Knowledge +
); diff --git a/src/pages/Trivia.tsx b/src/pages/Trivia.tsx index 0a1b628..e0260b4 100644 --- a/src/pages/Trivia.tsx +++ b/src/pages/Trivia.tsx @@ -3,6 +3,7 @@ import Loader from "../components/loader/index"; import { useQuery } from "@tanstack/react-query"; import { useCoinContext } from "../context/coin"; import { getTriviaFromGemini } from "../services/gemini"; +import { AppHeader } from "../components"; const Trivia: React.FC = () => { const { isLoading, data, refetch, isRefetching } = useQuery({ @@ -47,56 +48,74 @@ const Trivia: React.FC = () => { }, [isLoading, isRefetching]); return ( -
- {(isLoading || isRefetching) && } - {!isLoading && !isRefetching && ( -
-
-

{data?.question}

-
-
- {data?.options?.map((option, index) => ( - - ))} -
- {isAttempted && ( + <> + +
+ {(isLoading || isRefetching) && } + {!isLoading && !isRefetching && ( +
+
+ + # + {data?.category + ?.toLowerCase() + .replace(/[^a-z]/g, "") + .split(" ") + .map((word, index) => + index === 0 + ? word + : word.charAt(0).toUpperCase() + word.slice(1) + ) + .join()} + +
-
-

{data?.summary}

-
-
+

{data?.question}

+
+
+ {data?.options?.map((option, index) => ( -
+ ))}
- )} -
- )} -
+ {isAttempted && ( +
+
+

{data?.summary}

+
+
+ +
+
+ )} +
+ )} +
+ ); }; diff --git a/src/services/gemini.ts b/src/services/gemini.ts index c0e5de9..cdb7878 100644 --- a/src/services/gemini.ts +++ b/src/services/gemini.ts @@ -42,7 +42,7 @@ export const getTriviaFromGemini = async (categories: string[] = []): Promise => { }); const result = await chat.sendMessage( - "Give me a list of 20 trivia categories as an array of strings", + "Give me a list of 15 trivia categories as an array of strings", ); const response = result.response;