├── .eslintrc.json ├── .gitignore ├── README.md ├── app ├── (pages) │ ├── activity-selector │ │ ├── page.tsx │ │ └── styles.module.scss │ ├── algorithms │ │ ├── components │ │ │ ├── AlgorthmsSetUp │ │ │ │ ├── AlgorthmsSetUp.tsx │ │ │ │ └── styles.module.scss │ │ │ └── AlgorthmsStart │ │ │ │ ├── AlgorthmsStart.tsx │ │ │ │ └── styles.module.scss │ │ ├── page.tsx │ │ ├── playground │ │ │ ├── Workspace │ │ │ │ ├── Workspace.tsx │ │ │ │ └── styles.module.scss │ │ │ ├── page.tsx │ │ │ └── styles.module.scss │ │ └── styles.module.scss │ └── quiz │ │ ├── components │ │ ├── Questions │ │ │ ├── Questions.tsx │ │ │ ├── components │ │ │ │ └── AnswerOptions │ │ │ │ │ ├── AnswerOptions.tsx │ │ │ │ │ ├── Matching │ │ │ │ │ ├── Matching.tsx │ │ │ │ │ └── styles.module.scss │ │ │ │ │ ├── MultipleSelect │ │ │ │ │ ├── MultipleSelect.tsx │ │ │ │ │ └── styles.module.scss │ │ │ │ │ └── styles.module.scss │ │ │ └── styles.module.scss │ │ ├── QuizSetup │ │ │ ├── QuizSetup.tsx │ │ │ └── styles.module.scss │ │ └── Results │ │ │ ├── Results.tsx │ │ │ └── styles.module.scss │ │ ├── page.tsx │ │ ├── playground │ │ ├── page.tsx │ │ └── styles.module.scss │ │ └── styles.module.scss ├── api │ ├── _services │ │ ├── errors.ts │ │ └── successfulResponses.ts │ ├── algorithm │ │ └── route.ts │ ├── chat │ │ └── route.ts │ ├── quiz │ │ └── route.ts │ └── runcode │ │ └── route.tsx ├── components │ ├── AlgorithmBot │ │ ├── AlgorithmBot.tsx │ │ └── styles.module.scss │ ├── Ballon │ │ ├── Ballon.tsx │ │ └── styles.module.scss │ ├── BounceBall │ │ └── BounceBall.ts │ ├── Button │ │ ├── Button.tsx │ │ ├── ButtonLink.tsx │ │ └── styles.module.scss │ ├── ButtonBack │ │ ├── ButtonBack.tsx │ │ └── styles.module.scss │ ├── ButtonClose │ │ ├── ButtonClose.tsx │ │ └── styles.module.scss │ ├── ButtonCopy │ │ ├── ButtonCopy.tsx │ │ └── styles.module.scss │ ├── CircularProgress │ │ └── CircularProgress.tsx │ ├── CodeEditor │ │ ├── CodeEditor.tsx │ │ └── styles.module.scss │ ├── Combobox │ │ ├── Combobox.tsx │ │ └── styles.module.scss │ ├── Footer │ │ ├── Footer.tsx │ │ └── styles.module.scss │ ├── Header │ │ ├── Header.tsx │ │ └── styles.module.scss │ ├── Icons.tsx │ ├── Levels │ │ ├── Levels.tsx │ │ └── styles.module.scss │ ├── Loading │ │ ├── Loading.tsx │ │ └── styles.module.scss │ ├── Modal │ │ ├── Modal.tsx │ │ └── styles.module.scss │ ├── QuizBot │ │ ├── ParseTextToJSX.tsx │ │ ├── QuizBot.tsx │ │ └── styles.module.scss │ ├── Separator │ │ ├── Separator.tsx │ │ └── styles.module.scss │ ├── SnackProvider │ │ └── SnackProvider.tsx │ ├── TextBox │ │ ├── TextBox.tsx │ │ └── styles.module.scss │ └── TextBoxApiKey │ │ ├── TextBoxApiKey.tsx │ │ └── styles.module.scss ├── globals.css ├── interfaces │ ├── algorithm.ts │ ├── languages.ts │ └── quiz.ts ├── layout.tsx ├── page.module.css ├── page.tsx └── utils │ ├── const.tsx │ ├── dataFetch.ts │ ├── helpers.ts │ └── store.ts ├── next.config.mjs ├── package-lock.json ├── package.json ├── public ├── angular_icon.png ├── aws_icon.png ├── azure_icon.png ├── backcode.webp ├── bootstrap_icon.png ├── c_icon.png ├── cpp_icon.png ├── csharp_icon.png ├── css_icon.png ├── django_icon.png ├── docker_icon.png ├── flutter_icon.png ├── frame_code.png ├── frame_code2.png ├── go_icon.png ├── grid.png ├── html_icon.png ├── java_icon.png ├── javascript_icon.png ├── jenkins_icon.png ├── kotlin_icon.png ├── logo.svg ├── lua_icon.png ├── mongo_icon.png ├── node_icon.png ├── organize.svg ├── perl_icon.png ├── php_icon.png ├── python_icon.png ├── quiz.png ├── react_icon.png ├── ruby_icon.png ├── rust_icon.png ├── scala_icon.png ├── sql_icon.png ├── swift_icon.png ├── tailwind_icon.png ├── terraform_icon.png ├── typescript_icon.png └── vue_icon.png └── tsconfig.json /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals", 3 | "rules": { 4 | "semi": [ 5 | 1, 6 | "never" 7 | ] 8 | } 9 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CodeChallengeQuiz 2 | 3 | Vista Principal 4 | Vista Principal 5 | Vista Principal 6 | **CodeChallengeQuiz** es una aplicación interactiva diseñada para mejorar tus habilidades de programación a través de cuestionarios y retos de algoritmos. Esta aplicación es ideal para preparar entrevistas técnicas, desafiar tus conocimientos y aprender nuevas tecnologías. 7 | 8 | ## Características 9 | 10 | - **Quizzes Interactivos:** Preguntas de opción múltiple sobre diversos lenguajes de programación, frameworks y tecnologías. Ideal para practicar para entrevistas técnicas. 11 | - **Retos de Algoritmos:** Genera, escribe y envía algoritmos para ser validados y corregidos por la IA. 12 | - **Playground:** Una sección donde puedes elegir entre preguntas o retos de algoritmos para practicar y mejorar tus habilidades. 13 | - **Tecnologías Soportadas:** Incluye soporte para lenguajes como JavaScript, Python, Java, C++, y más, así como frameworks y herramientas populares. 14 | 15 | ## Tecnologías Utilizadas 16 | 17 | - **Front-End:** Next.js, HTML, CSS 18 | - **IA:** Google Gemini, Vercel AI SDK 19 | 20 | ## Instalación 21 | 22 | 1. **Clona el repositorio:** 23 | ```sh 24 | git clone https://github.com/AletzMan/code_challenge_and_quiz.git 25 | cd CodeChallengeQuiz 26 | ``` 27 | 28 | 2. **Instala las dependencias:** 29 | ```sh 30 | npm install 31 | ``` 32 | 33 | 3. **Ejecuta la aplicación:** 34 | ```sh 35 | npm run dev 36 | ``` 37 | 38 | 4. **Accede a la aplicación:** 39 | Abre tu navegador y ve a `http://localhost:3000` 40 | 41 | ## Uso 42 | 43 | - **Página Principal:** Explora las funcionalidades principales y selecciona entre quizzes interactivos y retos de algoritmos. 44 | - **Playground:** Elige entre responder preguntas o resolver algoritmos para practicar de forma interactiva. 45 | - **Quizzes:** Responde preguntas de opción múltiple sobre diferentes tecnologías y recibe feedback inmediato. 46 | - **Algoritmos:** Escribe y envía tu código para ser validado y corregido por la IA. 47 | 48 | ## Contribuciones 49 | 50 | ¡Contribuciones son bienvenidas! Por favor, sigue estos pasos para contribuir: 51 | 52 | 1. **Fork el repositorio** 53 | 2. **Crea una nueva rama:** 54 | ```sh 55 | git checkout -b mi-rama 56 | ``` 57 | 3. **Realiza tus cambios y haz un commit:** 58 | ```sh 59 | git commit -m 'Añadir algo increíble' 60 | ``` 61 | 4. **Envía tus cambios a tu repositorio remoto:** 62 | ```sh 63 | git push origin mi-rama 64 | ``` 65 | 5. **Abre un Pull Request** 66 | 67 | ## Licencia 68 | 69 | Este proyecto está bajo la licencia MIT. Ver el archivo [LICENSE](LICENSE) para más detalles. 70 | 71 | ## Contacto 72 | 73 | Para cualquier consulta o sugerencia, puedes contactar al autor del proyecto: 74 | 75 | - **Email:** [MAIL](mailto:alejandro.ga.dev@gmail.com) 76 | -------------------------------------------------------------------------------- /app/(pages)/activity-selector/page.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | import Link from "next/link" 3 | import { FlowChartIcon, HomeIcon, PuzzleIcon, QuestionIcon } from "../../components/Icons" 4 | import styles from "./styles.module.scss" 5 | import { Footer } from "@/app/components/Footer/Footer" 6 | import { useRef, MouseEvent, useEffect } from "react" 7 | import { ButtonBack } from "@/app/components/ButtonBack/ButtonBack" 8 | 9 | 10 | export default function Page() { 11 | const explotionRef = useRef(null) 12 | 13 | useEffect(() => { 14 | localStorage.removeItem("quizsetupccq") 15 | localStorage.removeItem("currentquizccq") 16 | localStorage.removeItem("algorithmccq") 17 | }, []) 18 | 19 | const HandleClickMain = (e: MouseEvent) => { 20 | if (explotionRef.current) { 21 | explotionRef.current.classList.toggle("explotion_active") 22 | const posX = e.clientX 23 | const posY = e.clientY 24 | explotionRef.current.style.top = `${posY}px` 25 | explotionRef.current.style.left = `${posX}px` 26 | setTimeout(() => { 27 | if (explotionRef.current) { 28 | explotionRef.current.classList.toggle("explotion_active") 29 | } 30 | 31 | }, 200) 32 | } 33 | } 34 | 35 | return ( 36 |
37 |
38 | 39 | <> 40 | 41 | {""} 42 | 43 | 44 |
45 |
46 |

¡Mejora tus habilidades de programación divirtiéndote!

47 |

Elige el tipo de desafío que te interesa para comenzar.

48 |

Actualmente, puedes seleccionar entre las opciones disponibles, pero pronto agregaremos más categorías para ofrecerte una experiencia más completa.

49 |
50 | 51 |

Potencia tu lógica

52 |
53 |

La IA creará problemas de programación adaptados a tu nivel.

54 |

¡Resuélvelos y crece como programador!

55 |
56 | 57 | 58 | 59 |

¡Prueba tus Conocimientos!

60 |
61 |

Genera quizzes aleatorios y desafía tus conocimientos.

62 |

¡Perfecto para estudiar o simplemente por diversión!

63 |
64 | 65 | 66 |
67 |

Juegos y Retos de Lógica

68 |
69 |

Mejora tu lógica y habilidades con juegos diseñados para programadores.

70 |
71 | 72 | 73 | Próximamente 74 | 75 |
76 |
77 |
78 | 79 | 80 |
81 |
82 |
83 | ) 84 | } -------------------------------------------------------------------------------- /app/(pages)/activity-selector/styles.module.scss: -------------------------------------------------------------------------------- 1 | .main { 2 | display: flex; 3 | flex-direction: column; 4 | align-items: center; 5 | justify-content: flex-start; 6 | gap: 2em; 7 | margin: 0.5em; 8 | border-radius: 0.25em; 9 | border: 1px solid var(--gray-color); 10 | height: calc(100svh - 1em); 11 | 12 | &_title { 13 | font-size: 1.75em; 14 | color: var(--font-color); 15 | text-align: center; 16 | background: linear-gradient(45deg, var(--purple-color), var(--yellow-color)); 17 | background-clip: text; 18 | -webkit-text-fill-color: transparent; 19 | 20 | @media (width < 600px) { 21 | font-size: 1.5em; 22 | } 23 | } 24 | } 25 | 26 | .header { 27 | position: sticky; 28 | top: 0; 29 | display: flex; 30 | justify-content: flex-start; 31 | padding: 0.5em; 32 | width: 100%; 33 | } 34 | 35 | .section { 36 | margin: 0 0 3.5em 0; 37 | display: flex; 38 | flex-direction: column; 39 | align-items: center; 40 | gap: 2em; 41 | z-index: 10; 42 | background-color: transparent; 43 | backdrop-filter: blur(7px); 44 | padding: 2em; 45 | border-radius: 0.5em; 46 | 47 | @media (width < 600px) { 48 | margin: 0; 49 | width: calc(100svw - 1em); 50 | padding: 0.5em; 51 | gap: 1em; 52 | } 53 | } 54 | 55 | .message { 56 | color: var(--fontsecond-color); 57 | max-width: 60ch; 58 | text-align: center; 59 | text-wrap: balance; 60 | 61 | @media (width < 600px) { 62 | font-size: 0.9em; 63 | text-wrap: pretty; 64 | } 65 | } 66 | 67 | .categories { 68 | display: grid; 69 | grid-template-columns: repeat(auto-fit, minmax(20em, 1fr)); 70 | gap: 1.5em; 71 | width: 100%; 72 | max-width: 1000px; 73 | border-radius: 0.25em; 74 | padding: 1.5em; 75 | } 76 | 77 | .subtitle { 78 | color: var(--font-color); 79 | } 80 | 81 | .article { 82 | display: flex; 83 | align-items: center; 84 | flex-direction: column; 85 | gap: 1em; 86 | border-radius: 0.25em; 87 | padding: 0.5em; 88 | min-height: 12.5em; 89 | text-decoration: none; 90 | transition: all 0.3s ease-in-out; 91 | background-color: var(--background-color); 92 | border: 1px solid var(--grayblack-color); 93 | 94 | &_messages { 95 | display: flex; 96 | flex-direction: column; 97 | align-items: center; 98 | } 99 | 100 | &_message { 101 | color: var(--fontsecond-color); 102 | text-align: center; 103 | } 104 | 105 | &:hover { 106 | border-color: #efe82060; 107 | box-shadow: 0 0 4px 2px var(--purple-color); 108 | 109 | & .icon { 110 | transform: scale(1.2); 111 | } 112 | 113 | 114 | } 115 | 116 | /* &_quiz { 117 | //background: linear-gradient(120deg, #2b3025, #3d4334); 118 | //border: 1px solid #efe82020; 119 | 120 | &:hover { 121 | border-color: #efe82060; 122 | box-shadow: 0 0 4px 2px #efe82030; 123 | } 124 | } 125 | 126 | &_algorithms { 127 | //background: linear-gradient(120deg, #203124, #293e2e); 128 | // border: 1px solid #39FF1420; 129 | background-color: var(--background-color); 130 | border: 1px solid var(--grayblack-color); 131 | 132 | &:hover { 133 | border-color: #39FF1460; 134 | box-shadow: 0 0 4px 2px #39FF1430; 135 | } 136 | }*/ 137 | 138 | &_games { 139 | position: relative; 140 | opacity: 0.8; 141 | pointer-events: stroke; 142 | cursor: not-allowed; 143 | 144 | &:hover>.article_cooming { 145 | animation: click 0.3s linear; 146 | } 147 | 148 | 149 | } 150 | 151 | &_cooming { 152 | position: absolute; 153 | top: calc(50% - 1.5em); 154 | display: flex; 155 | align-items: center; 156 | height: 3em; 157 | justify-content: center; 158 | width: 60%; 159 | font-weight: 600; 160 | font-size: 1.5em; 161 | text-transform: uppercase; 162 | color: #FFC107; 163 | background-color: #FFC10715; 164 | backdrop-filter: blur(2px); 165 | border-bottom: 3px solid #FFC107; 166 | border-top: 3px solid #FFC107; 167 | transform: rotateZ(8deg); 168 | z-index: 5; 169 | } 170 | 171 | 172 | } 173 | 174 | 175 | @keyframes click { 176 | 0% { 177 | transform: rotateZ(7deg); 178 | } 179 | 180 | 25% { 181 | transform: rotateZ(8deg) scale(.8); 182 | } 183 | 184 | 50% { 185 | transform: rotateZ(1deg); 186 | } 187 | 188 | 75% { 189 | transform: rotateZ(8deg) scale(.8); 190 | } 191 | 192 | 100% { 193 | transform: rotateZ(8deg) scale(1); 194 | } 195 | } 196 | 197 | .icon { 198 | width: 3em; 199 | height: 3em; 200 | transition: all 0.35s ease-in-out; 201 | 202 | &_one { 203 | color: #efe82050; 204 | } 205 | 206 | &_two { 207 | color: #39FF1450; 208 | } 209 | 210 | &_three { 211 | color: #14b1ff50; 212 | } 213 | } 214 | 215 | .buttonSelect { 216 | color: red !important; 217 | } -------------------------------------------------------------------------------- /app/(pages)/algorithms/components/AlgorthmsSetUp/AlgorthmsSetUp.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable react-hooks/exhaustive-deps */ 2 | "use client" 3 | import { Combobox } from "@/app/components/Combobox/Combobox" 4 | import styles from "./styles.module.scss" 5 | import { ChangeEvent, Dispatch, SetStateAction, useEffect, useState } from "react" 6 | import { AlgorithmsCategories, CATEGORIES } from "@/app/utils/const" 7 | import { useApiKey, useSetupQuiz } from "@/app/utils/store" 8 | import { FlowChartIcon, HammerIcon, StudentIcon, ToolsIcon, TrophyIcon } from "@/app/components/Icons" 9 | import { TextBoxApiKey } from "@/app/components/TextBoxApiKey/TextBoxApiKey" 10 | import { IItemCategory } from "@/app/interfaces/languages" 11 | import { IAlgorithmProperty } from "@/app/interfaces/algorithm" 12 | 13 | interface Props { 14 | error: boolean 15 | setError: Dispatch> 16 | } 17 | 18 | export function AlgorthmsSetUp({ error, setError }: Props) { 19 | const { language, setLanguage, difficulty, setDifficulty, categoryAlgorithm, setCategoryAlgorith } = useSetupQuiz() 20 | const { setApiKey, apiKey } = useApiKey() 21 | 22 | useEffect(() => { 23 | if (language.logo?.key === null) { 24 | //setLanguage(CATEGORIES.languages.items.find(item => item.language === language.language) as IItemCategory) 25 | } 26 | }, [categoryAlgorithm]) 27 | 28 | const HandleChangeDifficulty = (value: "easy" | "medium" | "hard" | "expert") => { 29 | setDifficulty(value) 30 | } 31 | 32 | function HandleChangeCategory(event: ChangeEvent): void { 33 | const value = event.currentTarget.value 34 | const selectCategory: IAlgorithmProperty | undefined = AlgorithmsCategories.find(item => item.option === value) 35 | if (selectCategory) { 36 | setCategoryAlgorith(selectCategory) 37 | } 38 | } 39 | 40 | function HandleChangeLanguage(event: ChangeEvent): void { 41 | const value = event.currentTarget.value 42 | const selectLanguage: IItemCategory | undefined = CATEGORIES.languages.items.find(item => item.option === value) 43 | if (selectLanguage) { 44 | setLanguage(selectLanguage) 45 | } 46 | } 47 | 48 | 49 | function HandleChangeApiKey(event: ChangeEvent): void { 50 | const newApiKey = event.currentTarget.value 51 | setApiKey(newApiKey) 52 | setError(false) 53 | } 54 | 55 | 56 | return ( 57 |
58 |
59 |
60 | 61 | 62 |
63 |
64 | 65 |
66 | 67 | 68 | 69 | 70 |
71 |
72 |
73 | 74 |
75 | ) 76 | } 77 | -------------------------------------------------------------------------------- /app/(pages)/algorithms/components/AlgorthmsSetUp/styles.module.scss: -------------------------------------------------------------------------------- 1 | .container { 2 | position: relative; 3 | display: flex; 4 | flex-direction: column; 5 | align-items: center; 6 | margin: 0em 0 0 0; 7 | padding: 2em; 8 | border-radius: 0.25em; 9 | //border: 1px solid #2b2b2b; 10 | 11 | @media (width < 600px) { 12 | margin: 0; 13 | padding: 0.5em; 14 | gap: 0.5em; 15 | } 16 | } 17 | 18 | .options { 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | gap: 1.5em; 23 | margin: 1em; 24 | 25 | 26 | } 27 | 28 | .selects { 29 | display: flex; 30 | gap: 1em; 31 | 32 | @media (width < 600px) { 33 | flex-direction: column; 34 | align-items: center; 35 | } 36 | } 37 | 38 | .difficulty { 39 | display: flex; 40 | align-items: center; 41 | flex-direction: column; 42 | 43 | 44 | &_label { 45 | font-size: 0.8em; 46 | color: var(--fontsecond-color); 47 | } 48 | 49 | &_buttons { 50 | display: flex; 51 | gap: 1em; 52 | padding: 1em; 53 | border-radius: 0.25em; 54 | background-color: var(--black-color); 55 | 56 | @media (width < 600px) { 57 | flex-direction: column; 58 | } 59 | } 60 | 61 | &_icon { 62 | width: 1.5em; 63 | height: 1.5em; 64 | } 65 | 66 | &_button { 67 | display: flex; 68 | align-items: center; 69 | justify-content: center; 70 | gap: 0.5em; 71 | min-width: 8.5em; 72 | padding: 0.25em 0; 73 | background-color: #a5a5a510; 74 | border-radius: 0.25em; 75 | font-weight: 400; 76 | border: 1px dashed #FFFFFF25; 77 | color: var(--fontsecond-color); 78 | background: var(--gray-color); 79 | font-family: var(--font-family); 80 | text-transform: capitalize; 81 | transition: all 0.3s ease-in-out; 82 | text-shadow: 0 0 3px #000000; 83 | filter: brightness(80%); 84 | 85 | 86 | 87 | &:not(.difficulty_buttonActive) { 88 | cursor: pointer; 89 | } 90 | 91 | &:hover:not(.difficulty_buttonActive) { 92 | filter: brightness(140%); 93 | box-shadow: 0 0 5px 2px #CCCCCC30; 94 | } 95 | 96 | &Easy:is(.difficulty_buttonActive) { 97 | //color: #40d940; 98 | //border-color: #028207; 99 | background: linear-gradient(-15deg, #02550480, #06980b80, #06980b80, #02550480); 100 | } 101 | 102 | &Medium:is(.difficulty_buttonActive) { 103 | //color: #3399FF; 104 | //border-color: #9a8b05; 105 | background: linear-gradient(-15deg, #1c6ab780, #3399FF80, #3399FF80, #1c6ab780); 106 | } 107 | 108 | &Hard:is(.difficulty_buttonActive) { 109 | //color: #FF8C00; 110 | //border-color: #925902; 111 | background: linear-gradient(-15deg, #5b370280, #b16c0480, #b16c0480, #5b370280); 112 | } 113 | 114 | &Expert:is(.difficulty_buttonActive) { 115 | //color: #FF0000; 116 | //border-color: #bd1206; 117 | background: linear-gradient(-15deg, #720b0480, #c11a0e80, #c11a0e80, #720b0480); 118 | } 119 | 120 | &Active { 121 | filter: brightness(140%); 122 | box-shadow: 0 0 5px 2px #CCCCCC30; 123 | color: var(--font-color); 124 | } 125 | } 126 | } -------------------------------------------------------------------------------- /app/(pages)/algorithms/components/AlgorthmsStart/AlgorthmsStart.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable react-hooks/exhaustive-deps */ 2 | "use client" 3 | import styles from "./styles.module.scss" 4 | import { useState } from "react" 5 | import { useAlgorithm, useApiKey } from "@/app/utils/store" 6 | import { enqueueSnackbar } from "notistack" 7 | import { useRouter } from "next/navigation" 8 | import { AlgorthmsSetUp } from "../AlgorthmsSetUp/AlgorthmsSetUp" 9 | import { Footer } from "@/app/components/Footer/Footer" 10 | import { Button } from "@/app/components/Button/Button" 11 | import { NewIcon, PlayIcon } from "@/app/components/Icons" 12 | import { Modal } from "@/app/components/Modal/Modal" 13 | import { ButtonClose } from "@/app/components/ButtonClose/ButtonClose" 14 | 15 | 16 | 17 | export const AlgorthmsStart = () => { 18 | const { apiKey } = useApiKey() 19 | const { setAlgorithmInProgress, algorithmInProgress } = useAlgorithm() 20 | const [error, setError] = useState(false) 21 | const [modal, setModal] = useState(false) 22 | const route = useRouter() 23 | 24 | 25 | const HandleStart = () => { 26 | if (apiKey) { 27 | if (algorithmInProgress) { 28 | enqueueSnackbar("Algoritmo en progreso", { variant: "info" }) 29 | setModal(true) 30 | } else { 31 | setAlgorithmInProgress(false) 32 | route.push("/algorithms/playground") 33 | } 34 | } else { 35 | enqueueSnackbar("Por favor, ingresa tu clave API de OpenAI para continuar", { variant: "error" }) 36 | setError(true) 37 | } 38 | } 39 | 40 | const HandleContinueOrNew = (isNew: boolean) => { 41 | if (isNew) { 42 | setAlgorithmInProgress(false) 43 | } 44 | route.push("/algorithms/playground") 45 | } 46 | 47 | return ( 48 | <> 49 |
50 |
51 |

Configura y comienza

52 |

Selecciona el lenguaje, la dificultad y el tema para crear desafíos que se adapten a tus objetivos

53 | 54 | 58 |
59 |
60 | {modal && 61 | 62 |
63 |
64 |

Algoritmo en pregreso

65 | setModal(false)} /> 66 |
67 |
68 |

Ya tienes un algoritmo en progreso

69 |

¿Deseas seguir con él o empezar de nuevo?

70 |
71 |
72 | 76 | 80 |
81 |
82 |
83 | } 84 |
85 | 86 | ) 87 | } -------------------------------------------------------------------------------- /app/(pages)/algorithms/components/AlgorthmsStart/styles.module.scss: -------------------------------------------------------------------------------- 1 | .section { 2 | position: relative; 3 | display: flex; 4 | flex-direction: column; 5 | align-items: center; 6 | justify-content: space-between; 7 | width: 100%; 8 | max-width: 1980px; 9 | height: 100%; 10 | padding: 3em 0 0 0; 11 | border-radius: 0.5em; 12 | //overflow: hidden; 13 | 14 | } 15 | 16 | .container { 17 | position: relative; 18 | display: flex; 19 | flex-direction: column; 20 | align-items: center; 21 | gap: 0.5em; 22 | width: max-content; 23 | padding: 2em; 24 | border-radius: 0.25em; 25 | background-color: transparent; 26 | border: 1px solid var(--grayblack-color); 27 | backdrop-filter: blur(5px); 28 | z-index: 5; 29 | 30 | @media (width < 600px) { 31 | padding: 0.5em; 32 | width: calc(100svw - 1em); 33 | } 34 | 35 | &_title { 36 | position: relative; 37 | justify-content: center; 38 | display: flex; 39 | width: 100%; 40 | margin: 0 0 1em 0; 41 | text-align: center; 42 | color: var(--yellow-color); 43 | 44 | @media (width < 600px) { 45 | margin: 0; 46 | font-size: 1.2em; 47 | } 48 | } 49 | 50 | 51 | &_setup { 52 | display: flex; 53 | flex-direction: column; 54 | align-items: center; 55 | padding: 1em; 56 | margin: 1em auto; 57 | border-radius: 0.25em; 58 | width: max-content; 59 | 60 | @media (width < 600px) { 61 | padding: 0.5em; 62 | } 63 | 64 | &Message { 65 | color: var(--font-color); 66 | max-width: 60ch; 67 | text-align: center; 68 | padding: 0.5em 0 0 0; 69 | font-weight: 300; 70 | font-size: 1.1em; 71 | text-wrap: balance; 72 | 73 | @media (width < 600px) { 74 | text-wrap: pretty; 75 | font-size: 0.95em; 76 | } 77 | } 78 | } 79 | 80 | 81 | 82 | } 83 | 84 | .start { 85 | align-self: center; 86 | width: 8em; 87 | //height: 4em; 88 | padding: 0.5em 1em; 89 | margin: 2em 0; 90 | border-radius: 0.25em; 91 | font-size: 1.1em; 92 | font-weight: 700; 93 | font-family: var(--font-family); 94 | color: var(--font-color); 95 | //background: #014760; 96 | // border: 1px solid #046a8f; 97 | // text-shadow: 0 0 2px #000000; 98 | background: var(--purple-color); 99 | border: none; 100 | filter: brightness(100%); 101 | cursor: pointer; 102 | transition: all 0.3s ease-in-out; 103 | 104 | @media (width < 600px) { 105 | margin: 0; 106 | } 107 | 108 | &:hover { 109 | border-color: var(--purple-color); 110 | color: var(--font-color); 111 | filter: brightness(100%); 112 | box-shadow: 0 0 4px 2px var(--purple-color); 113 | } 114 | } 115 | 116 | .modal { 117 | position: absolute; 118 | top: 0; 119 | left: 0; 120 | display: flex; 121 | align-items: center; 122 | justify-content: center; 123 | width: calc(100svw - 8em); 124 | height: calc(100svh - 8em); 125 | background-color: transparent; 126 | backdrop-filter: blur(3px); 127 | border: none; 128 | z-index: 20; 129 | 130 | &_window { 131 | display: grid; 132 | grid-template-rows: 2.25em 1fr 3em; 133 | border-radius: 0.25em; 134 | border: 1px solid var(--gray-color); 135 | background-color: var(--background-color); 136 | } 137 | 138 | &_header { 139 | display: flex; 140 | justify-content: space-between; 141 | background-color: var(--gray-color); 142 | padding: 0.25em 0.25em 0.5em 0.5em; 143 | 144 | &Title { 145 | font-size: 1em; 146 | color: var(--fontsecond-color); 147 | } 148 | } 149 | 150 | &_message { 151 | display: flex; 152 | flex-direction: column; 153 | justify-content: center; 154 | align-items: center; 155 | padding: 1.5em 1em; 156 | 157 | } 158 | 159 | &_p { 160 | color: var(--font-color); 161 | } 162 | 163 | &_footer { 164 | display: flex; 165 | justify-content: space-evenly; 166 | padding: 0.5em; 167 | } 168 | } -------------------------------------------------------------------------------- /app/(pages)/algorithms/page.tsx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | import { ButtonBack } from "@/app/components/ButtonBack/ButtonBack" 5 | import { AlgorthmsStart } from "./components/AlgorthmsStart/AlgorthmsStart" 6 | import styles from "./styles.module.scss" 7 | import { SnackProvider } from "@/app/components/SnackProvider/SnackProvider" 8 | import { TargetIcon } from "@/app/components/Icons" 9 | 10 | 11 | export default function Page() { 12 | return ( 13 | <> 14 |
15 |
16 | 17 | <> 18 | 19 | {"Elegir desafío"} 20 | 21 | 22 |
23 | 24 | 25 | 26 |
27 | 28 | ) 29 | } -------------------------------------------------------------------------------- /app/(pages)/algorithms/playground/Workspace/Workspace.tsx: -------------------------------------------------------------------------------- 1 | import { BulbIcon, CheckedIcon, IOIcon, RunCodeIcon } from "@/app/components/Icons" 2 | import styles from "./styles.module.scss" 3 | import { Button } from "@/app/components/Button/Button" 4 | import { CodeEditor } from "@/app/components/CodeEditor/CodeEditor" 5 | import { AlgorithmBot } from "@/app/components/AlgorithmBot/AlgorithmBot" 6 | import { useAlgorithm, useSetupQuiz } from "@/app/utils/store" 7 | import { IOutputRun } from "@/app/interfaces/languages" 8 | import { useState, MouseEvent } from "react" 9 | import { RunCode } from "@/app/utils/dataFetch" 10 | import { Modal } from "@/app/components/Modal/Modal" 11 | import { ButtonClose } from "@/app/components/ButtonClose/ButtonClose" 12 | import { parseTextToJSX } from "@/app/components/QuizBot/ParseTextToJSX" 13 | import { CodeBlock, atomOneDark } from "react-code-blocks" 14 | import { StyleCodeEditor } from "@/app/utils/const" 15 | import { Separator } from "@/app/components/Separator/Separator" 16 | 17 | 18 | export function Workspace() { 19 | const { language } = useSetupQuiz() 20 | const { algorithmSolution, currentAlgorithm } = useAlgorithm() 21 | const [evaluate, setEvaluate] = useState(false) 22 | const [openExplanation, setOpenExplanation] = useState(false) 23 | const [openExample, setOpenExample] = useState(false) 24 | const [output, setOutput] = useState({ code: 0, output: "Suerte 🍀", signal: "", stderr: "", stdout: "" }) 25 | 26 | function HandleEvaluate(event: MouseEvent): void { 27 | setEvaluate(true) 28 | setTimeout(() => { 29 | setEvaluate(false) 30 | }, 500) 31 | } 32 | 33 | const HandleRunCode = async () => { 34 | setOutput({ code: -135, output: "[RUN] Ejecutando código...", signal: "", stderr: "", stdout: "" }) 35 | const response = await RunCode(language.language, algorithmSolution.solution, language.version) 36 | 37 | if (response.response?.run.code === 1 && response.response?.run.stderr) { 38 | setOutput(response.response?.run) 39 | } else { 40 | if (response.response) 41 | setOutput(response.response?.run) 42 | } 43 | } 44 | 45 | 46 | return ( 47 | <> 48 |
49 |
50 |
51 | 55 | 59 | 60 |
61 | 65 |
66 |
67 |
68 | 69 |
70 |
71 |
72 |
73 | 74 |
75 |
76 | OUTPUT 77 | 0 && styles.playground_outputHeaderStatusError} 80 | ${output.code === 0 && styles.playground_outputHeaderStatusOK}`}> 81 |
82 |