Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@
"react-icons": "^5.5.0",
"react-responsive-carousel": "^3.2.23",
"react-router-dom": "^7.6.3",
"tailwindcss": "^4.1.11",
"tailwindcss": "^3.4.0",
"zustand": "^5.0.6"
},
"devDependencies": {
"@tailwindcss/postcss": "^4.1.11",
"@types/react": "^19.1.8",
"@types/react-dom": "^19.1.6",
"@typescript-eslint/eslint-plugin": "^8.35.0",
Expand Down
2 changes: 1 addition & 1 deletion src/components/Course.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export default function CourseCard({
{
slots.map((course: Course) => {
return (
<div key={course.slot} className='course'>
<div key={`${course.slot}-${course.name}-${course.start_time}`} className='course'>
<div className='course-deets'>
<div className='course-name'>{course.name}</div>
<div className='course-time'>
Expand Down
102 changes: 67 additions & 35 deletions src/components/GetUserName.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
/* eslint-disable react-hooks/exhaustive-deps */
import React, { useEffect, useState } from "react";
import { isAvailable, signIn } from "../utils/apicalls";
import { useAuthStore } from "../store/authStore";
import { useAuthStore, campusType } from "../store/authStore";
import { useLoadingStore } from "../store/useLoadingStore";

const GetUsername: React.FC = () => {
const [userName, setuserName] = useState("");
const [regNo, setRegNo] = useState("");
interface GetUsernameProps {
userExists: boolean;
}

const GetUsername: React.FC<GetUsernameProps> = ({ userExists }) => {
const { updateUsername, updateToken, username, regNo, campus, updateCampus } =
useAuthStore();

const [userName, setuserName] = useState(username ?? "");
const [regNumber, setRegNumber] = useState(regNo ?? "");
const [validregNo, setValidRegNo] = useState(false);
const [cam, setCampus] = useState<campusType>("vellore");
const [validUsername, setValidUsername] = useState(false);
const regexPattern = /^\d{2}[A-Z]{3}\d{4}$/;
const uuid = localStorage.getItem("uuid") || "";
const { updateUsername, updateToken } = useAuthStore();
const { setLoading } = useLoadingStore();

useEffect(() => {
Expand All @@ -20,38 +27,48 @@ const GetUsername: React.FC = () => {
}, [setLoading]);

const updateUserName = (): void => {
signIn(uuid, regNo, userName).then((data) => {
signIn(uuid, regNumber, userName, cam).then((data) => {
if (data.token) {
updateUsername(userName);
updateToken(data.access_token);
updateCampus(cam);
} else {
setValidUsername(false);
setValidRegNo(false);
console.log(data);
window.alert(data.detail);
}
});
};

const validateInput = (e: React.FormEvent): void => {
e.preventDefault();
if (!userExists) {
if (regexPattern.test(regNumber)) {
setValidRegNo(true);
console.log("valid reg no");
} else {
window.alert("Invalid Reg. No.");
return;
}

if (regexPattern.test(regNo)) {
setValidRegNo(true);
console.log("valid reg no");
isAvailable(userName).then((data) => {
if (data.detail === "Username is valid") {
setValidUsername(true);
console.log("valid username");
} else {
window.alert(data.detail);
return;
}
});
} else {
window.alert("Invalid Reg. No.");
setValidUsername(true);
setValidRegNo(true);
}
if(cam == null) {
window.alert("Please select a campus");
return;
}

isAvailable(userName).then((data) => {
if (data.detail === "Username is valid") {
setValidUsername(true);
console.log("valid username");
} else {
window.alert(data.detail);
return;
}
});
};

useEffect(() => {
Expand All @@ -66,22 +83,37 @@ const GetUsername: React.FC = () => {
<div className="overflow-hidden flex flex-col items-center justify-center overflow-y-hidden p-10 mx-auto h-full">
<h1 className="overflow-visible text-2xl mb-10">Enter your Details</h1>
<div className="flex flex-col items-center justify-center w-[50vw] md:w-[20vw] h-90vh">
<input
type="text"
{!userExists && (
<>
<input
type="text"
id="input-text"
value={userName}
placeholder="Username"
onChange={(e) => setuserName(e.target.value)}
className="box-border z-[4] text-lg font-poppins rounded-md text-black p-3 pl-4 border-2 border-blue bg-dark w-full mb-3 text-left"
/>
<input
type="text"
id="input-text"
value={regNumber}
placeholder="Reg. Number"
onChange={(e) => setRegNumber(e.target.value.toUpperCase())}
className="box-border text-lg font-poppins rounded-md text-black p-3 pl-4 border-2 border-blue bg-dark w-full mb-3 text-left"
/>
</>
)}
<select
id="input-text"
value={userName}
placeholder="Username"
onChange={(e) => setuserName(e.target.value)}
className="box-border z-[4] text-lg font-poppins rounded-md text-black p-3 pl-4 border-2 border-blue bg-dark w-full mb-3 text-left"
/>
<input
type="text"
id="input-text"
value={regNo}
placeholder="Reg. Number"
onChange={(e) => setRegNo((e.target.value).toUpperCase())}
className="box-border text-lg font-poppins rounded-md text-black p-3 pl-4 border-2 border-blue bg-dark w-full mb-3 text-left"
/>
value={cam ?? "vellore"}
defaultValue="vellore"
onChange={(e) => setCampus(e.target.value as campusType)}
className="box-boxrder text-lg font-poppins rounded-md text-black p-3 pl-4 border-2 border-blue bg-dark w-full mb-3 text-left"
>
<option value="vellore">Vellore</option>
<option value="chennai">Chennai</option>
<option value="bhopal">Bhopal</option>
</select>
<div
id="button-wrap"
className="flex justify-center items-center w-full mt-4"
Expand Down
25 changes: 14 additions & 11 deletions src/components/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interface Course {
code: string;
venue: string;
slot: string;
type: string;
type: "Lab" | "Theory";
start_time: string | null;
end_time: string | null;
}
Expand All @@ -22,7 +22,7 @@ export default function Modal({ slot, status, onClose }: ModalProps) {
// const [course, setCourse] = useState<Course | null>(null);
const [slotAdd, setSlotAdd] = useState("");
const [courseName, setCourseName] = useState("");
const [type, setType] = useState("");
const [type, setType] = useState<"Lab" | "Theory" | null>(null);
const [code, setCode] = useState("");
const [venue, setVenue] = useState("");

Expand Down Expand Up @@ -53,7 +53,7 @@ export default function Modal({ slot, status, onClose }: ModalProps) {
setTip("Tip: Please enter a course code!");
return false;
}
if (type === "") {
if (!type) {
setTip("Tip: Please enter a course type!");
return false;
}
Expand Down Expand Up @@ -83,7 +83,7 @@ export default function Modal({ slot, status, onClose }: ModalProps) {
const course: Course = {
name: courseName,
code: code,
type: type,
type: type || "Theory",
venue: venue,
slot: slotAdd,
start_time: null,
Expand Down Expand Up @@ -150,14 +150,17 @@ export default function Modal({ slot, status, onClose }: ModalProps) {
/>
<br />
<label className="modal-message">Course Type</label>
<input
<select
className="modal-input"
type="text"
value={type}
onChange={(e) => setType(e.target.value)}
placeholder="Theory"
required
/>
value={type || ""}
onChange={(e) => setType(e.target.value as "Lab" | "Theory")}
>
<option value="" disabled>
Select Type
</option>
<option value="Theory">Theory</option>
<option value="Lab">Lab</option>
</select>
<br />
<label className="modal-message">Venue</label>
<input
Expand Down
10 changes: 6 additions & 4 deletions src/components/ReviewTimeTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { deduplicateTimetable } from "../utils/deduplicateTimetable";
// import { useLoadingStore } from "../store/useLoadingStore";

export default function ReviewTimeTable() {
const { setReview, token, username, uploadTimetable } = useAuthStore();
const { setReview, token, username, uploadTimetable, campus } = useAuthStore();
const { timetable } = useTimeTableStore();
const { setTimetableUploadedThisSession } = useLoadingStore();
const [classes, setClasses] = useState<Course[] | null>(null);
Expand All @@ -23,7 +23,9 @@ export default function ReviewTimeTable() {
const [modalStatus, setModalStatus] = useState<string>("");

const fetchData = async () => {
const classes: Course[] = ParseAndReturn(timetable, day);

//ParseAndReturn function will return the classes for the selected day
const classes: Course[] = ParseAndReturn(timetable, day, campus ?? "vellore");
const sortedClasses = classes.sort((a, b) => {
const aTime = convertTo24HourFormat(a.start_time || "00:00");
const bTime = convertTo24HourFormat(b.start_time || "00:00");
Expand Down Expand Up @@ -59,9 +61,9 @@ export default function ReviewTimeTable() {
alert("Please upload the timetable first!");
return;
} else {
const deduplicatedTimetable = deduplicateTimetable(timetable.timetable || []);
// const deduplicatedTimetable = deduplicateTimetable(timetable.timetable || []);

uploadText(deduplicatedTimetable, token, username || "")
uploadText(timetable.timetable, token, username || "")
// eslint-disable-next-line @typescript-eslint/no-explicit-any
.then((res: any) => {
if (res.data.detail !== null) {
Expand Down
4 changes: 2 additions & 2 deletions src/components/UploadTimeTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { useTimeTableStore } from "../store/TimeTableStore";

const Upload: React.FC = () => {
const [text, setText] = useState("");
const { username, token, setReview } = useAuthStore();
const { token, setReview, campus } = useAuthStore();
const { uploadTimetable } = useTimeTableStore();
const { setLoading } = useLoadingStore();
// const regexPattern = /Registered and Approved$/;
Expand All @@ -34,7 +34,7 @@ const Upload: React.FC = () => {
// return;
// }
// }
parseAndReturn(text, token)
parseAndReturn(text, token, campus ?? "vellore")
.then((res: TimeTable) => {
if (res.timetable === null) {
alert(
Expand Down
11 changes: 8 additions & 3 deletions src/pages/Dashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { useAuthStore } from "../store/authStore";
import Loader from "../components/Loader";

export default function Dashboard() {
const { uuid, username, updateToken, updateUsername, token } = useAuthStore();
const { uuid, username, updateToken, updateUsername, token, campus, updateCampus } = useAuthStore();
var userExists = false;
useEffect(() => {
if(uuid === "") return;
checkUserExists(uuid).then((res) => {
Expand All @@ -18,6 +19,10 @@ export default function Dashboard() {
if (data) {
updateUsername(data.username);
updateToken(data.token);
if(data.campus) {
updateCampus(data.campus);
}
userExists = true;
localStorage.setItem("email", data.email);
} else {
window.alert("Some error occured");
Expand All @@ -32,8 +37,8 @@ export default function Dashboard() {
{
username === null
? <Loader />
: username === ""
? <GetUserName />
: username === "" || campus == null
? <GetUserName userExists={userExists}/>
: <Timetable />
}
</div>
Expand Down
27 changes: 21 additions & 6 deletions src/pages/TimeTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useEffect } from "react";
import EditTimeTable from "../components/EditTimeTable";
import UploadTimeTable from "../components/UploadTimeTable";
import ReviewTimeTable from "../components/ReviewTimeTable";
import Loader from "../components/Loader";

interface ClassInfo {
name: string;
Expand All @@ -21,24 +22,38 @@ interface Timetable {
}

export default function Timetable() {
const { username, token, timetable, uploadTimetable, deleteTimetable, review } = useAuthStore();
const {
username,
token,
timetable,
uploadTimetable,
deleteTimetable,
review,
} = useAuthStore();

useEffect(() => {
getTimetable(username || "", token)
.then((res) => {
if (res.data.Monday === undefined) {
deleteTimetable();
console.log(res, "upload timetable from timetable page");
}
else {
} else {
uploadTimetable(res.data);
console.log(res.data, "upload timetable from timetable page");
}
})
.catch((error) => {
console.error("Error fetching timetable:", error);
});
}, [username, token]);

return (review === false) ? ((timetable === null) ? <UploadTimeTable /> : <EditTimeTable />): <ReviewTimeTable />;
return review === false ? (
timetable === null ? (
<Loader />
) : timetable.timetable === null ? (
<UploadTimeTable />
) : (
<EditTimeTable />
)
) : (
<ReviewTimeTable />
);
}
Loading
Loading