| Автор | SHA1 | Сообщение | Дата |
|---|---|---|---|
|
|
6848954a15 | setted countdown based on the timeslot input | 3 лет назад |
|
|
3ecf6bd356 | fixed multiselect checkbox style and added enum for option type | 3 лет назад |
| @@ -1,7 +1,7 @@ | |||
| import { useEffect, useState } from 'react'; | |||
| const useCountdown = (targetDate: Date) => { | |||
| console.log(targetDate); | |||
| const countDownDate = new Date(targetDate).getTime(); | |||
| const [countDown, setCountDown] = useState( | |||
| @@ -14,13 +14,14 @@ const useCountdown = (targetDate: Date) => { | |||
| }, 1000); | |||
| return () => clearInterval(interval); | |||
| }, []); | |||
| }, [targetDate]); | |||
| const days = Math.floor(countDown / (1000 * 60 * 60 * 24)); | |||
| const hours = Math.floor((countDown % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); | |||
| const minutes = Math.floor((countDown % (1000 * 60 * 60)) / (1000 * 60)); | |||
| const seconds = Math.floor((countDown % (1000 * 60)) / 1000); | |||
| return [days, hours, minutes, seconds]; | |||
| }; | |||
| @@ -9,6 +9,7 @@ interface OwnProps { | |||
| month: string; | |||
| getDate: () => void; | |||
| HideTimeSlot: () => void; | |||
| getTimeSlot: (date: any, time: string) => void; | |||
| } | |||
| const TimeSlot: React.FC<OwnProps> = (props) => { | |||
| @@ -16,6 +17,14 @@ const TimeSlot: React.FC<OwnProps> = (props) => { | |||
| const [highlightedDate, setHighlightedDate] = useState<Date>(); | |||
| const [highlightedTime, setHighlightedTime] = useState<string>(""); | |||
| const setTimeSlot = () => { | |||
| if (highlightedDate && highlightedTime !== "") { | |||
| props.getDate(); | |||
| props.getTimeSlot(highlightedDate, highlightedTime); | |||
| } else { | |||
| return undefined; | |||
| } | |||
| } | |||
| const dates = Dates.map((date, key) => { | |||
| return ( | |||
| <div | |||
| @@ -27,7 +36,7 @@ const TimeSlot: React.FC<OwnProps> = (props) => { | |||
| {format(date, 'eee')} | |||
| </div> | |||
| <div> | |||
| {format(date, 'e')} | |||
| {format(date, 'd')} | |||
| </div> | |||
| </div> | |||
| @@ -68,7 +77,7 @@ const TimeSlot: React.FC<OwnProps> = (props) => { | |||
| </div> | |||
| </div> | |||
| <div onClick={(highlightedDate && highlightedTime !== "") ? () => props.getDate() : undefined} | |||
| <div onClick={setTimeSlot} | |||
| className={styles.timeSlotButton + " " + (highlightedDate && highlightedTime !== "" ? styles.buttonActive : "")}> | |||
| <IonButton shape="round" expand='block' >Confirm slot</IonButton> | |||
| </div> | |||
| @@ -1,4 +1,5 @@ | |||
| import { QuizDetails } from "../models/QuizDetails"; | |||
| import { QuizDetails, OptionType } from "../models/QuizDetails"; | |||
| const QUIZ_DETAILS: QuizDetails[] = [ | |||
| { | |||
| @@ -12,7 +13,7 @@ const QUIZ_DETAILS: QuizDetails[] = [ | |||
| answer: ["System.out.println('Hello, how are you?');"], | |||
| result: false, | |||
| timeLimit: 5, | |||
| type: "singleSelect" | |||
| type: OptionType.SINGLE_SELECT | |||
| }, | |||
| { | |||
| question: "How do you write 'Hello World' in an alert box?", | |||
| @@ -25,7 +26,7 @@ const QUIZ_DETAILS: QuizDetails[] = [ | |||
| answer: ["alert('Hello World');"], | |||
| result: false, | |||
| timeLimit: 10, | |||
| type: "singleSelect" | |||
| type: OptionType.SINGLE_SELECT | |||
| }, | |||
| { | |||
| @@ -38,8 +39,8 @@ const QUIZ_DETAILS: QuizDetails[] = [ | |||
| ], | |||
| answer: ["B", "C"], | |||
| result: false, | |||
| timeLimit: 15, | |||
| type: "multiSelect" | |||
| timeLimit: 60, | |||
| type: OptionType.MULTI_SELECT | |||
| }, | |||
| { | |||
| question: "Is javascript single threaded or multi threaded? enter the answer in the below box ", | |||
| @@ -47,7 +48,7 @@ const QUIZ_DETAILS: QuizDetails[] = [ | |||
| answer: ["single threaded"], | |||
| result: false, | |||
| timeLimit: 60, | |||
| type: "textInput" | |||
| type: OptionType.INPUT_TEXT | |||
| }, | |||
| { | |||
| question: "is javascript", | |||
| @@ -60,17 +61,8 @@ const QUIZ_DETAILS: QuizDetails[] = [ | |||
| answer: ["B", "C"], | |||
| result: false, | |||
| timeLimit: 35, | |||
| type: "multiSelect" | |||
| type: OptionType.MULTI_SELECT | |||
| }, | |||
| ]; | |||
| export let test = [ | |||
| { | |||
| a: "ss" | |||
| }, | |||
| { | |||
| a: "aa" | |||
| }, | |||
| ] | |||
| export default QUIZ_DETAILS; | |||
| @@ -1,8 +1,14 @@ | |||
| export enum OptionType { | |||
| SINGLE_SELECT = "singleSelect", | |||
| MULTI_SELECT = "multiSelect", | |||
| INPUT_TEXT = "textInput" | |||
| } | |||
| export interface QuizDetails { | |||
| question: string; | |||
| options?: string[]; | |||
| answer: string[]; | |||
| result: boolean; | |||
| timeLimit: number; | |||
| type: string; | |||
| type: OptionType; | |||
| } | |||
| @@ -8,23 +8,28 @@ import { Link } from "react-router-dom"; | |||
| import { useState } from "react"; | |||
| import TimeSlot from "../../components/timeSlot/TimeSlot"; | |||
| import { useCountdown } from "../../components/CountDownTimer/useCountdown"; | |||
| import { addDays } from "date-fns"; | |||
| import CountdownTimer from "../../components/CountDownTimer/CountdownTimer"; | |||
| import { format } from "date-fns"; | |||
| const FinalInterview: React.FC = () => { | |||
| const [isDateSet, setDate] = useState<boolean>(false); | |||
| const [isTimeSlot, setTimeSlot] = useState<boolean>(false); | |||
| const [isDateSet, setIsDate] = useState<boolean>(false); | |||
| const [isTimeSlot, setIsTimeSlot] = useState<boolean>(false); | |||
| const [date, setDate] = useState<Date>(new Date()); | |||
| const [days, hours, minutes, seconds] = useCountdown(new Date('may 6, 2022 07:00:00')); | |||
| const [days, hours, minutes, seconds] = useCountdown(date); | |||
| const getDate = () => { | |||
| setTimeSlot(false); | |||
| setDate(true); | |||
| setIsTimeSlot(false); | |||
| setIsDate(true); | |||
| } | |||
| const HideTimeSlot = () => { | |||
| setTimeSlot(false); | |||
| setIsTimeSlot(false); | |||
| } | |||
| const getTimeSlot = (date: any, time: string) => { | |||
| setDate(new Date(`${format(date, "LLL")} ${format(date, "d")} ${format(date, "y")} ${time.substring(0, 8)}`)); | |||
| } | |||
| return ( | |||
| @@ -46,13 +51,6 @@ const FinalInterview: React.FC = () => { | |||
| <h4>Let's Meet in:</h4> | |||
| <div className={styles.timeLeft}> | |||
| {/* <h4 className={styles.time}>02 : 04 : 25 : 53</h4> | |||
| <div className={styles.days}> | |||
| <div>Days</div> | |||
| <div>Hrs</div> | |||
| <div>Mins</div> | |||
| <div>Secs</div> | |||
| </div> */} | |||
| <CountdownTimer | |||
| days={days} | |||
| hours={hours} | |||
| @@ -68,7 +66,7 @@ const FinalInterview: React.FC = () => { | |||
| </div> | |||
| { | |||
| !isDateSet ? | |||
| <div className={styles.techinicalInterviewBtn} onClick={() => setTimeSlot(true)}> | |||
| <div className={styles.techinicalInterviewBtn} onClick={() => setIsTimeSlot(true)}> | |||
| <IonButton shape="round" expand='block'>Find a slot</IonButton> | |||
| </div> | |||
| : | |||
| @@ -87,7 +85,8 @@ const FinalInterview: React.FC = () => { | |||
| <TimeSlot | |||
| month="April-May" | |||
| getDate={getDate} | |||
| HideTimeSlot={HideTimeSlot} /> | |||
| HideTimeSlot={HideTimeSlot} | |||
| getTimeSlot={getTimeSlot} /> | |||
| } | |||
| </IonContent> | |||
| @@ -50,9 +50,9 @@ const StepsDescription: React.FC<Props> = (props) => { | |||
| </p> | |||
| {props.isRoundCompleted ? | |||
| <Link to="/interviewRounds" className={styles.button}> | |||
| <div className={styles.button}> | |||
| <IonButton shape="round" expand='block' disabled={true}>Completed</IonButton> | |||
| </Link> | |||
| </div> | |||
| : | |||
| <Link to={props.link} className={styles.button}> | |||
| <IonButton shape="round" expand='block'>{props.buttonText}</IonButton> | |||
| @@ -2,15 +2,13 @@ import styles from "./PreliminaryRoundResults.module.scss" | |||
| import { IonButton, IonContent, IonIcon, IonPage } from "@ionic/react"; | |||
| import StepHeader from "../../components/stepsHeader/StepHeader"; | |||
| import goodJobIcon from "../../assets/icons/good_job.svg"; | |||
| import { closeCircle, checkmarkCircle } from "ionicons/icons"; | |||
| import { Link } from "react-router-dom"; | |||
| import Quiz_Details from '../../mockData/QuizDetails'; | |||
| const PreliminaryRoundResults: React.FC = () => { | |||
| return ( | |||
| <IonPage> | |||
| <StepHeader stepNumber={2} roundName="Preliminary Round" /> | |||
| @@ -30,21 +30,25 @@ | |||
| // styles for multiselect checkbox | |||
| .checkBoxHolder { | |||
| border: 0.2rem solid #707070; | |||
| border: 0.2rem solid lighten($color: #707070, $amount: 20); | |||
| border-radius: 2.5rem; | |||
| width: 2rem; | |||
| height: 2rem; | |||
| margin-left: 2rem; | |||
| margin-left: 1.5rem; | |||
| .checkBox { | |||
| --background-checked: var(--primary-button-color); | |||
| --checkmark-color: var(--primary-button-color); | |||
| --border-width: 0; | |||
| margin: 0; | |||
| margin-top: 0.26rem; | |||
| margin-left: 0.27rem; | |||
| width: 1.2rem; | |||
| height: 1.2rem; | |||
| margin-top: 0.3rem; | |||
| margin-left: 0.3rem; | |||
| width: 1rem; | |||
| height: 1rem; | |||
| } | |||
| &.activeCheck { | |||
| border: 0.2rem solid var(--primary-button-color); | |||
| } | |||
| } | |||
| @@ -2,15 +2,15 @@ import { IonButton, IonCheckbox, IonItem, IonLabel, IonList, IonRadio, IonRadioG | |||
| import { useEffect, useRef, useState } from 'react'; | |||
| import { Link } from 'react-router-dom'; | |||
| import styles from './Options.module.scss'; | |||
| import { OptionType } from '../../models/QuizDetails' | |||
| interface OwnProps { | |||
| options: string[] | undefined; | |||
| type: string; | |||
| type: OptionType; | |||
| answer: string[]; | |||
| lastQuestion: boolean; | |||
| questionNumber: number; | |||
| updateQuestionNumber: () => void; | |||
| } | |||
| const Options: React.FC<OwnProps> = (props) => { | |||
| @@ -58,11 +58,12 @@ const Options: React.FC<OwnProps> = (props) => { | |||
| setTextInput(inputRef.current?.value!) | |||
| } | |||
| if (props.lastQuestion) { | |||
| const setAnswer = () => { | |||
| localStorage.setItem("answer", answers.toString()); | |||
| } | |||
| const options = props.options!.map((option, key) => { | |||
| return ( | |||
| <IonItem lines='none' key={key} className={(option === selected) ? styles.highlighted : ""}> | |||
| @@ -75,8 +76,12 @@ const Options: React.FC<OwnProps> = (props) => { | |||
| const MultiSelectOptions = props.options!.map((option, key) => { | |||
| return ( | |||
| <IonItem lines='none' key={key} className={(selectedOptions.includes(option)) ? styles.highlighted : ""}> | |||
| <div className={styles.checkBoxHolder}> | |||
| <IonCheckbox slot="start" mode='ios' className={styles.checkBox} onIonChange={e => selectChecked(option)} /> | |||
| <div className={(selectedOptions.includes(option)) ? (styles.activeCheck + " " + styles.checkBoxHolder) : styles.checkBoxHolder}> | |||
| <IonCheckbox | |||
| slot="start" | |||
| mode='ios' | |||
| className={styles.checkBox} | |||
| onIonChange={e => selectChecked(option)} /> | |||
| </div> | |||
| <IonLabel className={styles.multiSelectLabel}>{option}</IonLabel> | |||
| </IonItem> | |||
| @@ -118,7 +123,7 @@ const Options: React.FC<OwnProps> = (props) => { | |||
| } | |||
| {props.lastQuestion && | |||
| < Link to="/preliminaryRoundResults" className={styles.button + " " + ((selected || selectedOptions.length > 0 || textInput) ? styles.active : "")}> | |||
| < Link to="/preliminaryRoundResults" onClick={setAnswer} className={styles.button + " " + ((selected || selectedOptions.length > 0 || textInput) ? styles.active : "")}> | |||
| <IonButton shape="round" expand='block'>Next Step</IonButton> | |||
| </Link> | |||
| } | |||
| @@ -1,6 +1,6 @@ | |||
| import styles from './Quiz.module.scss'; | |||
| import { IonButton, IonIcon } from '@ionic/react'; | |||
| import { IonIcon } from '@ionic/react'; | |||
| import Options from './Options'; | |||
| import { closeOutline } from 'ionicons/icons' | |||
| import { Link } from 'react-router-dom'; | |||
| @@ -11,7 +11,7 @@ import QUIZ_DETAILS from '../../mockData/QuizDetails'; | |||
| const Quiz: React.FC = () => { | |||
| const [questionNumber, setQuestionNumber] = useState<number>(1); | |||
| const timeLimit = QUIZ_DETAILS[questionNumber - 1].timeLimit; | |||
| const currentQuestion = QUIZ_DETAILS[questionNumber - 1]; | |||
| const updateQuestionNumber = () => { | |||
| if (QUIZ_DETAILS.length > questionNumber) { | |||
| @@ -30,9 +30,9 @@ const Quiz: React.FC = () => { | |||
| </header> | |||
| <Question | |||
| question={QUIZ_DETAILS[questionNumber - 1].question} | |||
| question={currentQuestion.question} | |||
| questionNumber={questionNumber} | |||
| timeLimit={timeLimit} | |||
| timeLimit={currentQuestion.timeLimit} | |||
| updateQuestionNumber={updateQuestionNumber} /> | |||
| </div> | |||
| @@ -40,10 +40,10 @@ const Quiz: React.FC = () => { | |||
| <div className={styles.quizOptions}> | |||
| <div className={styles.options}> | |||
| <Options | |||
| options={QUIZ_DETAILS[questionNumber - 1].options} | |||
| options={currentQuestion.options} | |||
| updateQuestionNumber={updateQuestionNumber} | |||
| type={QUIZ_DETAILS[questionNumber - 1].type} | |||
| answer={QUIZ_DETAILS[questionNumber - 1].answer} | |||
| type={currentQuestion.type} | |||
| answer={currentQuestion.answer} | |||
| lastQuestion={QUIZ_DETAILS.length === questionNumber} | |||
| questionNumber={questionNumber} /> | |||
| </div> | |||
| @@ -5,27 +5,34 @@ import StepHeader from "../../components/stepsHeader/StepHeader"; | |||
| import techinicalInterview from "../../assets/icons/Technical_Interview.svg"; | |||
| import linkIcon from "../../assets/icons/link.svg"; | |||
| import { Link } from "react-router-dom"; | |||
| import { useState } from "react"; | |||
| import { useEffect, useState } from "react"; | |||
| import TimeSlot from "../../components/timeSlot/TimeSlot"; | |||
| import { useCountdown } from "../../components/CountDownTimer/useCountdown"; | |||
| import CountdownTimer from "../../components/CountDownTimer/CountdownTimer"; | |||
| import { format } from "date-fns"; | |||
| const TechnicalInterview: React.FC = () => { | |||
| const [isDateSet, setDate] = useState<boolean>(false); | |||
| const [isTimeSlot, setTimeSlot] = useState<boolean>(false); | |||
| const [isDateSet, setIsDate] = useState<boolean>(false); | |||
| const [isTimeSlot, setIsTimeSlot] = useState<boolean>(false); | |||
| const [date, setDate] = useState<Date>(new Date()); | |||
| const [days, hours, minutes, seconds] = useCountdown(new Date('may 7, 2022 07:00:00')); | |||
| const [days, hours, minutes, seconds] = useCountdown(date); | |||
| const getDate = () => { | |||
| setTimeSlot(false); | |||
| setDate(true); | |||
| setIsTimeSlot(false); | |||
| setIsDate(true); | |||
| } | |||
| const HideTimeSlot = () => { | |||
| setTimeSlot(false); | |||
| setIsTimeSlot(false); | |||
| } | |||
| const getTimeSlot = (date: any, time: string) => { | |||
| setDate(new Date(`${format(date, "LLL")} ${format(date, "d")} ${format(date, "y")} ${time.substring(0, 8)}`)); | |||
| } | |||
| return ( | |||
| <IonPage> | |||
| <StepHeader stepNumber={3} roundName="Technical Interview" /> | |||
| @@ -60,7 +67,7 @@ const TechnicalInterview: React.FC = () => { | |||
| </div> | |||
| { | |||
| !isDateSet ? | |||
| <div className={styles.techinicalInterviewBtn} onClick={() => setTimeSlot(true)}> | |||
| <div className={styles.techinicalInterviewBtn} onClick={() => setIsTimeSlot(true)}> | |||
| <IonButton shape="round" expand='block'>Find a slot</IonButton> | |||
| </div> | |||
| : | |||
| @@ -79,7 +86,8 @@ const TechnicalInterview: React.FC = () => { | |||
| <TimeSlot | |||
| month="April-May" | |||
| getDate={getDate} | |||
| HideTimeSlot={HideTimeSlot} /> | |||
| HideTimeSlot={HideTimeSlot} | |||
| getTimeSlot={getTimeSlot} /> | |||
| } | |||
| </IonContent> | |||