feat(InterviewBooking): added error handing, button css and defined select on date

This commit is contained in:
darkicewolf50 2025-04-12 12:03:14 -06:00
parent 6aade88454
commit aa8e5c2577
3 changed files with 412 additions and 320 deletions

View File

@ -82,3 +82,41 @@
padding-right: var(--interviewspacing); padding-right: var(--interviewspacing);
width: 80%; width: 80%;
} }
:root {
/* used for editing time buttons */
--TimeSlotSideWidth: 48%;
--TimeSlotSidePaddingTopBottom: 1svh 0px;
--TimeSlotSideMarginTopBottom: 0.25svh 1%;
}
.TimeSlotSide0 {
cursor: pointer;
border: none;
width: var(--TimeSlotSideWidth);
padding: var(--TimeSlotSidePaddingTopBottom);
margin: var(--TimeSlotSideMarginTopBottom);
}
.TimeSlotSide1 {
cursor: pointer;
border: none;
width: var(--TimeSlotSideWidth);
padding: var(--TimeSlotSidePaddingTopBottom);
margin: var(--TimeSlotSideMarginTopBottom);
}
#interviewLoading {
display: flex;
align-items: center;
justify-content: center;
text-align: center;
height: 334.3px;
}
#CurrentSelected {
background-color: lightseagreen;
}

View File

@ -1,5 +1,5 @@
import { useState, useRef } from "react"; import { useState, useRef } from "react";
import TimeDateSelector from "./TimeDateSelector"; // Import the TimeSlotSelector component import TimeDateSelector from "./TimeDateSelector";
/** /**
* @param {null} null - Takes in nothing * @param {null} null - Takes in nothing
@ -18,18 +18,19 @@ const InterviewForm = () => {
/** /**
* @param {String HTML} event - Takes in form info * @param {String HTML} event - Takes in form info
* @returns {null} null - Returns in nothing * @returns {null} null - Returns in nothing
* @description * @description submits the form with the appropriate information
* @author Ahmad <ahmadmuhammadofficial@gmail.com> * @author Ahmad <ahmadmuhammadofficial@gmail.com>
* @todo CSS * @todo imporper email and other erros from backend
*/ */
const formsubmit = async (event) => { const formsubmit = async (event) => {
const errorLine = document.getElementById("InterviewError");
event.preventDefault(); event.preventDefault();
if (!selectedTimeSlot) { if (selectedTimeSlot) {
alert("Please select a time slot!"); console.log(selectedTimeSlot);
return; if (selectedTimeSlot.date !== null && selectedTimeSlot.startTime !== "") {
} errorLine.innerHTML = " ";
// disable button to stop multiple requests // disable button to stop multiple requests
setIsButtonDisabled(true); setIsButtonDisabled(true);
@ -39,6 +40,7 @@ const InterviewForm = () => {
formObject.date = selectedTimeSlot["date"]; // Add the selected time slot to form data formObject.date = selectedTimeSlot["date"]; // Add the selected time slot to form data
formObject.startTime = selectedTimeSlot["startTime"]; formObject.startTime = selectedTimeSlot["startTime"];
console.log("Form Data:", formObject); console.log("Form Data:", formObject);
const res = await fetch( const res = await fetch(
"https://bajabackend.bajacloud.duckdns.org/SelectInterview", "https://bajabackend.bajacloud.duckdns.org/SelectInterview",
{ {
@ -67,10 +69,36 @@ const InterviewForm = () => {
} else { } else {
setGetTimeDates(getTimeDates + "i"); setGetTimeDates(getTimeDates + "i");
} }
x;
} else {
formSubmitTimeErorrs(selectedTimeSlot, errorLine);
}
} else {
formSubmitTimeErorrs(selectedTimeSlot, errorLine);
}
setIsButtonDisabled(false); setIsButtonDisabled(false);
}; };
/**
* @param {Object} missingError - Takes in object to find what is missing from it
* @param {HTMLSelectElement} - display line on page
* @returns {null} null - Returns in nothing
* @description A separated function to handle all timeslot errors possible states and displays the appropriate message on the error line
* @author Brock <darkicewolf50@gmail.com>
*/
const formSubmitTimeErorrs = (missingError, errorLine) => {
if (!missingError) {
errorLine.innerHTML = "Please Select a Date and a Time";
}
// impossible state
/*
else if (missingError.date === null) {
errorLine.innerHTML = "Please Select a Date";
*/
else if (missingError.startTime) {
errorLine.innerHTML = "Please Select a Time";
}
};
return ( return (
<> <>
<form onSubmit={formsubmit}> <form onSubmit={formsubmit}>
@ -120,9 +148,13 @@ const InterviewForm = () => {
out an alternate interview time or for rescheduling. out an alternate interview time or for rescheduling.
</p> </p>
</div> </div>
<p id="InterviewError"> </p> <p id="InterviewError"> </p>
<div id="InterviewSubmit"> <div id="InterviewSubmit">
<button type="submit" disabled={isButtonDisabled}> <button
type="submit"
disabled={isButtonDisabled}>
Submit Submit
</button> </button>
</div> </div>

View File

@ -2,6 +2,13 @@ import React, { useState, useEffect } from "react";
import DatePicker from "react-datepicker"; import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css"; import "react-datepicker/dist/react-datepicker.css";
/**
* @param {Function} onTimeSlotSelect - Used to pass back up the selected values from child component
* @param {Function} timeDateSelectorGet - Used to display dates avaialable
* @returns {JSX.element} JSX - HTML and JS functionality
* @description Used for picking an interview date
* @author Ahmad <ahmadmuhammadofficial@gmail.com>
*/
export default function TimeDateSelector({ export default function TimeDateSelector({
onTimeSlotSelect, onTimeSlotSelect,
timeDateSelectorGet, timeDateSelectorGet,
@ -10,6 +17,7 @@ export default function TimeDateSelector({
const [selectedDate, setSelectedDate] = useState(null); const [selectedDate, setSelectedDate] = useState(null);
const [timeSlotsAvialable, setTimeSlotsAvialable] = useState([]); const [timeSlotsAvialable, setTimeSlotsAvialable] = useState([]);
const [selectedTime, setSelectedTime] = useState(""); const [selectedTime, setSelectedTime] = useState("");
const [selectedTimeButton, setSelectedTimeButton] = useState(null);
useEffect(() => { useEffect(() => {
getInterviewDates(); getInterviewDates();
@ -59,10 +67,22 @@ export default function TimeDateSelector({
// get and set time slots for a given day // get and set time slots for a given day
setTimeSlotsAvialable(Object.keys(allDatesAvailable[selectedDateStr])); setTimeSlotsAvialable(Object.keys(allDatesAvailable[selectedDateStr]));
setSelectedTime(""); // clear because of date change setSelectedTime(""); // clear because of date change
// set prematurely for better error messages
onTimeSlotSelect({
date: selectedDateStr,
startTime: selectedTime,
});
}; };
const handleTimeSlotChange = (e) => { const handleTimeSlotChange = (e) => {
let startTime = e.target.innerHTML; e.currentTarget.id = "CurrentSelected";
if (selectedTimeButton !== null) {
selectedTimeButton.id = "";
}
setSelectedTimeButton(e.currentTarget);
let startTime = e.currentTarget.dataset.time;
setSelectedTime(startTime); setSelectedTime(startTime);
onTimeSlotSelect({ onTimeSlotSelect({
@ -99,8 +119,7 @@ export default function TimeDateSelector({
height: "241.633px", height: "241.633px",
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
}} }}>
>
<p>Please select the a date to see time slots.</p> <p>Please select the a date to see time slots.</p>
</div> </div>
</> </>
@ -119,15 +138,18 @@ export default function TimeDateSelector({
) : timeSlotsAvialable !== "" ? ( ) : timeSlotsAvialable !== "" ? (
<> <>
{Object.values(timeSlotsAvialable).map((time) => { {Object.values(timeSlotsAvialable).map((time) => {
// console.log(timeSlotsAvialable.indexOf(time));
return ( return (
<button <button
className={
"TimeSlotSide" +
(timeSlotsAvialable.indexOf(time) % 2)
}
key={time} key={time}
type="button" type="button"
onClick={(self) => { data-time={time}
handleTimeSlotChange(self); onClick={handleTimeSlotChange}>
}} {time.slice(0, 5)}
>
{time}
</button> </button>
); );
})} })}
@ -152,7 +174,7 @@ export default function TimeDateSelector({
</div>)} */} </div>)} */}
</> </>
) : ( ) : (
<p>Loading ...</p> <p id="interviewLoading">Loading ...</p>
)} )}
</div> </div>
); );