enzostvs HF Staff commited on
Commit
05e89fd
·
1 Parent(s): 091969f

all logic for calculating the score + error + add delete/quest api

Browse files
app/api/[questId]/score/route.ts CHANGED
@@ -35,7 +35,7 @@ export async function POST(request: NextRequest, { params }: { params: { questId
35
  if (quest.prompt_id_correct !== promptId) {
36
  return Response.json({
37
  ok: false,
38
- message: "Wrong answer",
39
  }, { statusText: "Wrong answer", status: 400 });
40
  }
41
 
 
35
  if (quest.prompt_id_correct !== promptId) {
36
  return Response.json({
37
  ok: false,
38
+ resultId: quest.prompt_id_correct,
39
  }, { statusText: "Wrong answer", status: 400 });
40
  }
41
 
app/api/bulk-delete/route.ts ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { NextRequest } from "next/server";
2
+ import { PrismaClient } from '@prisma/client'
3
+
4
+ const prisma = new PrismaClient()
5
+
6
+ export async function DELETE(request: NextRequest) {
7
+ const total = await prisma.quest.deleteMany({
8
+ where: {
9
+ created_at: {
10
+ lt: new Date(Date.now() - 24 * 60 * 60 * 1000)
11
+ }
12
+ }
13
+ })
14
+
15
+ return Response.json({
16
+ ok: true,
17
+ message: `${total.count} quests deleted`
18
+ })
19
+ }
app/results/page.tsx ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import Link from "next/link";
2
+ import Image from "next/image";
3
+
4
+ import { Button } from "@/components/button/button";
5
+ import SparklingEffect from "@/assets/images/sparkles.svg";
6
+ import SparklingEffect2 from "@/assets/images/sparkles-2.svg";
7
+
8
+ export default function Home() {
9
+ return (
10
+ <div className="w-full min-h-screen mx-auto max-w-4xl relative flex items-center justify-center">
11
+ <div className="relative grid grid-cols-1 gap-8 py-12 px-6">
12
+ <h1 className="text-center text-5xl md:text-7xl font-extrabold bg-clip-text text-transparent bg-gradient-to-b from-white to-white/80 relative">
13
+ <Image
14
+ src={SparklingEffect}
15
+ width={30}
16
+ height={50}
17
+ alt="Sparkling effect"
18
+ className="absolute top-8 left-0 -translate-x-[calc(100%+1rem)]"
19
+ />
20
+ Here is your <br />
21
+ <span className="bg-gradient-to-tr from-green to-cyan bg-clip-text">
22
+ results
23
+ </span>{" "}
24
+ <Image
25
+ src={SparklingEffect2}
26
+ width={30}
27
+ height={50}
28
+ alt="Sparkling effect"
29
+ className="absolute -top-6 right-0 translate-x-[calc(100%+1rem)]"
30
+ />
31
+ </h1>
32
+ <h2 className="text-white text-xl md:text-2xl text-center font-light">
33
+ Congrats!
34
+ </h2>
35
+ <div className="w-full mx-auto flex items-center gap-6">
36
+ <Button theme="primary" className="mx-auto">
37
+ Share on LinkedIn
38
+ </Button>
39
+ <Button theme="primary" className="mx-auto">
40
+ Share on X
41
+ </Button>
42
+ </div>
43
+ <div className="absolute top-1/2 left-1/2 will-transform -translate-x-1/2 -translate-y-1/2 bg-gradient-to-br from-green to-cyan blur-[120px] md:blur-[140px] w-full h-full max-h-[250px] rounded-full z-[-1] opacity-40"></div>
44
+ </div>
45
+ </div>
46
+ );
47
+ }
components/quizz/card/error.tsx ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import classNames from "classnames";
2
+ import { IoCloseSharp } from "react-icons/io5";
3
+
4
+ export const Error = ({
5
+ result,
6
+ prompt,
7
+ }: {
8
+ result: { success: boolean; id: null | string } | null | undefined;
9
+ prompt: { id: string };
10
+ }) => {
11
+ return (
12
+ <div
13
+ className={classNames(
14
+ "absolute bottom-0 w-full left-0 px-8 pb-8 flex justify-start items-center transition-all duration-200 opacity-0 pointer-events-none translate-y-full",
15
+ {
16
+ "!opacity-100 !pointer-events-auto !translate-y-0":
17
+ result && !result?.success && result?.id !== prompt.id,
18
+ }
19
+ )}
20
+ >
21
+ <div className="font-extrabold text-white text-3xl flex items-center justify-center transition-all duration-200 w-10 h-10 rounded-full bg-red-500">
22
+ <IoCloseSharp />
23
+ </div>
24
+ </div>
25
+ );
26
+ };
components/quizz/{card.tsx → card/index.tsx} RENAMED
@@ -3,53 +3,35 @@ import Image from "next/image";
3
  import Confetti from "react-confetti";
4
 
5
  import { PromptType } from "@/utils/type";
6
- import { useQuizz } from "./hooks/useQuizz";
7
  import classNames from "classnames";
 
 
 
8
 
9
  interface Props {
10
  prompt: PromptType;
11
  }
12
 
13
  export const Card: React.FC<Props> = ({ prompt }) => {
14
- const { onScore, success } = useQuizz();
15
 
16
  return (
17
  <div
18
  className={classNames(
19
  "w-[340px] h-[340px] p-5 relative z-[1] cursor-pointer group",
20
  {
21
- "!cursor-not-allowed": success,
22
  }
23
  )}
24
- onClick={success ? () => {} : async () => await onScore(prompt.id)}
 
 
25
  >
26
- <div
27
- className={classNames(
28
- "absolute bottom-0 w-full left-0 px-0 py-0 flex justify-between items-center translate-y-10 transition-all duration-200",
29
- {
30
- "opacity-0 pointer-events-none": success !== prompt.id,
31
- }
32
- )}
33
- >
34
- <p
35
- className={classNames("text-[90px] transition-all duration-200", {
36
- "-translate-x-1/2 translate-y-1/2": success !== prompt.id,
37
- })}
38
- >
39
- 🎉
40
- </p>
41
- <p
42
- className={classNames(
43
- "font-extrabold text-white text-7xl pr-6 pb-10 transition-all duration-200",
44
- {
45
- "translate-y-full": success !== prompt.id,
46
- }
47
- )}
48
- >
49
- +1
50
- </p>
51
- </div>
52
- {success === prompt.id && (
53
  <Confetti width={340} height={340} numberOfPieces={100} />
54
  )}
55
  <Image
@@ -61,8 +43,11 @@ export const Card: React.FC<Props> = ({ prompt }) => {
61
  "object-center object-cover w-full h-full select-none hover:ring-4 ring-white transition-all duration-100",
62
  {
63
  "ring-4 !ring-[#E5AC00] hover:ring-[#E5AC00]":
64
- success === prompt.id,
65
- "!ring-transparent": success && success !== prompt.id,
 
 
 
66
  }
67
  )}
68
  />
@@ -70,7 +55,7 @@ export const Card: React.FC<Props> = ({ prompt }) => {
70
  className={classNames(
71
  "w-full h-full blur-md lg:blur-md top-0 left-0 absolute z-[-1] opacity-20 transition-all duration-200",
72
  {
73
- "group-hover:opacity-40": !success,
74
  }
75
  )}
76
  style={{
 
3
  import Confetti from "react-confetti";
4
 
5
  import { PromptType } from "@/utils/type";
6
+ import { useQuizz } from "@/components/quizz/hooks/useQuizz";
7
  import classNames from "classnames";
8
+ import { Success } from "./success";
9
+ import { Error } from "./error";
10
+ import { Valid } from "./valid";
11
 
12
  interface Props {
13
  prompt: PromptType;
14
  }
15
 
16
  export const Card: React.FC<Props> = ({ prompt }) => {
17
+ const { onScore, result } = useQuizz();
18
 
19
  return (
20
  <div
21
  className={classNames(
22
  "w-[340px] h-[340px] p-5 relative z-[1] cursor-pointer group",
23
  {
24
+ "!cursor-not-allowed": result?.success,
25
  }
26
  )}
27
+ onClick={
28
+ result?.success ? () => {} : async () => await onScore(prompt.id)
29
+ }
30
  >
31
+ <Success result={result} prompt={prompt} />
32
+ <Error result={result} prompt={prompt} />
33
+ <Valid result={result} prompt={prompt} />
34
+ {result?.success && result?.id === prompt.id && (
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  <Confetti width={340} height={340} numberOfPieces={100} />
36
  )}
37
  <Image
 
43
  "object-center object-cover w-full h-full select-none hover:ring-4 ring-white transition-all duration-100",
44
  {
45
  "ring-4 !ring-[#E5AC00] hover:ring-[#E5AC00]":
46
+ result?.success && result?.id === prompt.id,
47
+ "!ring-transparent": result?.success && result?.id !== prompt.id,
48
+ "!ring-red-500 ring-4":
49
+ result && !result?.success && result?.id !== prompt.id,
50
+ "!ring-green ring-4": !result?.success && result?.id === prompt.id,
51
  }
52
  )}
53
  />
 
55
  className={classNames(
56
  "w-full h-full blur-md lg:blur-md top-0 left-0 absolute z-[-1] opacity-20 transition-all duration-200",
57
  {
58
+ "group-hover:opacity-40": !result,
59
  }
60
  )}
61
  style={{
components/quizz/card/success.tsx ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import classNames from "classnames";
2
+
3
+ export const Success = ({
4
+ result,
5
+ prompt,
6
+ }: {
7
+ result: { success: boolean; id: null | string } | null | undefined;
8
+ prompt: { id: string };
9
+ }) => {
10
+ return (
11
+ <div
12
+ className={classNames(
13
+ "absolute bottom-0 w-full left-0 px-0 py-0 flex justify-between items-center translate-y-10 transition-all duration-200",
14
+ {
15
+ "opacity-0 pointer-events-none":
16
+ !result?.success || result?.id !== prompt.id,
17
+ }
18
+ )}
19
+ >
20
+ <p
21
+ className={classNames("text-[90px] transition-all duration-200", {
22
+ "-translate-x-1/2 translate-y-1/2": result?.id !== prompt.id,
23
+ })}
24
+ >
25
+ 🎉
26
+ </p>
27
+ <p
28
+ className={classNames(
29
+ "font-extrabold text-white text-7xl pr-6 pb-10 transition-all duration-200",
30
+ {
31
+ "translate-y-full": result?.id !== prompt.id,
32
+ }
33
+ )}
34
+ >
35
+ +1
36
+ </p>
37
+ </div>
38
+ );
39
+ };
components/quizz/card/valid.tsx ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import classNames from "classnames";
2
+ import { IoMdCheckmark } from "react-icons/io";
3
+
4
+ export const Valid = ({
5
+ result,
6
+ prompt,
7
+ }: {
8
+ result: { success: boolean; id: null | string } | null | undefined;
9
+ prompt: { id: string };
10
+ }) => {
11
+ return (
12
+ <div
13
+ className={classNames(
14
+ "absolute bottom-0 w-full left-0 px-8 pb-8 flex justify-start items-center transition-all duration-200 opacity-0 pointer-events-none translate-y-full",
15
+ {
16
+ "!opacity-100 !pointer-events-auto !translate-y-0":
17
+ result && !result?.success && result?.id === prompt.id,
18
+ }
19
+ )}
20
+ >
21
+ <div className="font-extrabold text-white text-3xl flex items-center justify-center transition-all duration-200 w-10 h-10 rounded-full bg-green">
22
+ <IoMdCheckmark />
23
+ </div>
24
+ </div>
25
+ );
26
+ };
components/quizz/hooks/useQuizz.ts CHANGED
@@ -1,20 +1,32 @@
1
- import { useState } from "react";
 
2
  import { useQuery, useQueryClient } from "@tanstack/react-query";
 
3
 
4
  import { PromptType } from "@/utils/type";
5
  import { sleep } from "@/utils";
6
 
7
  export const useQuizz = () => {
8
  const client = useQueryClient();
 
9
 
10
- const { data: success } = useQuery<string | null>(['success'], () => null, {
11
  refetchOnWindowFocus: false,
12
  refetchOnMount: false,
13
  refetchOnReconnect: false,
14
  retry: false,
15
  });
16
 
17
- const setSuccess = (s: string | null) => client.setQueryData(['success'], s);
 
 
 
 
 
 
 
 
 
18
 
19
  const { data: score } = useQuery<number>(['score'], () => 0, {
20
  refetchOnWindowFocus: false,
@@ -34,12 +46,16 @@ export const useQuizz = () => {
34
  client.setQueryData(['score'], (score: number | undefined) => {
35
  return (score ?? 0) + 1;
36
  });
37
- setSuccess(id);
38
- await sleep(3000);
39
- setSuccess(null);
40
- await sleep(100);
 
 
41
  client.invalidateQueries(['quizz']);
42
- refetch()
 
 
43
  }
44
  };
45
 
@@ -61,6 +77,6 @@ export const useQuizz = () => {
61
  question: data?.question,
62
  onScore,
63
  score,
64
- success
65
  }
66
  }
 
1
+ "use client";
2
+
3
  import { useQuery, useQueryClient } from "@tanstack/react-query";
4
+ import { useRouter } from 'next/navigation'
5
 
6
  import { PromptType } from "@/utils/type";
7
  import { sleep } from "@/utils";
8
 
9
  export const useQuizz = () => {
10
  const client = useQueryClient();
11
+ const router = useRouter();
12
 
13
+ const { data: result } = useQuery<{ success: boolean, id: string} | null>(['success'], () => null, {
14
  refetchOnWindowFocus: false,
15
  refetchOnMount: false,
16
  refetchOnReconnect: false,
17
  retry: false,
18
  });
19
 
20
+ const setResult = (s: string | null, success?: boolean) => {
21
+ if (!s) {
22
+ client.setQueryData(['success'], null);
23
+ return;
24
+ }
25
+ client.setQueryData(['success'], {
26
+ success,
27
+ id: s,
28
+ });
29
+ }
30
 
31
  const { data: score } = useQuery<number>(['score'], () => 0, {
32
  refetchOnWindowFocus: false,
 
46
  client.setQueryData(['score'], (score: number | undefined) => {
47
  return (score ?? 0) + 1;
48
  });
49
+ }
50
+ setResult(response.ok ? id : response.resultId, response?.ok);
51
+ await sleep(3000);
52
+ setResult(null);
53
+ await sleep(100);
54
+ if (response?.ok) {
55
  client.invalidateQueries(['quizz']);
56
+ await refetch()
57
+ } else {
58
+ return router.push('/results');
59
  }
60
  };
61
 
 
77
  question: data?.question,
78
  onScore,
79
  score,
80
+ result,
81
  }
82
  }
components/quizz/index.tsx CHANGED
@@ -1,7 +1,5 @@
1
  "use client";
2
 
3
- import Image from "next/image";
4
-
5
  import { useQuizz } from "./hooks/useQuizz";
6
  import { PromptType } from "@/utils/type";
7
  import { Card } from "./card";
 
1
  "use client";
2
 
 
 
3
  import { useQuizz } from "./hooks/useQuizz";
4
  import { PromptType } from "@/utils/type";
5
  import { Card } from "./card";
data/dev.db CHANGED
Binary files a/data/dev.db and b/data/dev.db differ
 
package-lock.json CHANGED
@@ -19,6 +19,7 @@
19
  "react": "^18",
20
  "react-confetti": "^6.1.0",
21
  "react-dom": "^18",
 
22
  "react-use": "^17.4.0"
23
  },
24
  "devDependencies": {
@@ -683,6 +684,7 @@
683
  "version": "5.0.1",
684
  "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
685
  "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
 
686
  "engines": {
687
  "node": ">=8"
688
  }
@@ -691,6 +693,7 @@
691
  "version": "4.3.0",
692
  "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
693
  "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
 
694
  "dependencies": {
695
  "color-convert": "^2.0.1"
696
  },
@@ -956,7 +959,8 @@
956
  "node_modules/balanced-match": {
957
  "version": "1.0.2",
958
  "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
959
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
 
960
  },
961
  "node_modules/binary-extensions": {
962
  "version": "2.2.0",
@@ -971,6 +975,7 @@
971
  "version": "1.1.11",
972
  "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
973
  "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
 
974
  "dependencies": {
975
  "balanced-match": "^1.0.0",
976
  "concat-map": "0.0.1"
@@ -1086,6 +1091,7 @@
1086
  "version": "4.1.2",
1087
  "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
1088
  "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
 
1089
  "dependencies": {
1090
  "ansi-styles": "^4.1.0",
1091
  "supports-color": "^7.1.0"
@@ -1150,6 +1156,7 @@
1150
  "version": "2.0.1",
1151
  "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
1152
  "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
 
1153
  "dependencies": {
1154
  "color-name": "~1.1.4"
1155
  },
@@ -1160,7 +1167,8 @@
1160
  "node_modules/color-name": {
1161
  "version": "1.1.4",
1162
  "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
1163
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
 
1164
  },
1165
  "node_modules/commander": {
1166
  "version": "4.1.1",
@@ -1174,7 +1182,8 @@
1174
  "node_modules/concat-map": {
1175
  "version": "0.0.1",
1176
  "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
1177
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
 
1178
  },
1179
  "node_modules/copy-to-clipboard": {
1180
  "version": "3.3.3",
@@ -2073,7 +2082,8 @@
2073
  "node_modules/fs.realpath": {
2074
  "version": "1.0.0",
2075
  "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
2076
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
 
2077
  },
2078
  "node_modules/fsevents": {
2079
  "version": "2.3.3",
@@ -2172,6 +2182,7 @@
2172
  "version": "7.1.7",
2173
  "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
2174
  "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
 
2175
  "dependencies": {
2176
  "fs.realpath": "^1.0.0",
2177
  "inflight": "^1.0.4",
@@ -2290,6 +2301,7 @@
2290
  "version": "4.0.0",
2291
  "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
2292
  "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
 
2293
  "engines": {
2294
  "node": ">=8"
2295
  }
@@ -2405,6 +2417,7 @@
2405
  "version": "1.0.6",
2406
  "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
2407
  "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
 
2408
  "dependencies": {
2409
  "once": "^1.3.0",
2410
  "wrappy": "1"
@@ -2413,7 +2426,8 @@
2413
  "node_modules/inherits": {
2414
  "version": "2.0.4",
2415
  "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
2416
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
 
2417
  },
2418
  "node_modules/inline-style-prefixer": {
2419
  "version": "6.0.4",
@@ -2781,7 +2795,8 @@
2781
  "node_modules/isexe": {
2782
  "version": "2.0.0",
2783
  "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
2784
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
 
2785
  },
2786
  "node_modules/iterator.prototype": {
2787
  "version": "1.1.2",
@@ -2963,6 +2978,7 @@
2963
  "version": "6.0.0",
2964
  "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
2965
  "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
 
2966
  "dependencies": {
2967
  "yallist": "^4.0.0"
2968
  },
@@ -3001,6 +3017,7 @@
3001
  "version": "3.1.2",
3002
  "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
3003
  "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
 
3004
  "dependencies": {
3005
  "brace-expansion": "^1.1.7"
3006
  },
@@ -3020,7 +3037,8 @@
3020
  "node_modules/ms": {
3021
  "version": "2.1.2",
3022
  "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
3023
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
 
3024
  },
3025
  "node_modules/mz": {
3026
  "version": "2.7.0",
@@ -6020,6 +6038,7 @@
6020
  "version": "1.4.0",
6021
  "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
6022
  "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
 
6023
  "dependencies": {
6024
  "wrappy": "1"
6025
  }
@@ -6096,6 +6115,7 @@
6096
  "version": "1.0.1",
6097
  "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
6098
  "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
 
6099
  "engines": {
6100
  "node": ">=0.10.0"
6101
  }
@@ -6390,6 +6410,14 @@
6390
  "react": "^18.2.0"
6391
  }
6392
  },
 
 
 
 
 
 
 
 
6393
  "node_modules/react-is": {
6394
  "version": "16.13.1",
6395
  "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
@@ -6644,6 +6672,7 @@
6644
  "version": "7.5.4",
6645
  "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
6646
  "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
 
6647
  "dependencies": {
6648
  "lru-cache": "^6.0.0"
6649
  },
@@ -6874,6 +6903,7 @@
6874
  "version": "6.0.1",
6875
  "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
6876
  "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
 
6877
  "dependencies": {
6878
  "ansi-regex": "^5.0.1"
6879
  },
@@ -6975,6 +7005,7 @@
6975
  "version": "7.2.0",
6976
  "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
6977
  "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
 
6978
  "dependencies": {
6979
  "has-flag": "^4.0.0"
6980
  },
@@ -7043,7 +7074,8 @@
7043
  "node_modules/text-table": {
7044
  "version": "0.2.0",
7045
  "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
7046
- "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw=="
 
7047
  },
7048
  "node_modules/thenify": {
7049
  "version": "3.3.1",
@@ -7328,6 +7360,7 @@
7328
  "version": "2.0.2",
7329
  "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
7330
  "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
 
7331
  "dependencies": {
7332
  "isexe": "^2.0.0"
7333
  },
@@ -7417,12 +7450,14 @@
7417
  "node_modules/wrappy": {
7418
  "version": "1.0.2",
7419
  "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
7420
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
 
7421
  },
7422
  "node_modules/yallist": {
7423
  "version": "4.0.0",
7424
  "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
7425
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
 
7426
  },
7427
  "node_modules/yaml": {
7428
  "version": "2.3.4",
 
19
  "react": "^18",
20
  "react-confetti": "^6.1.0",
21
  "react-dom": "^18",
22
+ "react-icons": "^4.12.0",
23
  "react-use": "^17.4.0"
24
  },
25
  "devDependencies": {
 
684
  "version": "5.0.1",
685
  "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
686
  "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
687
+ "dev": true,
688
  "engines": {
689
  "node": ">=8"
690
  }
 
693
  "version": "4.3.0",
694
  "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
695
  "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
696
+ "dev": true,
697
  "dependencies": {
698
  "color-convert": "^2.0.1"
699
  },
 
959
  "node_modules/balanced-match": {
960
  "version": "1.0.2",
961
  "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
962
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
963
+ "dev": true
964
  },
965
  "node_modules/binary-extensions": {
966
  "version": "2.2.0",
 
975
  "version": "1.1.11",
976
  "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
977
  "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
978
+ "dev": true,
979
  "dependencies": {
980
  "balanced-match": "^1.0.0",
981
  "concat-map": "0.0.1"
 
1091
  "version": "4.1.2",
1092
  "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
1093
  "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
1094
+ "dev": true,
1095
  "dependencies": {
1096
  "ansi-styles": "^4.1.0",
1097
  "supports-color": "^7.1.0"
 
1156
  "version": "2.0.1",
1157
  "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
1158
  "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
1159
+ "dev": true,
1160
  "dependencies": {
1161
  "color-name": "~1.1.4"
1162
  },
 
1167
  "node_modules/color-name": {
1168
  "version": "1.1.4",
1169
  "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
1170
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
1171
+ "dev": true
1172
  },
1173
  "node_modules/commander": {
1174
  "version": "4.1.1",
 
1182
  "node_modules/concat-map": {
1183
  "version": "0.0.1",
1184
  "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
1185
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
1186
+ "dev": true
1187
  },
1188
  "node_modules/copy-to-clipboard": {
1189
  "version": "3.3.3",
 
2082
  "node_modules/fs.realpath": {
2083
  "version": "1.0.0",
2084
  "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
2085
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
2086
+ "dev": true
2087
  },
2088
  "node_modules/fsevents": {
2089
  "version": "2.3.3",
 
2182
  "version": "7.1.7",
2183
  "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
2184
  "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
2185
+ "dev": true,
2186
  "dependencies": {
2187
  "fs.realpath": "^1.0.0",
2188
  "inflight": "^1.0.4",
 
2301
  "version": "4.0.0",
2302
  "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
2303
  "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
2304
+ "dev": true,
2305
  "engines": {
2306
  "node": ">=8"
2307
  }
 
2417
  "version": "1.0.6",
2418
  "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
2419
  "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
2420
+ "dev": true,
2421
  "dependencies": {
2422
  "once": "^1.3.0",
2423
  "wrappy": "1"
 
2426
  "node_modules/inherits": {
2427
  "version": "2.0.4",
2428
  "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
2429
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
2430
+ "dev": true
2431
  },
2432
  "node_modules/inline-style-prefixer": {
2433
  "version": "6.0.4",
 
2795
  "node_modules/isexe": {
2796
  "version": "2.0.0",
2797
  "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
2798
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
2799
+ "dev": true
2800
  },
2801
  "node_modules/iterator.prototype": {
2802
  "version": "1.1.2",
 
2978
  "version": "6.0.0",
2979
  "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
2980
  "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
2981
+ "dev": true,
2982
  "dependencies": {
2983
  "yallist": "^4.0.0"
2984
  },
 
3017
  "version": "3.1.2",
3018
  "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
3019
  "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
3020
+ "dev": true,
3021
  "dependencies": {
3022
  "brace-expansion": "^1.1.7"
3023
  },
 
3037
  "node_modules/ms": {
3038
  "version": "2.1.2",
3039
  "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
3040
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
3041
+ "dev": true
3042
  },
3043
  "node_modules/mz": {
3044
  "version": "2.7.0",
 
6038
  "version": "1.4.0",
6039
  "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
6040
  "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
6041
+ "dev": true,
6042
  "dependencies": {
6043
  "wrappy": "1"
6044
  }
 
6115
  "version": "1.0.1",
6116
  "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
6117
  "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
6118
+ "dev": true,
6119
  "engines": {
6120
  "node": ">=0.10.0"
6121
  }
 
6410
  "react": "^18.2.0"
6411
  }
6412
  },
6413
+ "node_modules/react-icons": {
6414
+ "version": "4.12.0",
6415
+ "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.12.0.tgz",
6416
+ "integrity": "sha512-IBaDuHiShdZqmfc/TwHu6+d6k2ltNCf3AszxNmjJc1KUfXdEeRJOKyNvLmAHaarhzGmTSVygNdyu8/opXv2gaw==",
6417
+ "peerDependencies": {
6418
+ "react": "*"
6419
+ }
6420
+ },
6421
  "node_modules/react-is": {
6422
  "version": "16.13.1",
6423
  "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
 
6672
  "version": "7.5.4",
6673
  "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
6674
  "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
6675
+ "dev": true,
6676
  "dependencies": {
6677
  "lru-cache": "^6.0.0"
6678
  },
 
6903
  "version": "6.0.1",
6904
  "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
6905
  "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
6906
+ "dev": true,
6907
  "dependencies": {
6908
  "ansi-regex": "^5.0.1"
6909
  },
 
7005
  "version": "7.2.0",
7006
  "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
7007
  "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
7008
+ "dev": true,
7009
  "dependencies": {
7010
  "has-flag": "^4.0.0"
7011
  },
 
7074
  "node_modules/text-table": {
7075
  "version": "0.2.0",
7076
  "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
7077
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
7078
+ "dev": true
7079
  },
7080
  "node_modules/thenify": {
7081
  "version": "3.3.1",
 
7360
  "version": "2.0.2",
7361
  "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
7362
  "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
7363
+ "dev": true,
7364
  "dependencies": {
7365
  "isexe": "^2.0.0"
7366
  },
 
7450
  "node_modules/wrappy": {
7451
  "version": "1.0.2",
7452
  "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
7453
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
7454
+ "dev": true
7455
  },
7456
  "node_modules/yallist": {
7457
  "version": "4.0.0",
7458
  "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
7459
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
7460
+ "dev": true
7461
  },
7462
  "node_modules/yaml": {
7463
  "version": "2.3.4",
package.json CHANGED
@@ -20,6 +20,7 @@
20
  "react": "^18",
21
  "react-confetti": "^6.1.0",
22
  "react-dom": "^18",
 
23
  "react-use": "^17.4.0"
24
  },
25
  "devDependencies": {
 
20
  "react": "^18",
21
  "react-confetti": "^6.1.0",
22
  "react-dom": "^18",
23
+ "react-icons": "^4.12.0",
24
  "react-use": "^17.4.0"
25
  },
26
  "devDependencies": {