diff --git a/Client/src/Pages/Integrations/index.jsx b/Client/src/Pages/Integrations/index.jsx
index 1df87ee52..5cde4f4db 100644
--- a/Client/src/Pages/Integrations/index.jsx
+++ b/Client/src/Pages/Integrations/index.jsx
@@ -1,9 +1,70 @@
-import React from 'react'
+import { Box, Typography, useTheme } from '@mui/material';
+import IntegrationsComponent from '../../Components/Integrations';
+
+/**
+ * Integrations Page Component
+ * @returns {JSX.Element} The JSX representation of the Integrations page.
+ */
const Integrations = () => {
- return (
-
Integrations
- )
-}
+ const theme = useTheme();
-export default Integrations
\ No newline at end of file
+
+ const integrations = [
+ {
+ url: 'https://via.placeholder.com/100',
+ header: 'Integration 1',
+ info: 'Info about Integration 1',
+ onClick: () => {}
+ },
+ {
+ url: 'https://via.placeholder.com/100',
+ header: 'Integration 2',
+ info: 'Info about Integration 2',
+ onClick: () => {}
+ },
+ {
+ url: 'https://via.placeholder.com/100',
+ header: 'Integration 2',
+ info: 'Info about Integration 2',
+ onClick: () => {}
+ }
+ // Add more integrations as needed
+ ];
+
+ return (
+
+
+ Integrations
+
+
+ Connect Uptime Genie to your favorite service
+
+
+ {integrations.map((integration, index) => (
+
+ ))}
+
+
+ );
+};
+
+export default Integrations;
diff --git a/Client/src/Pages/Login/index.jsx b/Client/src/Pages/Login/index.jsx
index 19edcf6f0..01cce9ded 100644
--- a/Client/src/Pages/Login/index.jsx
+++ b/Client/src/Pages/Login/index.jsx
@@ -1,4 +1,6 @@
-import { useState } from "react";
+import { useState, useEffect } from "react";
+import { useNavigate } from "react-router-dom";
+
import "./index.css";
import BackgroundPattern from "../../Components/BackgroundPattern/BackgroundPattern";
import Logomark from "../../assets/Images/Logomark.png";
@@ -8,23 +10,84 @@ import Button from "../../Components/Button";
import Google from "../../assets/Images/Google.png";
import PasswordTextField from "../../Components/TextFields/Password/PasswordTextField";
+import { loginValidation } from "../../Validation/validation";
+import { login } from "../../Features/Auth/authSlice";
+import { useDispatch } from "react-redux";
+
const Login = () => {
+ const dispatch = useDispatch();
+ const navigate = useNavigate();
+
const idMap = {
"login-email-input": "email",
"login-password-input": "password",
};
+ const [errors, setErrors] = useState({});
+
const [form, setForm] = useState({
email: "",
password: "",
});
+ useEffect(() => {
+ const { error } = loginValidation.validate(form, {
+ abortEarly: false,
+ });
+
+ if (error) {
+ // Creates an error object in the format { field: message }
+ const validationErrors = error.details.reduce((acc, err) => {
+ return { ...acc, [err.path[0]]: err.message };
+ }, {});
+ setErrors(validationErrors);
+ } else {
+ setErrors({});
+ }
+ }, []);
+
+ const handleSubmit = async () => {
+ try {
+ await loginValidation.validateAsync(form, { abortEarly: false });
+ const action = await dispatch(login(form));
+ if (action.meta.requestStatus === "fulfilled") {
+ const token = action.payload.data;
+ localStorage.setItem("token", token);
+ navigate("/");
+ }
+ if (action.meta.requestStatus === "rejected") {
+ const error = new Error("Request rejected");
+ error.response = action.payload;
+ throw error;
+ }
+ } catch (error) {
+ if (error.name === "ValidationError") {
+ // TODO Handle validation errors
+ console.log(error.details);
+ alert(error);
+ } else if (error.response) {
+ // TODO handle dispatch errors
+ alert(error.response.msg);
+ } else {
+ // TODO handle unknown errors
+ console.log(error);
+ alert("Unknown error");
+ }
+ }
+ };
+
const handleInput = (e) => {
const fieldName = idMap[e.target.id];
- setForm({
- ...form,
- [fieldName]: e.target.value,
- });
+ // Extract and validate individual fields as input changes
+ const fieldSchema = loginValidation.extract(fieldName);
+ const { error } = fieldSchema.validate(e.target.value);
+ let errMsg = "";
+ if (error) {
+ errMsg = error.message;
+ }
+ setErrors({ ...errors, [fieldName]: errMsg });
+ const newForm = { ...form, [idMap[e.target.id]]: e.target.value };
+ setForm(newForm);
};
return (
@@ -44,14 +107,16 @@ const Login = () => {
@@ -63,7 +128,12 @@ const Login = () => {
-
+