From 412c834245b461edada39f09e03611b1569b392c Mon Sep 17 00:00:00 2001
From: "google-labs-jules[bot]"
<161369871+google-labs-jules[bot]@users.noreply.github.com>
Date: Fri, 30 May 2025 14:19:45 +0000
Subject: [PATCH] Jules was unable to complete the task in time. Please review
the work done so far and provide feedback for Jules to continue.
---
back-codequest/src/core/rotas.js | 38 +-
.../src/functions/CalculateTheProfission.js | 53 +-
.../src/pages/desktop/HomePage.css | 1016 +++++++++--------
.../src/pages/desktop/HomePage.tsx | 336 +++---
.../src/pages/desktop/SavePage.tsx | 290 +++--
.../src/pages/desktop/TestPage01.tsx | 757 ++++++------
.../src/pages/desktop/TestPage02.tsx | 765 +++++++------
.../src/pages/desktop/TestPage03.tsx | 716 ++++++------
.../src/pages/desktop/TestPage04.tsx | 588 ++++------
.../src/pages/desktop/TestPage05.tsx | 555 +++------
10 files changed, 2508 insertions(+), 2606 deletions(-)
diff --git a/back-codequest/src/core/rotas.js b/back-codequest/src/core/rotas.js
index 28b2c07..88d5b5f 100644
--- a/back-codequest/src/core/rotas.js
+++ b/back-codequest/src/core/rotas.js
@@ -1,6 +1,7 @@
const Emails = require('../daos/emails.js');
const Email = require('../dbos/email.js');
const Comunicado = require('./comunicado.js');
+const { calculateJob } = require('../functions/CalculateTheProfission.js'); // Added import
async function inclusao(req, res) {
if(Object.values(req.body).length !=2 || !req.body.id || !req.body.email) {
@@ -170,5 +171,38 @@ async function recuperacaoDeTodos(req, res) {
}
return res.status(200).json(ret);
}
-
-module.exports = { inclusao, atualizacao, remocao, recuperacaoDeUm, recuperacaoDeTodos }
\ No newline at end of file
+
+async function calculateVocationRoute(req, res) {
+ try {
+ const { answers } = req.body;
+
+ // Input Validation
+ if (!answers || !Array.isArray(answers) || answers.length !== 20) {
+ const erro = Comunicado.novo('DDI','Dados Inválidos', 'As respostas fornecidas são inválidas. Esperava-se um array de 20 números.').object;
+ return res.status(400).json(erro);
+ }
+
+ for (const answer of answers) {
+ if (typeof answer !== 'number') {
+ const erro = Comunicado.novo('DDI','Dados Inválidos', 'Todas as respostas devem ser números.').object;
+ return res.status(400).json(erro);
+ }
+ }
+
+ // Call Calculation Logic
+ const result = calculateJob(answers);
+ return res.status(200).json(result);
+
+ } catch (error) {
+ console.error('Error calculating vocational test:', error); // Log the error on the server
+ // Check if the error is from calculateJob's specific validation or a general one
+ if (error.message && (error.message.includes('Missing Questionnarie') || error.message.includes('Any alternative is null') || error.message.includes('Entering invalid data'))) {
+ const erro = Comunicado.novo('DDI','Dados Inválidos', error.message).object;
+ return res.status(400).json(erro);
+ }
+ const erro = Comunicado.novo('PFL','Processamento Falhou', 'Ocorreu um erro ao calcular o resultado do teste vocacional.').object;
+ return res.status(500).json(erro);
+ }
+}
+
+module.exports = { inclusao, atualizacao, remocao, recuperacaoDeUm, recuperacaoDeTodos, calculateVocationRoute }
\ No newline at end of file
diff --git a/back-codequest/src/functions/CalculateTheProfission.js b/back-codequest/src/functions/CalculateTheProfission.js
index 4870101..d1543a0 100644
--- a/back-codequest/src/functions/CalculateTheProfission.js
+++ b/back-codequest/src/functions/CalculateTheProfission.js
@@ -6,20 +6,21 @@ class CalculateTheJob {
#formAnswers
constructor(formAnswers) {
- this.#formAnswers = formAnswers;
+ this.formAnswers = formAnswers;
}
get formAnswers() { return this.#formAnswers }
set formAnswers(formAnswers) {
- const ENNEAGRAM_QUESTIONS_QUANTITY = 25;
+ const EXPECTED_ANSWERS = 20;
if(formAnswers === undefined) throw ('Missing Questionnarie');
- if(formAnswers.length !== ENNEAGRAM_QUESTIONS_QUANTITY) throw ('Any alternative is null');
- for(let line = 0; line < ENNEAGRAM_QUESTIONS_QUANTITY; line++) {
- if(typeof formAnswers[line] !== Number ||
+ if(formAnswers.length !== EXPECTED_ANSWERS) throw ('Any alternative is null');
+ this.#formAnswers = [];
+ for(let line = 0; line < EXPECTED_ANSWERS; line++) {
+ if(typeof formAnswers[line] !== 'number' || // Corrected 'Number' to 'number'
isNaN(formAnswers[line]) ||
- formAnswers[line] !== parseInt(formAnswers[line] ||
- formAnswers[line] <= 0 || formAnswers[line] > 5))
+ formAnswers[line] !== parseInt(formAnswers[line]) || // Corrected logical OR error
+ formAnswers[line] <= 0 || formAnswers[line] > 5)
throw('Entering invalid data');
this.#formAnswers[line] = formAnswers[line];
}
@@ -27,29 +28,29 @@ class CalculateTheJob {
}
function calculateJob(formAnswers){
- formAnswers = new CalculateTheJob(formAnswers);
- const ENNEAGRAM_QUESTIONS_QUANTITY = 45;
- let sumType1;
- let sumType2;
- let sumType3;
- let sumType4;
- let sumType5;
- let resp;
- for(let line = 0; line < ENNEAGRAM_QUESTIONS_QUANTITY; line++) {
- if(line < 5) {
- sumType1 += this.formAnswers[line];
+ const jobCalculator = new CalculateTheJob(formAnswers); // Create instance
+ const QUESTIONS_TO_PROCESS = 20; // Define number of questions to process
+ let sumType1 = 0; // Initialize sumType1
+ let sumType2 = 0; // Initialize sumType2
+ let sumType3 = 0; // Initialize sumType3
+ let sumType4 = 0; // Initialize sumType4
+ let sumType5 = 0; // Initialize sumType5
+ let resp = []; // Initialize resp
+ for(let line = 0; line < QUESTIONS_TO_PROCESS; line++) { // Loop through questions to process
+ if(line < 4) { // Questions 0-3 for sumType1
+ sumType1 += jobCalculator.formAnswers[line]; // Access answers from instance
}
- if(line >= 5 && line < 10) {
- sumType2 += this.formAnswers[line];
+ if(line >= 4 && line < 8) { // Questions 4-7 for sumType2
+ sumType2 += jobCalculator.formAnswers[line]; // Access answers from instance
}
- if(line >= 10 && line < 15) {
- sumType3 += this.formAnswers[line];
+ if(line >= 8 && line < 12) { // Questions 8-11 for sumType3
+ sumType3 += jobCalculator.formAnswers[line]; // Access answers from instance
}
- if(line >= 15 && line < 20) {
- sumType4 += this.formAnswers[line];
+ if(line >= 12 && line < 16) { // Questions 12-15 for sumType4
+ sumType4 += jobCalculator.formAnswers[line]; // Access answers from instance
}
- if(line >= 20 && line < 25) {
- sumType5 += this.formAnswers[line];
+ if(line >= 16 && line < 20) { // Questions 16-19 for sumType5
+ sumType5 += jobCalculator.formAnswers[line]; // Access answers from instance
}
}
if(sumType1 >= 15) resp[0] = sumType1;
diff --git a/front-codequest/src/pages/desktop/HomePage.css b/front-codequest/src/pages/desktop/HomePage.css
index b3e5e36..38e1271 100644
--- a/front-codequest/src/pages/desktop/HomePage.css
+++ b/front-codequest/src/pages/desktop/HomePage.css
@@ -1,489 +1,527 @@
-.home-page-desktop {
- position: relative;
- width: 100%;
- text-align: left;
- font-size: 1.6vw; /* Use vw para tamanho de fonte responsivo */
- color: var(--color-white);
- font-family: var(--font-tt-mussels-trl);
- overflow-x: hidden;
-}
-
-.background-contact-icon {
- height: 100%;
- width: 100%;
- max-width: 100%;
-}
-
-.cdquestinsta {
- margin-left: 90px;
- margin-top: -55px;
-}
-
-.cdquestmail {
- margin-left: 90px;
- margin-top: 15px;
-}
-
-.cdquestloca {
- margin-left: 90px;
- margin-top: -50px;
-}
-.logos-icon {
- position: absolute;
- top: 195px;
- left: 127px;
- width: 330px;
- height: 255px;
- object-fit: cover;
-}
-
-.vector-icon {
- position: absolute;
- left: 0;
-}
-
-.gmail {
- position: absolute;
- height: 29.06%;
- width: 72.39%;
- top: 34.54%;
- right: 27.61%;
- bottom: 36.41%;
-}
-
-.codequest- {
- text-decoration: underline;
- position: absolute;
- width: 65.21%;
- top: 26.31%;
- left: 34.79%;
- color: inherit;
- display: inline-block;
-}
-
-.instagram{
- position: absolute;
-}
-
-.gmail{
- position: absolute;
-}
-
-.local{
- position: absolute;
-}
-
-.local {
- height: 30%;
- top: 69%;
-}
-
-
-
-.vector-icon,
-.vector-icon1,
-.vector-icon2 {
- width: 70px;
- height: 70px;
-}
-
-.vector-icon:hover,
-.vector-icon1:hover,
-.vector-icon2:hover {
- transform: scale(1.2);
- transition: transform 0.2s ease-in-out;
-}
-
-.contact-page,
-.socials {
- position: absolute;
- object-fit: cover;
- top: 26.74%;
- right: 5.99%;
- bottom: 28.41%;
- left: 59.11%;
-}
-
-.contact-page {
- height: 23.96%;
- width: 100%;
- top: 76.04%;
- right: 0;
- bottom: 0;
- left: 0;
-}
-
-.image-10-icon,
-.rock-of-the-astronaut-1 {
- position: absolute;
- top: 0;
- left: 0;
- width: 1925px;
- height: 945px;
- object-fit: cover;
-}
-
-.rock-of-the-astronaut-1 {
- height: 26.14%;
- width: 33.18%;
- right: 8.49%;
- bottom: 73.86%;
- left: 58.33%;
- max-width: 100%;
- overflow: hidden;
- max-height: 100%;
-}
-
-.about-us {
- margin: 0;
- position: absolute;
- top: 0;
- left: 0;
- font-size: inherit;
- font-weight: 700;
- font-family: inherit;
- display: inline-block;
- width: 389.01px;
-}
-
-.rectangle-title {
- position: absolute;
- top: 101px;
- left: 0;
- background-color: var(--color-midnightblue);
- width: 212.55px;
- height: 32px;
- overflow: hidden;
-}
-
-.rectangle-high {
- position: relative;
- border-radius: 0px 0px 20px 20px;
- background: linear-gradient(90deg, #6113a8, rgba(69, 63, 203, 0));
- backdrop-filter: blur(25px);
- width: 100%;
- height: 96px;
-}
-
-.title-about {
- position: absolute;
- top: 116px;
- left: 62.16px;
- width: 389.01px;
- height: 133px;
- font-size: var(--font-size-81xl);
-}
-
-.c {
- font-family: var(--font-tt-mussels-trl);
-}
-
-.txtAbout {
- margin: 0;
- position: absolute;
- top: 336px;
- left: 62.16px;
- font-size: var(--font-size-21xl);
- display: inline-block;
- width: 1700.42px;
- font-family: inherit;
-}
-
-.image-6-icon {
- position: absolute;
- top: 0;
- left: 0;
- border-radius: var(--br-107xl);
- width: 271.71px;
- height: 256px;
- object-fit: cover;
- cursor: pointer;
- display: flex;
- align-items: center;
- justify-content: center;
- cursor: pointer;
- transition: transform 0.3s ease;
-}
-
-.image-6-icon:hover {
- transform: scale(1.1);
-}
-
-.gustavo-miguel {
- margin: 0;
- position: absolute;
- top: 258px;
- left: 15.99px;
- font-size: inherit;
- font-weight: 400;
- font-family: inherit;
- display: inline-block;
- width: 234.61px;
- text-shadow: 2px 1px 0#2d0159;
-}
-
-.gustavo,
-.image-4-icon {
- position: absolute;
- top: 545px;
- left: 117.3px;
- width: 271.71px;
- height: 297px;
- cursor: pointer;
- display: flex;
- align-items: center;
- justify-content: center;
- cursor: pointer;
- transition: transform 0.3s ease;
-}
-
-.image-4-icon:hover {
- transform: scale(1.1);
-}
-
-.image-4-icon {
- top: 0;
- left: 0;
- border-radius: var(--br-107xl);
- width: 269.7px;
- height: 252px;
- object-fit: cover;
-}
-
-.kauan-piacente {
- margin: 0;
- position: absolute;
- top: 258px;
- left: 18.97px;
- font-size: inherit;
- font-weight: 400;
- font-family: inherit;
- display: inline-block;
- width: 235.61px;
- text-shadow: 2px 1px 0#2d0159;
-}
-
-.kauan {
- position: absolute;
- top: 545px;
- left: 786.04px;
- width: 269.7px;
- height: 297px;
-}
-
-.joo-victor {
- margin: 0;
- position: absolute;
- top: 264px;
- left: 49.08px;
- font-size: inherit;
- font-weight: 400;
- font-family: inherit;
- display: inline-block;
- width: 167.43px;
- text-shadow: 2px 1px 0#2d0159;
-}
-
-.image-5-icon,
-.joo {
- position: absolute;
- width: 269.7px;
-}
-
-.image-5-icon {
- top: 0;
- left: 0;
- border-radius: var(--br-107xl);
- height: 263px;
- object-fit: cover;
- cursor: pointer;
- display: flex;
- align-items: center;
- justify-content: center;
- transition: transform 0.3s ease;
-}
-
-.image-5-icon:hover {
- transform: scale(1.1);
-}
-
-.joo {
- top: 539px;
- left: 1466.81px;
- height: 303px;
-}
-
-.about-page,
-.background-high-icon {
- position: absolute;
- top: 1083px;
- left: 0;
- width: 1925px;
- height: 945px;
-
-}
-
-.background-high-icon {
- top: 0;
- height: 1083px;
- object-fit: cover;
-}
-
-.astronaut-icon,
-.rectangle-high-icon {
- position: absolute;
- top: 96px;
- left: 1079px;
- width: 828px;
- height: 987px;
- object-fit: cover;
-}
-
-.rectangle-high-icon {
- top: 0;
- left: 0;
- border-radius: var(--br-xl);
- width: 1925px;
- height: 96px;
-}
-
-.logo-branco-icon {
- position: absolute;
- top: 15px;
- left: 42px;
- width: 295px;
- height: 66px;
- object-fit: cover;
-}
-
-.about {
- margin: 0;
- top: 0;
- left: 0;
- font-size: inherit;
- font-weight: 700;
- font-family: inherit;
- display: inline-block;
- width: 179px;
- cursor: pointer;
- cursor: pointer;
- color: var(--color-white);
- font-family: var(--font-tt-mussels-trl);
- text-decoration: none;
- transition: transform 0.3s ease;
-}
-
-.about:active {
- transform: scale(0.9);
-}
-
-.about,
-.contact,
-.high,
-.text-high {
- position: absolute;
- height: 65px;
-}
-
-.contact {
- margin: 0;
- top: 0;
- left: 294px;
- font-size: inherit;
- font-weight: 700;
- font-family: inherit;
- display: inline-block;
- width: 179px;
- cursor: pointer;
- color: var(--color-white);
- font-family: var(--font-tt-mussels-trl);
- text-decoration: none;
- transition: transform 0.3s ease;
-}
-
-.contact:active {
- transform: scale(0.9);
-}
-
-.text-high {
- top: 16px;
- left: 1368px;
- width: 473px;
-}
-
-.high {
- position: fixed;
- top: 0;
- left: 0;
- width: 1925px;
- height: 59px;
- text-align: left;
- font-size: var(--font-size-31xl);
- color: var(--color-white);
- font-family: var(--font-tt-mussels-trl);
- z-index: 1000;
-
-}
-
-.seu-teste-tecnolgico-container {
- position: absolute;
- top: 0;
- left: 0;
- font-size: inherit;
- font-weight: 700;
- font-family: inherit;
-}
-
-.boto-iniciar {
- margin: 40px;
- width: 270px;
- height: 70px;
- position: absolute;
- top: calc(50% + 127.5px);
- left: 450px;
- background-image: linear-gradient(to right, #D100FF, #DB00FF);
- box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
- border: none;
- border-radius: var(--br-31xl);
- cursor: pointer;
- align-items: center;
- justify-content: center;
- transition: transform 0.3s ease;
- font-size: var(--font-size-21xl);
- font-weight: bold;
-}
-
-.boto-iniciar:active {
- transform: scale(0.9);
-}
-
-.title4 {
- position: absolute;
- top: 260px;
- left: 142px;
- width: 1026px;
- height: 495px;
- position: absolute;
- font-size: inherit;
- font-weight: 700;
- font-family: inherit;
-}
-
-.high-page {
- top: 0;
- left: 0;
- width: 100%; /* Defina a largura que você deseja, por exemplo, 100% para ocupar toda a largura */
- height: 70px; /* Defina a altura que você deseja, por exemplo, 70px */
- font-size: var(--font-size-131xl);
-}
-
-
-.home-page-desktop {
- position: relative;
- width: 100%;
- height: 2659px;
- text-align: left;
- font-size: var(--font-size-16xl);
- color: var(--color-white);
- font-family: var(--font-tt-mussels-trl);
-}
+/* General Reset and Base Styles */
+body, html {
+ margin: 0;
+ padding: 0;
+ width: 100%;
+ overflow-x: hidden; /* Prevent horizontal scrollbars caused by minor overflows */
+ box-sizing: border-box;
+ font-family: var(--font-tt-mussels-trl), sans-serif; /* Fallback font */
+}
+
+*, *:before, *:after {
+ box-sizing: inherit;
+}
+
+.home-page-desktop {
+ position: relative;
+ width: 100%;
+ text-align: left;
+ color: var(--color-white);
+ font-family: var(--font-tt-mussels-trl);
+ /* overflow-x: hidden; /* Already on body, but keep if needed for specific structure */
+}
+
+/* Variables (assuming they are defined elsewhere, e.g., :root or a theme file) */
+:root {
+ --font-tt-mussels-trl: "TT Mussels Trl", sans-serif; /* Example, ensure this font is loaded */
+ --color-white: #ffffff;
+ --color-midnightblue: #2d0159; /* Example */
+ --br-107xl: 126px; /* Example */
+ --br-31xl: 50px; /* Example */
+ --font-size-16xl: 1.5rem; /* Base for smaller elements */
+ --font-size-21xl: 1.75rem;
+ --font-size-31xl: 2rem;
+ --font-size-81xl: 4rem;
+ --font-size-131xl: 6rem;
+
+ /* Responsive Breakpoints (examples, align with your responsive.tsx if possible) */
+ --screen-mobile: 480px;
+ --screen-tablet: 768px;
+ --screen-desktop: 1024px;
+}
+
+
+/* High Section (Fixed Header) */
+.high {
+ position: fixed; /* Keep fixed for header behavior */
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: auto; /* Adjust height based on content */
+ min-height: 70px; /* Minimum height */
+ background: linear-gradient(90deg, #6113a8, rgba(69, 63, 203, 0.8)); /* Slightly more solid gradient */
+ backdrop-filter: blur(15px); /* Adjusted blur */
+ z-index: 1000;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 10px 20px; /* Vertical and horizontal padding */
+ box-shadow: 0 2px 10px rgba(0,0,0,0.2); /* Subtle shadow */
+}
+
+.logo-branco-icon {
+ height: 50px; /* Adjust height, width will auto-scale */
+ width: auto;
+ max-width: 250px; /* Prevent it from becoming too large */
+ object-fit: contain;
+}
+
+.text-high {
+ display: flex;
+ align-items: center;
+ gap: 20px; /* Space between "about" and "contact" */
+}
+
+.text-high .about,
+.text-high .contact {
+ font-size: var(--font-size-21xl); /* Base size, adjust in media queries */
+ font-weight: 700;
+ color: var(--color-white);
+ text-decoration: none;
+ cursor: pointer;
+ padding: 5px 10px;
+ transition: transform 0.3s ease, color 0.3s ease;
+}
+
+.text-high .about:hover,
+.text-high .contact:hover {
+ transform: scale(1.1);
+ color: #ddd; /* Slight hover effect */
+}
+
+/* Hero Section (high-page content) */
+.high-page {
+ display: flex; /* Use flex for overall layout */
+ flex-direction: column; /* Stack children vertically by default */
+ align-items: center; /* Center children horizontally */
+ justify-content: center; /* Center children vertically (if section has fixed height) */
+ width: 100%;
+ min-height: 100vh; /* Make it at least full viewport height */
+ padding-top: 90px; /* Account for fixed header height */
+ position: relative; /* For positioning background image */
+ text-align: center; /* Center text for mobile */
+ overflow: hidden; /* Prevent astronaut from overflowing weirdly on resize */
+}
+
+.background-high-icon {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ object-fit: cover; /* Cover the entire area */
+ z-index: -1; /* Behind content */
+}
+
+.hero-content {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ width: 90%; /* Max width for content */
+ max-width: 1200px; /* Prevent content from becoming too wide */
+ position: relative; /* Ensure z-index works for children if needed */
+ z-index: 1;
+}
+
+.title-and-button {
+ width: 100%;
+}
+
+.title4 {
+ font-size: var(--font-size-81xl); /* Base size for title */
+ font-weight: 700;
+ color: var(--color-white);
+ margin-bottom: 30px; /* Space below title */
+ line-height: 1.2;
+}
+
+.title4 p {
+ margin: 0; /* Remove default paragraph margins */
+}
+
+.astronaut-icon {
+ width: 300px; /* Base size for astronaut */
+ max-width: 80%; /* Ensure it doesn't overflow on small screens */
+ height: auto;
+ margin-top: 20px; /* Space above astronaut on mobile */
+ object-fit: contain;
+}
+
+.boto-iniciar {
+ width: 220px;
+ height: 60px;
+ background-image: linear-gradient(to right, #D100FF, #DB00FF);
+ box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
+ border: none;
+ border-radius: var(--br-31xl);
+ cursor: pointer;
+ font-size: var(--font-size-21xl);
+ font-weight: bold;
+ color: var(--color-white);
+ transition: transform 0.3s ease;
+ margin-top: 20px; /* Space above button */
+}
+
+.boto-iniciar:hover {
+ transform: scale(1.05);
+}
+
+/* About Us Section */
+.about-page {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding: 50px 20px; /* Vertical and horizontal padding */
+ position: relative; /* For background image positioning */
+ width: 100%;
+}
+
+.image-10-icon { /* Background for about page */
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ z-index: -1;
+}
+
+.title-about-container {
+ text-align: center;
+ margin-bottom: 30px;
+ position: relative; /* For the rectangle-title accent */
+}
+
+.about-us {
+ font-size: var(--font-size-81xl);
+ font-weight: 700;
+ margin: 0;
+ position: relative; /* Ensure it's above the rectangle */
+ z-index: 1;
+}
+
+.rectangle-title {
+ position: absolute;
+ bottom: -5px; /* Position under the title */
+ left: 50%;
+ transform: translateX(-50%);
+ background-color: var(--color-midnightblue);
+ width: 150px; /* Shorter accent */
+ height: 15px; /* Thicker accent */
+ z-index: 0;
+}
+
+.txtAbout-container {
+ width: 90%;
+ max-width: 800px; /* Control text width for readability */
+ margin-bottom: 40px;
+}
+
+.txtAbout {
+ font-size: var(--font-size-21xl);
+ text-align: center; /* Center align the paragraph */
+ line-height: 1.6;
+ margin:0;
+}
+
+.members-container {
+ display: flex;
+ justify-content: space-around;
+ flex-wrap: wrap; /* Allow members to wrap on smaller screens */
+ width: 100%;
+ max-width: 1200px; /* Max width for members area */
+}
+
+.member-card {
+ width: 280px; /* Base width for member cards */
+ margin: 20px;
+ text-align: center;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.member-card img { /* Common style for member images */
+ width: 200px; /* Fixed size for consistency */
+ height: 200px;
+ border-radius: 50%; /* Circular images */
+ object-fit: cover;
+ margin-bottom: 15px;
+ transition: transform 0.3s ease;
+ box-shadow: 0 4px 15px rgba(0,0,0,0.2);
+}
+
+.member-card img:hover {
+ transform: scale(1.1);
+}
+
+.member-name {
+ font-size: var(--font-size-21xl); /* Adjusted for consistency */
+ font-weight: 400;
+ text-shadow: 1px 1px 0px #2d0159; /* Simplified shadow */
+}
+
+.rock-of-the-astronaut-1 {
+ display: none; /* Hide by default, show on larger screens if desired */
+ width: 200px; /* Example size */
+ height: auto;
+ position: absolute; /* If needed for specific placement, but try to avoid */
+ /* top: ...; left: ...; */
+}
+
+
+/* Contact Section */
+.contact-page {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding: 50px 20px;
+ text-align: center;
+ position: relative;
+ width: 100%;
+ min-height: 50vh; /* Ensure it has some height */
+}
+
+.background-contact-icon {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ z-index: -1;
+}
+
+.logos-icon { /* Decorative partner logos */
+ width: 250px; /* Adjust size */
+ height: auto;
+ margin-bottom: 30px;
+ object-fit: contain;
+}
+
+.socials {
+ display: flex;
+ flex-direction: column; /* Stack social items */
+ align-items: center; /* Center items if stacked, or flex-start if labels are long */
+}
+
+.social-item {
+ display: flex;
+ align-items: center;
+ margin-bottom: 20px; /* Space between social items */
+ text-decoration: none;
+ color: var(--color-white);
+}
+
+.vector-icon { /* Common style for social icons */
+ width: 40px; /* Adjust size */
+ height: 40px;
+ margin-right: 15px; /* Space between icon and text */
+ transition: transform 0.2s ease-in-out;
+}
+.vector-icon:hover {
+ transform: scale(1.2);
+}
+/* Specific icon classes if needed, otherwise .vector-icon can be used for all */
+.vector-icon1 {} /* Instagram */
+.vector-icon2 {} /* Location */
+
+
+.social-text { /* Common style for social text */
+ font-size: var(--font-size-16xl); /* Adjust size */
+ margin: 0; /* Reset margins */
+}
+/* Remove specific margin/positioning for these as flexbox handles it */
+.cdquestinsta, .cdquestmail, .cdquestloca {
+ margin: 0;
+}
+
+
+/* Media Queries */
+
+/* Mobile Devices (e.g., max-width: 480px or 576px) */
+@media (max-width: 576px) {
+ .high {
+ min-height: 60px;
+ padding: 5px 15px;
+ }
+ .logo-branco-icon {
+ height: 40px;
+ }
+ .text-high {
+ gap: 10px; /* Smaller gap */
+ }
+ .text-high .about, .text-high .contact {
+ font-size: var(--font-size-16xl); /* Smaller font for header links */
+ padding: 5px;
+ }
+
+ .title4 {
+ font-size: 2.5rem; /* Significantly smaller title */
+ }
+ .astronaut-icon {
+ width: 200px; /* Smaller astronaut */
+ margin-top: 30px;
+ }
+ .boto-iniciar {
+ width: 180px;
+ height: 50px;
+ font-size: var(--font-size-16xl); /* Smaller button text */
+ }
+
+ .about-us {
+ font-size: 2.8rem; /* Smaller section title */
+ }
+ .rectangle-title {
+ width: 100px;
+ height: 10px;
+ }
+ .txtAbout {
+ font-size: var(--font-size-16xl); /* Smaller about text */
+ }
+ .member-card {
+ width: 80%; /* Member cards take more width */
+ margin: 15px 0;
+ }
+ .member-card img {
+ width: 150px;
+ height: 150px;
+ }
+ .member-name {
+ font-size: var(--font-size-16xl);
+ }
+
+ .logos-icon {
+ width: 180px;
+ margin-bottom: 20px;
+ }
+ .vector-icon {
+ width: 30px;
+ height: 30px;
+ margin-right: 10px;
+ }
+ .social-text {
+ font-size: 0.9rem; /* Smaller social text */
+ }
+ .social-item {
+ margin-bottom: 15px;
+ }
+}
+
+/* Tablet Devices (e.g., min-width: 577px and max-width: 768px) */
+@media (min-width: 577px) and (max-width: 768px) {
+ .high-page .hero-content {
+ /* Could change to row if space allows */
+ }
+ .title4 {
+ font-size: 3.5rem;
+ }
+ .astronaut-icon {
+ width: 250px;
+ }
+ .boto-iniciar {
+ width: 200px;
+ height: 55px;
+ }
+
+ .about-us {
+ font-size: 3rem;
+ }
+ .txtAbout {
+ font-size: 1.1rem;
+ }
+ .member-card {
+ width: 45%; /* Two cards per row */
+ }
+ .member-card img {
+ width: 180px;
+ height: 180px;
+ }
+ .socials {
+ flex-direction: row; /* Social items in a row for tablet */
+ flex-wrap: wrap;
+ justify-content: center;
+ gap: 20px;
+ }
+ .social-item {
+ margin-bottom: 10px; /* Adjust spacing for row layout */
+ }
+}
+
+/* Desktop (adjustments for larger screens if needed) */
+@media (min-width: 769px) {
+ .high-page .hero-content {
+ flex-direction: row; /* Title/button on one side, astronaut on other */
+ justify-content: space-between; /* Or space-around */
+ align-items: center;
+ text-align: left; /* Align text to left on desktop */
+ }
+ .title-and-button {
+ width: 50%; /* Example width */
+ max-width: 600px;
+ }
+ .astronaut-icon {
+ width: 400px; /* Larger astronaut for desktop */
+ max-width: 45%;
+ margin-top: 0; /* Reset margin */
+ }
+ .title4 {
+ font-size: var(--font-size-131xl); /* Restore larger desktop font size */
+ }
+ .boto-iniciar {
+ margin-left: 0; /* Align button to the left of its container */
+ }
+ .about-us {
+ font-size: var(--font-size-81xl);
+ }
+ .txtAbout {
+ font-size: var(--font-size-21xl);
+ text-align: left;
+ }
+ .member-card {
+ width: 30%; /* Three cards per row */
+ }
+ .socials {
+ flex-direction: row;
+ justify-content: space-evenly; /* Spread out social items */
+ width: 100%;
+ max-width: 800px; /* Limit width of social links container */
+ }
+ .social-item {
+ margin-bottom: 0;
+ }
+ .rock-of-the-astronaut-1 {
+ display: block; /* Show this decorative image on desktop */
+ position: absolute;
+ width: 25%;
+ height: auto;
+ bottom: 50px; /* Example positioning */
+ right: 50px;
+ z-index: 0;
+ }
+}
+
+/* Ensure any fixed dimensions on .home-page-desktop itself are removed or responsive */
+.home-page-desktop {
+ /* height: 2659px; Remove fixed height, let content define it */
+}
+
+/* Legacy absolute positioning from original CSS - to be removed or refactored */
+/* .instagram, .gmail, .local { position: absolute; } -> Handled by flex on .social-item */
+/* .cdquestinsta, .cdquestmail, .cdquestloca { margin-left: ...; margin-top: ...; } -> Handled by flex spacing */
+/* .logos-icon { position: absolute; } -> Now positioned by flex in .contact-page */
+/* .title-about, .txtAbout, .gustavo, .kauan, .joo { position: absolute; } -> Handled by flex/flow */
+/* .high .logo-branco-icon, .high .text-high { position: absolute; } -> Handled by flex on .high */
+/* .high-page .title4, .high-page .astronaut-icon, .high-page .boto-iniciar { position: absolute; } -> Handled by flex on .high-page / .hero-content */
+
+/* Ensure .rectangle-high is not used if .high is the header itself */
+.rectangle-high { display: none; } /* This was likely for the old fixed-size header background */
+
+/* Cleanup any remaining fixed widths that might cause overflow */
+.about-page, .contact-page { /* These were 1925px */
+ width: 100%;
+}
+
+/* Final check for any remaining large fixed dimensions or problematic absolute positions */
+/* The goal is a fluid layout that adapts, not fixed pixel perfection from the original desktop-only design */
diff --git a/front-codequest/src/pages/desktop/HomePage.tsx b/front-codequest/src/pages/desktop/HomePage.tsx
index 6c022b8..9eedc38 100644
--- a/front-codequest/src/pages/desktop/HomePage.tsx
+++ b/front-codequest/src/pages/desktop/HomePage.tsx
@@ -1,170 +1,166 @@
-import { FunctionComponent, useEffect, useState } from "react";
-import "bootstrap/dist/css/bootstrap.min.css";
-import { Button } from "react-bootstrap";
-import "./HomePage.css";
-import { Link as RouterLink } from 'react-router-dom';
-import { Link as ScrollLink } from 'react-scroll';
-
-const HomePageDesktop: FunctionComponent = () => {
- const [displayText, setDisplayText] = useState("");
- const [redirecting, setRedirecting] = useState(false);
-
- const textToType = `Nós somos um grupo de estudantes do Colégio Técnico de Campinas, e esse é o nosso Trabalho de Conclusão de Curso do Departamento de Processamento de Dados.`;
-
- useEffect(() => {
- const aboutPageContainer = document.getElementById("aboutPageContainer");
-
- const handleScroll = () => {
- if (aboutPageContainer) {
- const rect = aboutPageContainer.getBoundingClientRect();
-
- // Verifique se o elemento aboutPageContainer está no campo de visão do usuário.
- if (rect.top < window.innerHeight * 0.8) {
- let currentIndex = 0;
- const interval = setInterval(() => {
- if (currentIndex <= textToType.length) {
- setDisplayText(textToType.substring(0, currentIndex));
- currentIndex++;
- } else {
- clearInterval(interval);
- }
- }, 30); // Velocidade da digitação (50 milissegundos)
- window.removeEventListener("scroll", handleScroll); // Remova o ouvinte após iniciar a animação.
- }
- }
- };
-
- window.addEventListener("scroll", handleScroll);
-
- return () => {
- window.removeEventListener("scroll", handleScroll);
- };
- }, [textToType]);
-
- const handleRedirect = () => {
- setRedirecting(true);
-
- // Simule um atraso de 1 segundo antes do redirecionamento
- setTimeout(() => {
- setRedirecting(false);
- // Realize o redirecionamento real no local apropriado dentro da função handleRedirect.
- // history.push("/testpage01");
- }, 1000); // 1000 milissegundos = 1 segundo
- };
-
- return (
-
-
-
-
-
-
-
SEU TESTE
-
TECNOLÓGICO
-
AQUI.
-
-
- {redirecting ? "Aguarde..." : "INICIAR"}
-
-
-
-
-
-
-
-
-
-
-
- {displayText}
-
-
-
-
-
- Gustavo Miguel
-
-
-
-
-
- Kauan Piacente
-
-
-
-
- João Victor
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@codequest_
-
-
-
-
-
-
-
codequest03@gmail.com
-
-
-
-
-
-
-
R. Culto à Ciência - Centro, Campinas - SP
-
-
-
-
-
-
-
-
-
- );
-};
-
-export default HomePageDesktop;
+import { FunctionComponent, useEffect, useState } from "react";
+import "bootstrap/dist/css/bootstrap.min.css";
+import { Button } from "react-bootstrap";
+import "./HomePage.css";
+import { Link as RouterLink } from 'react-router-dom';
+import { Link as ScrollLink } from 'react-scroll';
+
+const HomePageDesktop: FunctionComponent = () => {
+ const [displayText, setDisplayText] = useState("");
+ const [redirecting, setRedirecting] = useState(false);
+
+ const textToType = `Nós somos um grupo de estudantes do Colégio Técnico de Campinas, e esse é o nosso Trabalho de Conclusão de Curso do Departamento de Processamento de Dados.`;
+
+ useEffect(() => {
+ const aboutPageContainer = document.getElementById("aboutPageContainer");
+
+ const handleScroll = () => {
+ if (aboutPageContainer) {
+ const rect = aboutPageContainer.getBoundingClientRect();
+ if (rect.top < window.innerHeight * 0.8 && displayText === "") { // Start typing only once
+ let currentIndex = 0;
+ const interval = setInterval(() => {
+ if (currentIndex <= textToType.length) {
+ setDisplayText(textToType.substring(0, currentIndex));
+ currentIndex++;
+ } else {
+ clearInterval(interval);
+ }
+ }, 30);
+ window.removeEventListener("scroll", handleScroll);
+ }
+ }
+ };
+
+ window.addEventListener("scroll", handleScroll);
+
+ return () => {
+ window.removeEventListener("scroll", handleScroll);
+ };
+ }, [textToType, displayText]); // Added displayText to dependencies
+
+ const handleRedirect = () => {
+ setRedirecting(true);
+ setTimeout(() => {
+ setRedirecting(false);
+ // Navigation is handled by RouterLink, this is for visual feedback if needed
+ }, 1000);
+ };
+
+ return (
+
+
+
+
+
+ SOBRE NÓS
+
+
+ CONTATO
+
+
+
+
+
+
+
+
+
+
SEU TESTE
+
TECNOLÓGICO
+
AQUI.
+
+
+
+ {redirecting ? "Aguarde..." : "INICIAR"}
+
+
+
+
+
+
+
+
+
+
+
+
+
{/* Changed h2 to p for semantic text */}
+ {displayText}
+
+
+ {/* Added wrapper */}
+
+
+
+ Gustavo Miguel
+
+
+
+
+
+ Kauan Piacente
+
+
+
+
+
+ João Victor
+
+
+
+
+
+
{/* Changed to footer for semantics */}
+
+
+
+
+
+
+
+
+
codequest03@gmail.com
+
+
+
+
+
+ );
+};
+
+export default HomePageDesktop;
diff --git a/front-codequest/src/pages/desktop/SavePage.tsx b/front-codequest/src/pages/desktop/SavePage.tsx
index 1e03a3b..97e7ca7 100644
--- a/front-codequest/src/pages/desktop/SavePage.tsx
+++ b/front-codequest/src/pages/desktop/SavePage.tsx
@@ -1,99 +1,191 @@
-import { FunctionComponent, useState } from "react";
-import "./SavePage.css";
-import { Link } from 'react-router-dom';
-import "bootstrap/dist/css/bootstrap.min.css";
-import { Button } from "react-bootstrap";
-
-const SavePageDesktop: FunctionComponent = () => {
- const [email, setEmail] = useState("");
- const [redirecting, setRedirecting] = useState(false);
-
- const handleEmailChange = (e: React.ChangeEvent) => {
- setEmail(e.target.value);
- };
-
- const handleRedirect = async () => {
- if (email) {
- setRedirecting(true);
-
- try {
- const response = await fetch('http://localhost:3306/emails/incluir', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({ email }), // Envie o email digitado pelo usuário para o backend
- });
-
- if (response.ok) {
- // Se a resposta do servidor foi bem-sucedida, redirecione para a homepage ou faça outra ação necessária
- setTimeout(() => {
- setRedirecting(false);
- // Realize o redirecionamento aqui, por exemplo:
- // history.push("/");
- }, 1000);
- } else {
- // Trate a falha na requisição
- console.error('Falha ao enviar e-mail');
- setRedirecting(false);
- }
- } catch (error) {
- // Trate erros de rede ou outros erros
- console.error('Erro ao enviar e-mail:', error);
- setRedirecting(false);
- }
- }
- };
-
-
-
- return (
-
-
-
-
-
-
-
-
-
-
-
- {redirecting ? "Aguarde..." : "CONTINUAR"}
-
-
-
-
Finalizando seu teste!
-
- por favor, digite seu email e nós enviaremos seu teste em breve
-
-
-
-
- {redirecting ? "Aguarde..." : "X"}
-
-
-
-
-
- );
-};
-
-export default SavePageDesktop;
+import { FunctionComponent, useState, useEffect } from "react"; // Added useEffect
+import "./SavePage.css";
+import { Link, useNavigate } from 'react-router-dom'; // Added useNavigate
+import "bootstrap/dist/css/bootstrap.min.css";
+import { Button } from "react-bootstrap";
+
+const SavePageDesktop: FunctionComponent = () => {
+ const [email, setEmail] = useState(""); // Keep if email feature is desired (optional for now)
+ const [isLoading, setIsLoading] = useState(false);
+ const [error, setError] = useState(null);
+ const navigate = useNavigate(); // Initialize useNavigate
+
+ // Optional: keep handleEmailChange if email input is kept
+ const handleEmailChange = (e: React.ChangeEvent) => {
+ setEmail(e.target.value);
+ };
+
+ const handleProceed = async () => {
+ setIsLoading(true);
+ setError(null);
+
+ try {
+ let allAnswers: (number | null)[] = [];
+ for (let i = 1; i <= 5; i++) {
+ const key = `respostasPage${i}`;
+ const pageAnswersString = localStorage.getItem(key);
+ if (pageAnswersString) {
+ try {
+ const parsedAnswers = JSON.parse(pageAnswersString);
+ // Ensure correct property names if they differ from resposta1-4
+ allAnswers.push(parsedAnswers.resposta1 ?? null);
+ allAnswers.push(parsedAnswers.resposta2 ?? null);
+ allAnswers.push(parsedAnswers.resposta3 ?? null);
+ allAnswers.push(parsedAnswers.resposta4 ?? null);
+ } catch (e) {
+ console.error(`Error parsing localStorage for ${key}:`, e);
+ // Add nulls for all 4 questions of the page if parsing fails
+ allAnswers.push(null, null, null, null);
+ }
+ } else {
+ console.warn(`No data found in localStorage for ${key}`);
+ // Add nulls for all 4 questions of the page if data is missing
+ allAnswers.push(null, null, null, null);
+ }
+ }
+
+ if (allAnswers.length !== 20) {
+ // This check might be redundant if the loop always pushes 4 values
+ // but good for sanity check if logic changes
+ console.error("Collected answers length is not 20:", allAnswers.length);
+ throw new Error("Não foi possível coletar todas as respostas. Por favor, tente refazer o teste.");
+ }
+
+ // Replace nulls with 3 (neutral) before sending to backend
+ const finalAnswers = allAnswers.map(ans => ans === null ? 3 : ans);
+
+ // **Optional Email Submission (Commented out as per instruction)**
+ // if (email) {
+ // try {
+ // const emailResponse = await fetch('http://localhost:3306/emails/incluir', { // Ensure this port and path are correct
+ // method: 'POST',
+ // headers: { 'Content-Type': 'application/json' },
+ // body: JSON.stringify({ email }),
+ // });
+ // if (!emailResponse.ok) console.error('Falha ao enviar e-mail');
+ // } catch (emailError) {
+ // console.error('Erro ao enviar e-mail:', emailError);
+ // }
+ // }
+
+ // **Call Vocational Test API:**
+ const response = await fetch('/api/calculate-vocation', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ answers: finalAnswers }),
+ });
+
+ if (!response.ok) {
+ const errorText = await response.text();
+ throw new Error(`Erro do servidor: ${response.status} ${errorText}`);
+ }
+
+ const result = await response.json();
+
+ if (!result || !Array.isArray(result) || result.length === 0) { // Check for empty array too
+ console.error("Resultado inesperado ou vazio do servidor:", result);
+ throw new Error("Resultado inesperado ou vazio do servidor.");
+ }
+
+ const scores: number[] = result.map(score => typeof score === 'number' ? score : 0); // Ensure scores are numbers
+ let maxScore = -1;
+ let bestVocationIndex = -1;
+
+ for (let i = 0; i < scores.length; i++) {
+ if (scores[i] > maxScore) {
+ maxScore = scores[i];
+ bestVocationIndex = i;
+ }
+ }
+
+ // Ensure there's at least one score and it's not negative from initialization
+ if (bestVocationIndex === -1 && scores.length > 0) {
+ // If all scores are 0 or less (e.g. from default mapping), pick first as a fallback
+ // or handle as "undetermined". For now, let's assume valid positive scores are expected.
+ // If all scores are 0 (e.g. if all answers were neutral and backend returns 0s),
+ // this logic might need a tie-breaking rule or specific handling.
+ // For now, if maxScore remains <=0 and there are scores, it indicates no clear preference.
+ if (maxScore <= 0) {
+ console.warn("Nenhuma vocação teve pontuação positiva clara. Verifique a lógica de pontuação ou respostas.", scores);
+ // Fallback: could navigate to a generic "results" page or show a message.
+ // For now, let's throw an error to indicate this state.
+ throw new Error("Não foi possível determinar uma vocação clara com as pontuações atuais.");
+ }
+ }
+
+
+ const vocationRoutes = [
+ "/dessoftware", // Index 0
+ "/desweb", // Index 1
+ "/desaplicativos",// Index 2
+ "/analisedados", // Index 3
+ "/segti" // Index 4
+ ];
+
+ if (bestVocationIndex >= 0 && bestVocationIndex < vocationRoutes.length) {
+ navigate(vocationRoutes[bestVocationIndex]);
+ } else {
+ console.error("Não foi possível determinar a vocação. Índice inválido ou pontuações não conclusivas.", result);
+ throw new Error("Não foi possível determinar sua vocação com base nas respostas.");
+ }
+
+ } catch (err: any) {
+ setError(err.message || "Ocorreu um erro ao processar seu teste.");
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+ {/* Link component removed from around the button as navigate is used */}
+
+ {isLoading ? "Aguarde..." : "VER RESULTADO"}
+
+
+
Finalizando seu teste!
+ {/* Updated text to be more generic if email is optional */}
+
+ Clique em "VER RESULTADO" para descobrir sua área.
+
+
+ {error &&
{error}
}
+
+
!isLoading && navigate("/")}
+ disabled={isLoading}
+ style={{ fontSize: '1.5rem', padding: '0.2rem 0.5rem', border: 'none', background: 'transparent', color: '#000' }} // Basic styling for X
+ >
+ X
+
+
+
+
+
+ );
+};
+
+export default SavePageDesktop;
diff --git a/front-codequest/src/pages/desktop/TestPage01.tsx b/front-codequest/src/pages/desktop/TestPage01.tsx
index 280b7a1..53456db 100644
--- a/front-codequest/src/pages/desktop/TestPage01.tsx
+++ b/front-codequest/src/pages/desktop/TestPage01.tsx
@@ -1,368 +1,389 @@
-import { FunctionComponent, SetStateAction } from "react";
-import React, { useState, useEffect } from 'react';
-import "./TestPage01.css";
-import { Button } from "react-bootstrap";
-import { Link } from 'react-router-dom';
-import handleInputChange from '../../handleResp';
-import respostasData from '../../respostasData';
-
-interface TestPage01DesktopProps {
- onRespostasChange: (respostas: { resposta1: string; resposta2: string; resposta3: string; resposta4: string; }) => void;
-}
-
-const TestPage01Desktop: FunctionComponent = ({ onRespostasChange }) => {
-
-const [redirecting, setRedirecting] = useState(false);
-const [respostas, setRespostas] = useState({
- resposta1: "",
- resposta2: "",
- resposta3: "",
- resposta4: "",
-});
-
-React.useEffect(() => {
- onRespostasChange(respostas);
-}, [onRespostasChange, respostas]);
-
-useEffect(() => {
- // Carregar respostas salvas quando o componente monta
- const savedRespostas = localStorage.getItem("respostas");
- if (savedRespostas) {
- setRespostas(JSON.parse(savedRespostas));
- }
-}, []);
-
-useEffect(() => {
- // Salvar respostas no localStorage sempre que elas mudam
- localStorage.setItem("respostas", JSON.stringify(respostas));
-}, [respostas]);
-const handleRespostaChange = (pergunta: string, resposta: string) => {
- setRespostas((prevRespostas) => ({
- ...prevRespostas,
- [pergunta]: resposta,
- }));
-};
-
- const handleRedirect = () => {
- setRedirecting(true);
- setTimeout(() => {
- setRedirecting(false);
- }, 5000);
- };
-
- return (
-
-
-
-
-
-
-
-
-
-
-
- Se sente empolgado com a ideia de criar programas que podem
- melhorar a forma como as empresas ou pessoas realizam tarefas?
-
-
-
-
-
-
-
-
-
- Gostaria de aprender a linguagem "código" para criar
- aplicativos, jogos ou software?
-
-
-
-
-
-
-
-
-
- Se sente atraído por trabalhar em equipe para criar
- aplicativos ou software maiores?
-
-
-
-
-
-
-
-
-
- Considera emocionante a possibilidade de ver suas ideias se
- transformarem em programas ou aplicativos reais?
-
-
-
-
-
-
-
-
-
- Em uma escala de 1 a 5, o quanto você:
-
-
-
-
- {redirecting ? "Aguarde..." : "CONTINUAR"}
-
-
-
-
- {redirecting ? "Aguarde..." : }
-
-
-
-
- );
-}
-
-export default TestPage01Desktop;
+import { FunctionComponent, SetStateAction } from "react";
+import React, { useState, useEffect } from 'react';
+import "./TestPage01.css";
+import { Button } from "react-bootstrap";
+import { Link } from 'react-router-dom';
+
+const LOCAL_STORAGE_KEY = "respostasPage1";
+
+const answerMapping: { [key: string]: number } = {
+ "nadaEmpolgado": 1, "poucoEmpolgado": 2, "neutro": 3, "empolgado": 4, "muitoEmpolgado": 5,
+ "nadaInteressado": 1, "poucoInteressado": 2, "interessado": 4, "muitoInteressado": 5,
+ "nadaAtraido": 1, "poucoAtraido": 2, "atraido": 4, "muitoAtraido": 5,
+ "nadaEmocionante": 1, "poucoEmocionante": 2, "emocionante": 4, "muitoEmocionante": 5
+};
+
+interface TestPage01DesktopProps {
+ onRespostasChange: (respostas: { resposta1: number | null; resposta2: number | null; resposta3: number | null; resposta4: number | null; }) => void;
+}
+
+const TestPage01Desktop: FunctionComponent = ({ onRespostasChange }) => {
+
+const [redirecting, setRedirecting] = useState(false); // Keep for button visual feedback if desired
+const [respostas, setRespostas] = useState<{ resposta1: number | null; resposta2: number | null; resposta3: number | null; resposta4: number | null; }>({
+ resposta1: null,
+ resposta2: null,
+ resposta3: null,
+ resposta4: null,
+});
+
+React.useEffect(() => {
+ onRespostasChange(respostas);
+}, [onRespostasChange, respostas]);
+
+useEffect(() => {
+ const savedRespostas = localStorage.getItem(LOCAL_STORAGE_KEY);
+ if (savedRespostas) {
+ try {
+ const parsedRespostas = JSON.parse(savedRespostas);
+ setRespostas({
+ resposta1: typeof parsedRespostas.resposta1 === 'number' ? parsedRespostas.resposta1 : null,
+ resposta2: typeof parsedRespostas.resposta2 === 'number' ? parsedRespostas.resposta2 : null,
+ resposta3: typeof parsedRespostas.resposta3 === 'number' ? parsedRespostas.resposta3 : null,
+ resposta4: typeof parsedRespostas.resposta4 === 'number' ? parsedRespostas.resposta4 : null,
+ });
+ } catch (error) {
+ console.error("Failed to parse respostas from localStorage for Page 1", error);
+ setRespostas({ resposta1: null, resposta2: null, resposta3: null, resposta4: null });
+ }
+ }
+}, []);
+
+useEffect(() => {
+ localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(respostas));
+}, [respostas]);
+
+const handleRespostaChange = (pergunta: keyof typeof respostas, respostaValue: string) => {
+ const mappedValue = answerMapping[respostaValue];
+ setRespostas((prevRespostas) => ({
+ ...prevRespostas,
+ [pergunta]: mappedValue !== undefined ? mappedValue : (respostaValue === "neutro" ? 3 : null),
+ }));
+};
+
+ const handleLinkClick = () => { // Renamed from handleRedirect to avoid confusion
+ setRedirecting(true);
+ setTimeout(() => {
+ setRedirecting(false);
+ }, 1000); // Shorter delay for link clicks
+ };
+
+ return (
+
+
{/* Renamed from test-page3 for clarity */}
+ {/* The background image div is removed, .test-page-container will be styled */}
+
{/* Simplified class */}
+
+
{/* Simplified class */}
+
{/* Simplified class */}
+
{/* Simplified class */}
+ Em uma escala de 1 a 5, o quanto você:
+
+
+
+
{/* Renamed from text-test3 */}
+
+
{/* Added base class */}
+
+
+
+
{/* Added base class */}
+
+
+
+
+
+
{/* Added base class */}
+
+
+
+
{/* Added base class */}
+
+
+
+
+
+
+
+
+ {redirecting ? "..." : }
+
+
+
+
+ {redirecting ? "Aguarde..." : "CONTINUAR"}
+
+
+
+
+
+ );
+}
+
+export default TestPage01Desktop;
diff --git a/front-codequest/src/pages/desktop/TestPage02.tsx b/front-codequest/src/pages/desktop/TestPage02.tsx
index 6c9eeb8..40f7b57 100644
--- a/front-codequest/src/pages/desktop/TestPage02.tsx
+++ b/front-codequest/src/pages/desktop/TestPage02.tsx
@@ -1,369 +1,396 @@
-import { FunctionComponent, useEffect } from "react";
-import "bootstrap/dist/css/bootstrap.min.css";
-import { Button } from "react-bootstrap";
-import "./TestPage02.css";
-import { Link } from 'react-router-dom';
-import { useState } from "react";
-import React from "react";
-
-interface TestPage02DesktopProps {
- onRespostasChange: (respostas: { resposta1: string; resposta2: string; resposta3: string; resposta4: string; }) => void;
-}
-
-const TestPage02Desktop: FunctionComponent = ({ onRespostasChange }) => {
- const [redirecting, setRedirecting] = useState(false);
- const [respostas, setRespostas] = useState({
- resposta1: "",
- resposta2: "",
- resposta3: "",
- resposta4: "",
- });
- React.useEffect(() => {
- onRespostasChange(respostas);
- }, [onRespostasChange, respostas]);
- useEffect(() => {
- // Carregar respostas salvas quando o componente monta
- const savedRespostas = localStorage.getItem("respostas");
- if (savedRespostas) {
- setRespostas(JSON.parse(savedRespostas));
- }
- }, []);
-
- useEffect(() => {
- // Salvar respostas no localStorage sempre que elas mudam
- localStorage.setItem("respostas", JSON.stringify(respostas));
- }, [respostas]);
-
- const handleRespostaChange = (pergunta: string, resposta: string) => {
- setRespostas((prevRespostas) => ({
- ...prevRespostas,
- [pergunta]: resposta,
- }));
- };
-
- const handleRedirect = () => {
- setRedirecting(true);
- setTimeout(() => {
- setRedirecting(false);
- }, 5000);
- };
-
-
- return (
-
-
-
-
-
-
-
-
-
-
-
- Acha bacana a ideia de criar aplicativos que possam ser usados
- em smartphones ou tablets?
-
-
-
-
-
-
-
-
-
- Imagina-se aprendendo a desenvolver aplicativos que facilitem
- a vida das pessoas, como apps de transporte ou de pedidos de
- comida?
-
-
-
-
-
-
-
-
-
- Valoriza a ideia de criar interfaces amigáveis e atraentes
- para seus aplicativos?
-
-
-
-
-
-
-
-
-
- Gostaria de criar aplicativos que aproveitassem recursos
- específicos de dispositivos móveis, como câmeras e sensores?
-
-
-
-
-
-
-
-
-
- Em uma escala de 1 a 5, o quanto você:
-
-
-
-
- {redirecting ? "Aguarde..." : "CONTINUAR"}
-
-
-
-
- {redirecting ? "Aguarde..." : }
-
-
-
-
- );
-};
-
-export default TestPage02Desktop;
+import { FunctionComponent, useEffect } from "react";
+import "bootstrap/dist/css/bootstrap.min.css";
+import { Button } from "react-bootstrap";
+import "./TestPage02.css"; // Assuming TestPage02.css will be created or updated for responsive styles
+import { Link } from 'react-router-dom';
+import { useState } from "react";
+import React from "react";
+
+const LOCAL_STORAGE_KEY = "respostasPage2";
+
+const answerMapping: { [key: string]: number } = {
+ "nadaBacana": 1, "poucoBacana": 2, "neutro": 3, "bacana": 4, "muitoBacana": 5,
+ "nadaImaginavel": 1, "poucoImaginavel": 2, "imaginavel": 4, "muitoImaginavel": 5,
+ "nadaValorizo": 1, "poucoValorizo": 2, "valorizo": 4, "muitoValorizo": 5,
+ "nadaGostaria": 1, "poucoGostaria": 2, "gostaria": 4, "muitoGostaria": 5
+};
+
+interface TestPage02DesktopProps {
+ onRespostasChange: (respostas: { resposta1: number | null; resposta2: number | null; resposta3: number | null; resposta4: number | null; }) => void;
+}
+
+const TestPage02Desktop: FunctionComponent = ({ onRespostasChange }) => {
+ const [redirecting, setRedirecting] = useState(false);
+ const [respostas, setRespostas] = useState<{ resposta1: number | null; resposta2: number | null; resposta3: number | null; resposta4: number | null; }>({
+ resposta1: null,
+ resposta2: null,
+ resposta3: null,
+ resposta4: null,
+ });
+
+ React.useEffect(() => {
+ onRespostasChange(respostas);
+ }, [onRespostasChange, respostas]);
+
+ useEffect(() => {
+ const savedRespostas = localStorage.getItem(LOCAL_STORAGE_KEY);
+ if (savedRespostas) {
+ try {
+ const parsedRespostas = JSON.parse(savedRespostas);
+ setRespostas({
+ resposta1: typeof parsedRespostas.resposta1 === 'number' ? parsedRespostas.resposta1 : null,
+ resposta2: typeof parsedRespostas.resposta2 === 'number' ? parsedRespostas.resposta2 : null,
+ resposta3: typeof parsedRespostas.resposta3 === 'number' ? parsedRespostas.resposta3 : null,
+ resposta4: typeof parsedRespostas.resposta4 === 'number' ? parsedRespostas.resposta4 : null,
+ });
+ } catch (error) {
+ console.error("Failed to parse respostas from localStorage for TestPage02", error);
+ setRespostas({ resposta1: null, resposta2: null, resposta3: null, resposta4: null });
+ }
+ }
+ }, []);
+
+ useEffect(() => {
+ localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(respostas));
+ }, [respostas]);
+
+ const handleRespostaChange = (pergunta: keyof typeof respostas, respostaValue: string) => {
+ const mappedValue = answerMapping[respostaValue];
+ setRespostas((prevRespostas) => ({
+ ...prevRespostas,
+ [pergunta]: mappedValue !== undefined ? mappedValue : (respostaValue === "neutro" ? 3 : null),
+ }));
+ };
+
+ const handleLinkClick = () => {
+ setRedirecting(true);
+ setTimeout(() => {
+ setRedirecting(false);
+ }, 1000);
+ };
+
+ return (
+ // General container class for consistent padding/max-width if TestPage02.css is created
+
+
{/* Renamed from test-page2 */}
+ {/* Background image div can be removed if .test-page-container handles background */}
+ {/*
+
+
*/}
+
{/* Simplified class */}
+
+
{/* Simplified class */}
+
{/* Simplified class */}
+
{/* Simplified class */}
+ Em uma escala de 1 a 5, o quanto você:
+
+
+
+ {/* Changed
to for questions area */}
+
{/* Renamed from text-test2 */}
+
+
{/* Use a common class + specific one */}
+
{/* Simplified class */}
+
+ Acha bacana a ideia de criar aplicativos que possam ser usados
+ em smartphones ou tablets?
+
+
+
+
+
+
+
+
+ Imagina-se aprendendo a desenvolver aplicativos que facilitem
+ a vida das pessoas, como apps de transporte ou de pedidos de
+ comida?
+
+
+
+
+
+
+
+
+
+
+ Valoriza a ideia de criar interfaces amigáveis e atraentes
+ para seus aplicativos?
+
+
+
+
+
+
+
+
+ Gostaria de criar aplicativos que aproveitassem recursos
+ específicos de dispositivos móveis, como câmeras e sensores?
+
+
+
+
+
+
+
+
+
+
+ {redirecting ? "..." : }
+
+
+
+
+ {redirecting ? "Aguarde..." : "CONTINUAR"}
+
+
+
+
+
+ );
+};
+
+export default TestPage02Desktop;
diff --git a/front-codequest/src/pages/desktop/TestPage03.tsx b/front-codequest/src/pages/desktop/TestPage03.tsx
index 41a99d8..66b0c3c 100644
--- a/front-codequest/src/pages/desktop/TestPage03.tsx
+++ b/front-codequest/src/pages/desktop/TestPage03.tsx
@@ -1,348 +1,368 @@
-import { FunctionComponent } from "react";
-import "bootstrap/dist/css/bootstrap.min.css";
-import { Button } from "react-bootstrap";
-import "./TestPage03.css";
-import { Link } from 'react-router-dom';
-import React, { useState, useEffect } from "react";
-
-interface TestPage03DesktopProps {
- onRespostasChange: (respostas: { resposta1: string; resposta2: string; resposta3: string; resposta4: string; }) => void;
-}
-
-const TestPage03Desktop: FunctionComponent
= ({ onRespostasChange }) => {
- const [redirecting, setRedirecting] = useState(false);
- const [respostas, setRespostas] = useState({
- resposta1: "",
- resposta2: "",
- resposta3: "",
- resposta4: "",
- });
-
- React.useEffect(() => {
- onRespostasChange(respostas);
- }, [onRespostasChange, respostas]);
-
- useEffect(() => {
- // Carregar respostas salvas quando o componente monta
- const savedRespostas = localStorage.getItem("respostas");
- if (savedRespostas) {
- setRespostas(JSON.parse(savedRespostas));
- }
- }, []);
-
- useEffect(() => {
- // Salvar respostas no localStorage sempre que elas mudam
- localStorage.setItem("respostas", JSON.stringify(respostas));
- }, [respostas]);
-
- const handleRespostaChange = (pergunta: string, resposta: string) => {
- setRespostas((prevRespostas) => ({
- ...prevRespostas,
- [pergunta]: resposta,
- }));
- };
-
- const handleRedirect = () => {
- // Ativar o sinalizador de redirecionamento para mostrar algum indicador de carregamento (opcional).
- setRedirecting(true);
-
- // Atraso de 1000 milissegundos (1 segundo) antes do redirecionamento.
- setTimeout(() => {
- setRedirecting(false); // Desativar o sinalizador de redirecionamento.
- }, 5000); // 1000 milissegundos = 1 segundo
- };
-
- return (
-
-
-
-
-
-
-
-
-
-
-
- Gostaria de aprender a fazer páginas na internet usando coisas
- simples, como imagens e textos?
-
-
-
-
-
-
-
-
-
- Transformar designs visuais em sites interativos e funcionais
- te atrai?
-
-
-
-
-
-
-
-
-
- Valoriza a capacidade de criar sites que se adaptam a
- diferentes dispositivos, como computadores, tablets e
- smartphones?
-
-
-
-
-
-
-
-
-
- Se sente motivado a aprender a construir sites modernos,
- utilizando as últimas tecnologias da web?
-
-
-
-
-
-
-
-
-
- Em uma escala de 1 a 5, o quanto você:
-
-
-
-
- {redirecting ? "Aguarde..." : "CONTINUAR"}
-
-
-
-
- {redirecting ? "Aguarde..." : }
-
-
-
-
- );
-};
-
-export default TestPage03Desktop;
+import { FunctionComponent } from "react";
+import "bootstrap/dist/css/bootstrap.min.css";
+import { Button } from "react-bootstrap";
+import "./TestPage03.css"; // Assuming TestPage03.css will be created/updated
+import { Link } from 'react-router-dom';
+import React, { useState, useEffect } from "react";
+
+const LOCAL_STORAGE_KEY = "respostasPage3";
+
+const answerMapping: { [key: string]: number } = {
+ "nadaGostaria": 1, "poucoGostaria": 2, "neutro": 3, "gostaria": 4, "muitoGostaria": 5,
+ "nadaAtrai": 1, "poucoAtrai": 2, "atrai": 4, "muitoAtrai": 5,
+ "nadaValorizo": 1, "poucoValorizo": 2, "valorizo": 4, "muitoValorizo": 5,
+ "nadaMotivado": 1, "poucoMotivado": 2, "motivado": 4, "muitoMotivado": 5
+};
+
+interface TestPage03DesktopProps {
+ onRespostasChange: (respostas: { resposta1: number | null; resposta2: number | null; resposta3: number | null; resposta4: number | null; }) => void;
+}
+
+const TestPage03Desktop: FunctionComponent = ({ onRespostasChange }) => {
+ const [redirecting, setRedirecting] = useState(false);
+ const [respostas, setRespostas] = useState<{ resposta1: number | null; resposta2: number | null; resposta3: number | null; resposta4: number | null; }>({
+ resposta1: null,
+ resposta2: null,
+ resposta3: null,
+ resposta4: null,
+ });
+
+ React.useEffect(() => {
+ onRespostasChange(respostas);
+ }, [onRespostasChange, respostas]);
+
+ useEffect(() => {
+ const savedRespostas = localStorage.getItem(LOCAL_STORAGE_KEY);
+ if (savedRespostas) {
+ try {
+ const parsedRespostas = JSON.parse(savedRespostas);
+ setRespostas({
+ resposta1: typeof parsedRespostas.resposta1 === 'number' ? parsedRespostas.resposta1 : null,
+ resposta2: typeof parsedRespostas.resposta2 === 'number' ? parsedRespostas.resposta2 : null,
+ resposta3: typeof parsedRespostas.resposta3 === 'number' ? parsedRespostas.resposta3 : null,
+ resposta4: typeof parsedRespostas.resposta4 === 'number' ? parsedRespostas.resposta4 : null,
+ });
+ } catch (error) {
+ console.error("Failed to parse respostas from localStorage for TestPage03", error);
+ setRespostas({ resposta1: null, resposta2: null, resposta3: null, resposta4: null });
+ }
+ }
+ }, []);
+
+ useEffect(() => {
+ localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(respostas));
+ }, [respostas]);
+
+ const handleRespostaChange = (pergunta: keyof typeof respostas, respostaValue: string) => {
+ const mappedValue = answerMapping[respostaValue];
+ setRespostas((prevRespostas) => ({
+ ...prevRespostas,
+ [pergunta]: mappedValue !== undefined ? mappedValue : (respostaValue === "neutro" ? 3 : null),
+ }));
+ };
+
+ const handleLinkClick = () => {
+ setRedirecting(true);
+ setTimeout(() => {
+ setRedirecting(false);
+ }, 1000);
+ };
+
+ return (
+ {/* Consistent wrapper */}
+
{/* Renamed from test-page1 */}
+
{/* Simplified class */}
+
+
{/* Simplified class */}
+
{/* Simplified class */}
+
{/* Simplified class */}
+ Em uma escala de 1 a 5, o quanto você:
+
+
+
+
{/* Renamed from text-test1 */}
+
+
{/* Base + specific class */}
+
+
+ Gostaria de aprender a fazer páginas na internet usando coisas
+ simples, como imagens e textos?
+
+
+
+
+
+
+
+
+ Transformar designs visuais em sites interativos e funcionais
+ te atrai?
+
+
+
+
+
+
+
+
+
+
+ Valoriza a capacidade de criar sites que se adaptam a
+ diferentes dispositivos, como computadores, tablets e
+ smartphones?
+
+
+
+
+
+
+
+
+ Se sente motivado a aprender a construir sites modernos,
+ utilizando as últimas tecnologias da web?
+
+
+
+
+
+
+
+
+
+
+ {redirecting ? "..." : }
+
+
+
+
+ {redirecting ? "Aguarde..." : "CONTINUAR"}
+
+
+
+
+
+ );
+};
+
+export default TestPage03Desktop;
diff --git a/front-codequest/src/pages/desktop/TestPage04.tsx b/front-codequest/src/pages/desktop/TestPage04.tsx
index b7c6256..3cdd0df 100644
--- a/front-codequest/src/pages/desktop/TestPage04.tsx
+++ b/front-codequest/src/pages/desktop/TestPage04.tsx
@@ -1,369 +1,219 @@
-import { FunctionComponent } from "react";
-import "bootstrap/dist/css/bootstrap.min.css";
-import { Button } from "react-bootstrap";
-import "./TestPage04.css";
-import { Link } from 'react-router-dom';
-import React,{ useState, useEffect } from "react";
-
-interface TestPage04DesktopProps {
- onRespostasChange: (respostas: { resposta1: string; resposta2: string; resposta3: string; resposta4: string; }) => void;
-}
-
-const TestPage04Desktop: FunctionComponent = ({ onRespostasChange }) => {
- const [redirecting, setRedirecting] = useState(false);
- const [respostas, setRespostas] = useState({
- resposta1: "",
- resposta2: "",
- resposta3: "",
- resposta4: "",
- });
- React.useEffect(() => {
- onRespostasChange(respostas);
- }, [onRespostasChange, respostas]);
- useEffect(() => {
- // Carregar respostas salvas quando o componente monta
- const savedRespostas = localStorage.getItem("respostas");
- if (savedRespostas) {
- setRespostas(JSON.parse(savedRespostas));
- }
- }, []);
-
- useEffect(() => {
- // Salvar respostas no localStorage sempre que elas mudam
- localStorage.setItem("respostas", JSON.stringify(respostas));
- }, [respostas]);
-
- const handleRespostaChange = (pergunta: string, resposta: string) => {
- setRespostas((prevRespostas) => ({
- ...prevRespostas,
- [pergunta]: resposta,
- }));
- };
-
- const handleRedirect = () => {
- // Ativar o sinalizador de redirecionamento para mostrar algum indicador de carregamento (opcional).
- setRedirecting(true);
-
- // Atraso de 1000 milissegundos (1 segundo) antes do redirecionamento.
- setTimeout(() => {
- setRedirecting(false); // Desativar o sinalizador de redirecionamento.
- }, 5000); // 1000 milissegundos = 1 segundo
- };
-
- return (
-
-
-
-
-
-
-
-
-
-
-
- Se interessa por descobrir informações importantes escondidas
- em grandes quantidades de dados?
-
-
-
-
-
-
-
-
-
- Gostaria de aprender como usar números e estatísticas para
- encontrar padrões e tendências em conjuntos de informações?
-
-
-
-
-
-
-
-
-
- Valoriza a possibilidade de ajudar empresas a tomar decisões
- melhores com base em dados concretos?
-
-
-
-
-
-
-
-
-
- Se sente motivado a criar visualizações de dados interessantes
- para tornar informações complexas mais compreensíveis?
-
-
-
-
-
-
-
-
-
- Em uma escala de 1 a 5, o quanto você:
-
-
-
-
- {redirecting ? "Aguarde..." : "CONTINUAR"}
-
-
-
-
- {redirecting ? "Aguarde..." : }
-
-
-
-
- );
-};
-
-export default TestPage04Desktop;
+import { FunctionComponent } from "react";
+import "bootstrap/dist/css/bootstrap.min.css";
+import { Button } from "react-bootstrap";
+import "./TestPage04.css"; // Assuming TestPage04.css will be created/updated
+import { Link } from 'react-router-dom';
+import React,{ useState, useEffect } from "react";
+
+const LOCAL_STORAGE_KEY = "respostasPage4";
+
+const answerMapping: { [key: string]: number } = {
+ "nadaInteressado": 1, "poucoInteressado": 2, "neutro": 3, "interessado": 4, "muitoInteressado": 5
+ // This mapping applies to all questions on this page
+};
+
+interface TestPage04DesktopProps {
+ onRespostasChange: (respostas: { resposta1: number | null; resposta2: number | null; resposta3: number | null; resposta4: number | null; }) => void;
+}
+
+const TestPage04Desktop: FunctionComponent = ({ onRespostasChange }) => {
+ const [redirecting, setRedirecting] = useState(false);
+ const [respostas, setRespostas] = useState<{ resposta1: number | null; resposta2: number | null; resposta3: number | null; resposta4: number | null; }>({
+ resposta1: null,
+ resposta2: null,
+ resposta3: null,
+ resposta4: null,
+ });
+
+ React.useEffect(() => {
+ onRespostasChange(respostas);
+ }, [onRespostasChange, respostas]);
+
+ useEffect(() => {
+ const savedRespostas = localStorage.getItem(LOCAL_STORAGE_KEY);
+ if (savedRespostas) {
+ try {
+ const parsedRespostas = JSON.parse(savedRespostas);
+ setRespostas({
+ resposta1: typeof parsedRespostas.resposta1 === 'number' ? parsedRespostas.resposta1 : null,
+ resposta2: typeof parsedRespostas.resposta2 === 'number' ? parsedRespostas.resposta2 : null,
+ resposta3: typeof parsedRespostas.resposta3 === 'number' ? parsedRespostas.resposta3 : null,
+ resposta4: typeof parsedRespostas.resposta4 === 'number' ? parsedRespostas.resposta4 : null,
+ });
+ } catch (error) {
+ console.error("Failed to parse respostas from localStorage for TestPage04", error);
+ setRespostas({ resposta1: null, resposta2: null, resposta3: null, resposta4: null });
+ }
+ }
+ }, []);
+
+ useEffect(() => {
+ localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(respostas));
+ }, [respostas]);
+
+ const handleRespostaChange = (pergunta: keyof typeof respostas, respostaValue: string) => {
+ const mappedValue = answerMapping[respostaValue];
+ setRespostas((prevRespostas) => ({
+ ...prevRespostas,
+ [pergunta]: mappedValue !== undefined ? mappedValue : (respostaValue === "neutro" ? 3 : null),
+ }));
+ };
+
+ const handleLinkClick = () => {
+ setRedirecting(true);
+ setTimeout(() => {
+ setRedirecting(false);
+ }, 1000);
+ };
+
+ return (
+ {/* Consistent wrapper */}
+
{/* Renamed from test-page */}
+ {/* Background image div can be removed */}
+
{/* Simplified class */}
+
+
{/* Simplified class, was title-test3 */}
+
{/* Simplified class */}
+
{/* Simplified class */}
+ Em uma escala de 1 a 5, o quanto você:
+
+
+
+
{/* Renamed from text-test */}
+
+
{/* Base + specific class */}
+
+
+ Se interessa por descobrir informações importantes escondidas
+ em grandes quantidades de dados?
+
+
+
+
+
+
+
+
+ Gostaria de aprender como usar números e estatísticas para
+ encontrar padrões e tendências em conjuntos de informações?
+
+
+
+
+
+
+
+
+
+
+ Valoriza a possibilidade de ajudar empresas a tomar decisões
+ melhores com base em dados concretos?
+
+
+
+
+
+
+
+
+ Se sente motivado a criar visualizações de dados interessantes
+ para tornar informações complexas mais compreensíveis?
+
+
+
+
+
+
+
+
+
+
+ {redirecting ? "..." : }
+
+
+
+
+ {redirecting ? "Aguarde..." : "CONTINUAR"}
+
+
+
+
+
+ );
+};
+
+export default TestPage04Desktop;
diff --git a/front-codequest/src/pages/desktop/TestPage05.tsx b/front-codequest/src/pages/desktop/TestPage05.tsx
index 1458371..cfaeef7 100644
--- a/front-codequest/src/pages/desktop/TestPage05.tsx
+++ b/front-codequest/src/pages/desktop/TestPage05.tsx
@@ -1,366 +1,189 @@
-import { FunctionComponent } from "react";
-import "./TestPage05.css";
-import "bootstrap/dist/css/bootstrap.min.css";
-import { Button } from "react-bootstrap";
-import { Link } from 'react-router-dom';
-import React,{ useState, useEffect } from "react";
-
-interface TestPage05DesktopProps {
- onRespostasChange: (respostas: { resposta1: string; resposta2: string; resposta3: string; resposta4: string; }) => void;
-}
-
-const TestPage05Desktop: FunctionComponent = ({ onRespostasChange }) => {
- const [redirecting, setRedirecting] = useState(false);
- const [respostas, setRespostas] = useState({
- resposta1: "",
- resposta2: "",
- resposta3: "",
- resposta4: "",
- });
-
- React.useEffect(() => {
- onRespostasChange(respostas);
- }, [onRespostasChange, respostas]);
-
- useEffect(() => {
- // Carregar respostas salvas quando o componente monta
- const savedRespostas = localStorage.getItem("respostas");
- if (savedRespostas) {
- setRespostas(JSON.parse(savedRespostas));
- }
- }, []);
-
- useEffect(() => {
- // Salvar respostas no localStorage sempre que elas mudam
- localStorage.setItem("respostas", JSON.stringify(respostas));
- }, [respostas]);
-
- const handleRespostaChange = (pergunta: string, resposta: string) => {
- setRespostas((prevRespostas) => ({
- ...prevRespostas,
- [pergunta]: resposta,
- }));
- };
-
- const handleRedirect = () => {
- // Ativar o sinalizador de redirecionamento para mostrar algum indicador de carregamento (opcional).
- setRedirecting(true);
-
- // Atraso de 1000 milissegundos (1 segundo) antes do redirecionamento.
- setTimeout(() => {
- setRedirecting(false); // Desativar o sinalizador de redirecionamento.
- }, 5000); // 1000 milissegundos = 1 segundo
- };
-
- return (
-
-
-
-
-
-
-
-
-
-
-
- Se preocupa em proteger informações pessoais e digitais de
- possíveis ameaças?
-
-
-
-
-
-
-
-
-
- Se sente atraído pela ideia de entender como hackers trabalham
- para criar defesas contra ataques cibernéticos?
-
-
-
-
-
-
-
-
-
- Gostaria de aprender a criar estratégias de segurança para
- proteger sistemas e redes de possíveis invasões?
-
-
-
-
-
-
-
-
-
- Se sente motivado a estar atualizado sobre as últimas ameaças
- digitais e como se defender delas?
-
-
-
-
-
-
-
-
-
- Em uma escala de 1 a 5, o quanto você:
-
-
-
-
- {redirecting ? "Aguarde..." : "FINALIZAR"}
-
-
-
-
- {redirecting ? "Aguarde..." : }
-
-
-
-
- );
-};
-
-export default TestPage05Desktop;
+import { FunctionComponent } from "react";
+import "./TestPage05.css"; // Assuming TestPage05.css will be created/updated
+import "bootstrap/dist/css/bootstrap.min.css";
+import { Button } from "react-bootstrap";
+import { Link } from 'react-router-dom';
+import React,{ useState, useEffect } from "react";
+
+const LOCAL_STORAGE_KEY = "respostasPage5";
+
+const answerMapping: { [key: string]: number } = {
+ "nadaPreocupado": 1, "poucoPreocupado": 2, "neutro": 3, "preocupado": 4, "muitoPreocupado": 5,
+ "nadaInteressado": 1, "poucoIneressado": 2, "poucoInteressado": 2, "interessado": 4, "muitoInteressado": 5,
+ "nadaMotivado": 1, "poucoMotivado": 2, "motivado": 4, "muitoMotivado": 5
+};
+
+interface TestPage05DesktopProps {
+ onRespostasChange: (respostas: { resposta1: number | null; resposta2: number | null; resposta3: number | null; resposta4: number | null; }) => void;
+}
+
+const TestPage05Desktop: FunctionComponent = ({ onRespostasChange }) => {
+ const [redirecting, setRedirecting] = useState(false);
+ const [respostas, setRespostas] = useState<{ resposta1: number | null; resposta2: number | null; resposta3: number | null; resposta4: number | null; }>({
+ resposta1: null,
+ resposta2: null,
+ resposta3: null,
+ resposta4: null,
+ });
+
+ React.useEffect(() => {
+ onRespostasChange(respostas);
+ }, [onRespostasChange, respostas]);
+
+ useEffect(() => {
+ const savedRespostas = localStorage.getItem(LOCAL_STORAGE_KEY);
+ if (savedRespostas) {
+ try {
+ const parsedRespostas = JSON.parse(savedRespostas);
+ setRespostas({
+ resposta1: typeof parsedRespostas.resposta1 === 'number' ? parsedRespostas.resposta1 : null,
+ resposta2: typeof parsedRespostas.resposta2 === 'number' ? parsedRespostas.resposta2 : null,
+ resposta3: typeof parsedRespostas.resposta3 === 'number' ? parsedRespostas.resposta3 : null,
+ resposta4: typeof parsedRespostas.resposta4 === 'number' ? parsedRespostas.resposta4 : null,
+ });
+ } catch (error) {
+ console.error("Failed to parse respostas from localStorage for TestPage05", error);
+ setRespostas({ resposta1: null, resposta2: null, resposta3: null, resposta4: null });
+ }
+ }
+ }, []);
+
+ useEffect(() => {
+ localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(respostas));
+ }, [respostas]);
+
+ const handleRespostaChange = (pergunta: keyof typeof respostas, respostaValue: string) => {
+ const mappedValue = answerMapping[respostaValue];
+ setRespostas((prevRespostas) => ({
+ ...prevRespostas,
+ [pergunta]: mappedValue !== undefined ? mappedValue : (respostaValue === "neutro" ? 3 : null),
+ }));
+ };
+
+ const handleLinkClick = () => {
+ setRedirecting(true);
+ setTimeout(() => {
+ setRedirecting(false);
+ }, 1000);
+ };
+
+ // Helper to generate radio options for a question
+ const renderOptions = (questionName: keyof typeof respostas, options: string[]) => {
+ return options.map(value => (
+
+
+ handleRespostaChange(questionName, value)}
+ />{" "}
+ {/* Auto-generate label text, handling the typo case */}
+ {value === "poucoIneressado" ? "Pouco Interessado" : value.replace(/([A-Z])/g, ' $1').replace(/^./, str => str.toUpperCase())}
+
+
+ ));
+ };
+
+ return (
+ {/* Consistent wrapper */}
+
{/* Renamed from test-page4 */}
+
{/* Simplified class */}
+
+
{/* Simplified class, was title-test3 */}
+
{/* Simplified class */}
+
{/* Simplified class */}
+ Em uma escala de 1 a 5, o quanto você:
+
+
+
+
{/* Renamed from text-test4 */}
+
+
{/* Base + specific class */}
+
+
+ Se preocupa em proteger informações pessoais e digitais de
+ possíveis ameaças?
+
+
+
+ {renderOptions("resposta1", ["nadaPreocupado", "poucoPreocupado", "neutro", "preocupado", "muitoPreocupado"])}
+
+
+
+
+
+
+ Se sente atraído pela ideia de entender como hackers trabalham
+ para criar defesas contra ataques cibernéticos?
+
+
+
+ {/* Note the typo "poucoIneressado" here as per original file value */}
+ {renderOptions("resposta2", ["nadaInteressado", "poucoIneressado", "neutro", "interessado", "muitoInteressado"])}
+
+
+
+
+
+
+
+
+ Gostaria de aprender a criar estratégias de segurança para
+ proteger sistemas e redes de possíveis invasões?
+
+
+
+ {/* This uses "poucoInteressado" (correct spelling) */}
+ {renderOptions("resposta3", ["nadaInteressado", "poucoInteressado", "neutro", "interessado", "muitoInteressado"])}
+
+
+
+
+
+
+ Se sente motivado a estar atualizado sobre as últimas ameaças
+ digitais e como se defender delas?
+
+
+
+ {renderOptions("resposta4", ["nadaMotivado", "poucoMotivado", "neutro", "motivado", "muitoMotivado"])}
+
+
+
+
+
+
+
+
+ {redirecting ? "..." : }
+
+
+ {/* Link to /save (SavePage) as this is the last test page */}
+
+
+ {redirecting ? "Aguarde..." : "FINALIZAR"}
+
+
+
+
+
+ );
+};
+
+export default TestPage05Desktop;