Skip to content

Commit

Permalink
status pages, flashcards (#35)
Browse files Browse the repository at this point in the history
* Quiz Layour applied, svgs added with wrong z-indexes

* flashcards route

* Control bar arrows and jotai state for quizes set up

* GetQuizData custom hook integrated with atoms

* dynamic Flashcards page setup

* Styled arrows for control bar (no server)

* Flashcard and control bar jotai implementation

* Flashcards page functionalities, name and length atoms

* loading, error, 401, 404 pages
  • Loading branch information
SzymonBudziakk authored Jan 22, 2024
1 parent 7afe77b commit 2778716
Show file tree
Hide file tree
Showing 32 changed files with 556 additions and 174 deletions.
39 changes: 32 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"dependencies": {
"@fvilers/disable-react-devtools": "^1.3.0",
"@hookform/resolvers": "^3.3.4",
"@tanstack/query-core": "^5.17.10",
"@tanstack/react-query": "^5.17.9",
"@tanstack/react-query-devtools": "^5.17.9",
"axios": "^1.6.5",
Expand All @@ -24,7 +25,9 @@
"react-hook-form": "^7.49.2",
"react-hot-toast": "^2.4.1",
"react-router-dom": "^6.21.1",
"react-spinners": "^0.13.8",
"tailwind-merge": "^2.2.0",
"wonka": "^6.3.4",
"zod": "^3.22.4"
},
"devDependencies": {
Expand All @@ -46,4 +49,4 @@
"typescript": "^5.3.3",
"vite": "^5.0.11"
}
}
}
59 changes: 59 additions & 0 deletions src/atoms/quiz.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { api } from "@/api/axios";
import { QuizResponse } from "@/api/types/quiz";
import { atom } from "jotai";
import { atomWithQuery } from "jotai-tanstack-query";

interface updateParamsAtom {
newName: string | undefined;
newSlug: string | undefined;
}

interface updateCurrTermProps {
value: number;
length: number;
}

export const userNameAtom = atom<string | undefined>("");
export const quizSlugAtom = atom<string | undefined>("");
export const currTermAtom = atom<number>(0);

export const quizNameAtom = atom<string>(
get => get(quizAtom).data?.data.name ?? "Go Back"
);

export const quizLengthAtom = atom<number>(
get => get(quizAtom).data?.data.questions.length ?? 0
);

export const quizAtom = atomWithQuery(get => ({
queryKey: ["quiz", get(userNameAtom), get(quizSlugAtom)],
queryFn: () =>
api.get<QuizResponse>(
`/api/v1/Quiz/${get(userNameAtom)}/${get(quizSlugAtom)}`
),
}));

export const updateParamsAtom = atom(
null,
(get, set, { newName, newSlug }: updateParamsAtom) => {
if (newName !== get(userNameAtom) || newSlug !== get(quizSlugAtom)) {
set(userNameAtom, newName);
set(quizSlugAtom, newSlug);
set(currTermAtom, 0);
}
}
);

export const updateCurrTermAtom = atom(
null,
(get, set, { value, length }: updateCurrTermProps) => {
const prev = get(currTermAtom);
value > 0
? prev === length - 1
? set(currTermAtom, 0)
: set(currTermAtom, prev + 1)
: prev === 0
? set(currTermAtom, length - 1)
: set(currTermAtom, prev - 1);
}
);
23 changes: 19 additions & 4 deletions src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ import Verified from "./pages/Auth/Verified";
import Home from "./pages/Home/Home";
import PersistLogin from "./router/PersistLogin";
import Flashcards from "./pages/Quiz/Flashcards/Flashcards";
import NotFound from "./pages/Status/NotFound";
import NotFound from "./pages/Status/NotFound/NotFound";
import QuizLayout from "./layout/QuizLayout";
import Error from "./pages/Status/Error";
import Loading from "./pages/Status/Loading";
import Unauthorized from "./pages/Status/Unauthorized";

export default function App() {
return (
Expand All @@ -32,10 +36,21 @@ export default function App() {

<Route path="/:userName/:quizSlug" element={<Quiz />} />

<Route path="*" element={<NotFound />} />
{/* <Route path="*" element={<NotFound />} /> */}
<Route path="/error" element={<Error />} />
<Route path="/notfound" element={<NotFound />} />
<Route path="/loading" element={<Loading />} />
<Route path="/unauthorized" element={<Unauthorized />} />
</Route>

<Route path="/" element={<QuizLayout />}>
<Route path="/flashcards" element={<Flashcards />} />
<Route
path="/:userName/:quizSlug/flashcards"
element={<Flashcards />}
/>
<Route path="/test" element={<Test />} />
</Route>
<Route path="/flashcards" element={<Flashcards />} />
<Route path="/test" element={<Test />} />
</Route>
</Routes>
);
Expand Down
12 changes: 12 additions & 0 deletions src/components/layout/Background/Background.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Left from "./Left";
import Right from "./Right";

export default function Background() {
return (
<>
<div className="absolute top-0 w-full h-full bg-primary z-[-100]" />
<Right />
<Left />
</>
);
}
31 changes: 31 additions & 0 deletions src/components/layout/Background/Left.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
export default function Left() {
return (
<svg
width="287"
height="254"
viewBox="0 0 287 254"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="absolute z-10 left-0 top-[50vh]"
>
<path
opacity="0.1"
d="M286.5 0.5L-14.5 254.5V69.5L286.5 0.5Z"
fill="url(#paint0_linear_111:578)"
></path>
<defs>
<linearGradient
id="paint0_linear_111:578"
x1="-40.5"
y1="117"
x2="301.926"
y2="-97.1485"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#4A6CF7"></stop>
<stop offset="1" stopColor="#4A6CF7" stopOpacity="0"></stop>
</linearGradient>
</defs>
</svg>
);
}
47 changes: 47 additions & 0 deletions src/components/layout/Background/Right.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
export default function Right() {
return (
<svg
width="628"
height="258"
viewBox="0 0 628 258"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="absolute z-10 right-0 top-0"
>
<path
opacity="0.1"
d="M669.125 257.002L345.875 31.9983L524.571 -15.8832L669.125 257.002Z"
fill="url(#paint0_linear_0:1)"
></path>
<path
opacity="0.1"
d="M0.0716344 182.78L101.988 -15.0769L142.154 81.4093L0.0716344 182.78Z"
fill="url(#paint1_linear_0:1)"
></path>
<defs>
<linearGradient
id="paint0_linear_0:1"
x1="644"
y1="221"
x2="429.946"
y2="37.0429"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#4A6CF7"></stop>
<stop offset="1" stopColor="#4A6CF7" stopOpacity="0"></stop>
</linearGradient>
<linearGradient
id="paint1_linear_0:1"
x1="18.3648"
y1="166.016"
x2="105.377"
y2="32.3398"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#4A6CF7"></stop>
<stop offset="1" stopColor="#4A6CF7" stopOpacity="0"></stop>
</linearGradient>
</defs>
</svg>
);
}
21 changes: 12 additions & 9 deletions src/components/layout/Header/QuizHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
import MainLogo from "@/assets/images/light.png";
import { X } from "lucide-react";
import { Link } from "react-router-dom";
import { Link, useNavigate } from "react-router-dom";
import DarkModeButton from "./DarkModeButton";
import Logo from "./Logo";
import { useAtomValue } from "jotai";
import { quizNameAtom } from "@/atoms/quiz";

interface QuizHeaderProps {
name: string;
}
export default function QuizHeader() {
const navigate = useNavigate();
const name = useAtomValue(quizNameAtom);

export default function QuizHeader({ name }: QuizHeaderProps) {
return (
<nav className="bg-primary text-white top-0 w-full z-10 font-primary">
<div className="grid grid-cols-2 sm:grid-cols-3 gap-2 container mx-auto px-4 sm:px-6 py-2 sm:py-3 lg:py-4 xl:px-8 2xl:px-12">
<div className="grid grid-cols-2 sm:grid-cols-3 gap-2 container mx-auto px-4 sm:px-6 py-2 sm:py-3 lg:py-4 xl:px-8 2xl:px-12 z-50">
<div className="col-start-1 flex items-center">
<Logo logo={MainLogo} />
</div>
<div className="hidden sm:flex sm:items-center sm:justify-center sm:col-start-2">
<p className="textHover hidden sm:block text-lg font-semibold md:text-xl xl:text-2xl">
{name}
<p className="textHover hidden sm:block text-lg font-semibold md:text-xl xl:text-2xl z-50">
<button onClick={() => navigate(-1)}>{name}</button>
</p>
</div>

<div className="col-start-2 sm:col-start-3 flex items-center ml-auto">
<DarkModeButton />
<Link to="/quiz" className="flex pl-3">
<X className="w-10 h-10" />
<button onClick={() => navigate(-1)}>
<X className="w-10 h-10 z-50" />
</button>
</Link>
</div>
</div>
Expand Down
5 changes: 0 additions & 5 deletions src/components/layout/Other/FillHeight.tsx

This file was deleted.

4 changes: 3 additions & 1 deletion src/components/layout/QuizLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { Toaster } from "react-hot-toast";
import { Outlet } from "react-router-dom";
import QuizHeader from "./Header/QuizHeader";
// import Background from "./Background/Background";

export default function QuizLayout() {
return (
<>
<Toaster />
<QuizHeader name="Test" />
<QuizHeader />
{/* <Background /> */}
<Outlet />
</>
);
Expand Down
Loading

0 comments on commit 2778716

Please sign in to comment.