diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 05db132..7d6efbf 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -10,7 +10,8 @@ "dependencies": { "next": "16.1.6", "react": "19.2.3", - "react-dom": "19.2.3" + "react-dom": "19.2.3", + "react-hook-form": "^7.71.2" }, "devDependencies": { "@svgr/webpack": "^8.1.0", @@ -6934,6 +6935,22 @@ "react": "^19.2.3" } }, + "node_modules/react-hook-form": { + "version": "7.71.2", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.71.2.tgz", + "integrity": "sha512-1CHvcDYzuRUNOflt4MOq3ZM46AronNJtQ1S7tnX6YN4y72qhgiUItpacZUAQ0TyWYci3yz1X+rXaSxiuEm86PA==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/react-hook-form" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18 || ^19" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index 96aed6f..d0921ac 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,7 +11,8 @@ "dependencies": { "next": "16.1.6", "react": "19.2.3", - "react-dom": "19.2.3" + "react-dom": "19.2.3", + "react-hook-form": "^7.71.2" }, "devDependencies": { "@svgr/webpack": "^8.1.0", diff --git a/frontend/src/app/agents/add/page.jsx b/frontend/src/app/agents/add/page.jsx index 219a580..d378e02 100644 --- a/frontend/src/app/agents/add/page.jsx +++ b/frontend/src/app/agents/add/page.jsx @@ -6,6 +6,8 @@ import TopToolTip from "@/app/components/topToolTip/TopToolTip"; import globalStyle from "../../globalStyle.module.css"; import createAgentStyle from "./styles.module.css"; import Prompts from "@/app/components/prompts/Prompts"; +import useAgentForm from "@/app/hooks/useAgentForm"; +import Alert from "@/app/components/alerts/Alert"; const Page = () => { const [isChecked, setIsChecked] = useState(false); @@ -13,9 +15,24 @@ const Page = () => { const handleCheckboxChange = (e) => { setIsChecked(e.target.checked); }; + const { + register, + handleSubmit, + errors, + onSubmit, + triggerAlert, + setTriggerAlert, + } = useAgentForm(); return (
+ {triggerAlert && ( + setEditState(true)} + title="Create New Agent" + /> + )}
{ {/* Create agent Container */}
-
+ {/* Header */}
@@ -40,10 +61,14 @@ const Page = () => { {/* Label */}

Agent Name

- {/*

*

*/} +

*

{/* Input Field */} - +
{/* Kubernetes API input */} @@ -51,10 +76,14 @@ const Page = () => { {/* Label */}

Kubernetes API Proxy Name

- {/*

*

*/} +

*

{/* Input Field */} - +
{/* Checkbox */} @@ -89,12 +118,13 @@ const Page = () => { {/* Label */}

Agent Endpoint

- {/*

*

*/} +

*

{/* Input Field */}
diff --git a/frontend/src/app/components/fields/styles.module.css b/frontend/src/app/components/fields/styles.module.css index 141a0f0..b3e24e0 100644 --- a/frontend/src/app/components/fields/styles.module.css +++ b/frontend/src/app/components/fields/styles.module.css @@ -19,13 +19,11 @@ line-height: normal; caret-color: #575bc7; } -.input:focus, -.input:active { +.input:focus { border-radius: 6px; border: 1px solid #959aff; background: rgba(75, 79, 109, 0.25); } -.input:active::placeholder, .input:focus::placeholder { color: #4b4f6d; font-family: Inter; @@ -54,6 +52,8 @@ pointer-events: none; user-select: none; } -.input:invalid { +.error, +.error:focus, +.error:hover { border: 1px solid #b43939; } diff --git a/frontend/src/app/credentials/add/page.jsx b/frontend/src/app/credentials/add/page.jsx index 1ac4d3b..9e981b7 100644 --- a/frontend/src/app/credentials/add/page.jsx +++ b/frontend/src/app/credentials/add/page.jsx @@ -6,8 +6,18 @@ import createCredStyle from "./styles.module.css"; import TopToolTip from "@/app/components/topToolTip/TopToolTip"; import TextField from "@/app/components/fields/textfield"; import Prompts from "@/app/components/prompts/Prompts"; +import useRoleForm from "@/app/hooks/useRolesForm"; +import Alert from "@/app/components/alerts/Alert"; const Page = () => { + const { + register, + handleSubmit, + errors, + onSubmit, + triggerAlert, + setTriggerAlert, + } = useRoleForm(); const [selectedFile, setSelectedFile] = useState(null); // Click const handleFileChange = (e) => { @@ -31,6 +41,13 @@ const Page = () => { }; return (
+ {triggerAlert && ( + setEditState(true)} + title="Create Credential" + /> + )}
{ {/* Create Crediantial Container */}
-
+ {/* Project Name Input Container */}

Project Name

- {/*

*

*/} +

*

{/* Content */}
- +
@@ -62,7 +87,7 @@ const Page = () => {

Upload File

{/* Optional or Required */} - {/*

(Optional)

*/}{" "} +

(Optional)

{" "}
{/* Upload File */}
-
+
diff --git a/frontend/src/app/hooks/useAgentForm.jsx b/frontend/src/app/hooks/useAgentForm.jsx new file mode 100644 index 0000000..24cd1b2 --- /dev/null +++ b/frontend/src/app/hooks/useAgentForm.jsx @@ -0,0 +1,32 @@ +"use client"; + +import { useState } from "react"; +import { useForm } from "react-hook-form"; + +const useAgentForm = () => { + const [triggerAlert, setTriggerAlert] = useState(false); + + const { + register, + handleSubmit, + watch, + formState: { errors }, + } = useForm(); + + const onSubmit = (data) => { + setTriggerAlert(true); + console.log("Submitted data:", data); + }; + + return { + register, + handleSubmit, + watch, + errors, + onSubmit, + triggerAlert, + setTriggerAlert, + }; +}; + +export default useAgentForm; diff --git a/frontend/src/app/hooks/useCredentialForm.jsx b/frontend/src/app/hooks/useCredentialForm.jsx new file mode 100644 index 0000000..67461bd --- /dev/null +++ b/frontend/src/app/hooks/useCredentialForm.jsx @@ -0,0 +1,33 @@ +"use client"; + +import { useState } from "react"; +import { useForm } from "react-hook-form"; + +const useCredentialForm = () => { + const [triggerAlert, setTriggerAlert] = useState(false); + + const { + register, + handleSubmit, + watch, + formState: { errors }, + } = useForm(); + + const onSubmit = (data) => { + setTriggerAlert(true); + + console.log("Submitted data:", data); + }; + + return { + register, + handleSubmit, + watch, + errors, + onSubmit, + triggerAlert, + setTriggerAlert, + }; +}; + +export default useCredentialForm; diff --git a/frontend/src/app/hooks/useOrganizationForm.jsx b/frontend/src/app/hooks/useOrganizationForm.jsx new file mode 100644 index 0000000..2250966 --- /dev/null +++ b/frontend/src/app/hooks/useOrganizationForm.jsx @@ -0,0 +1,46 @@ +"use client"; +import { useState } from "react"; + +const useOrganizationForm = () => { + const [organizationName, setOrganizationName] = useState(""); + const [error, setError] = useState(false); + const [triggerAlert, setTriggerAlert] = useState(false); + + const handleChange = (e) => { + const value = e.target.value; + setOrganizationName(value); + + if (value.trim() !== "") { + setError(false); + } + }; + + const handleValidation = (e) => { + e.preventDefault(); + setError(true); + }; + + const handleSubmit = (e) => { + e.preventDefault(); + + if (!organizationName.trim()) { + setError(true); + return; + } + setTriggerAlert(true); + + console.log("Submitted organization:", organizationName); + }; + + return { + organizationName, + error, + triggerAlert, + handleChange, + handleValidation, + handleSubmit, + setTriggerAlert, + }; +}; + +export default useOrganizationForm; diff --git a/frontend/src/app/hooks/useProjectForm.jsx b/frontend/src/app/hooks/useProjectForm.jsx new file mode 100644 index 0000000..0f73831 --- /dev/null +++ b/frontend/src/app/hooks/useProjectForm.jsx @@ -0,0 +1,33 @@ +"use client"; + +import { useState } from "react"; +import { useForm } from "react-hook-form"; + +const useProjectForm = () => { + const [triggerAlert, setTriggerAlert] = useState(false); + + const { + register, + handleSubmit, + watch, + formState: { errors }, + } = useForm(); + + const onSubmit = (data) => { + setTriggerAlert(true); + + console.log("Submitted data:", data); + }; + + return { + register, + handleSubmit, + watch, + errors, + onSubmit, + triggerAlert, + setTriggerAlert, + }; +}; + +export default useProjectForm; diff --git a/frontend/src/app/hooks/useRolesForm.jsx b/frontend/src/app/hooks/useRolesForm.jsx new file mode 100644 index 0000000..05e302c --- /dev/null +++ b/frontend/src/app/hooks/useRolesForm.jsx @@ -0,0 +1,33 @@ +"use client"; + +import { useState } from "react"; +import { useForm } from "react-hook-form"; + +const useRoleForm = () => { + const [triggerAlert, setTriggerAlert] = useState(false); + + const { + register, + handleSubmit, + watch, + formState: { errors }, + } = useForm(); + + const onSubmit = (data) => { + setTriggerAlert(true); + + console.log("Submitted data:", data); + }; + + return { + register, + handleSubmit, + watch, + errors, + onSubmit, + triggerAlert, + setTriggerAlert, + }; +}; + +export default useRoleForm; diff --git a/frontend/src/app/hooks/useServicesForm.jsx b/frontend/src/app/hooks/useServicesForm.jsx new file mode 100644 index 0000000..24b4292 --- /dev/null +++ b/frontend/src/app/hooks/useServicesForm.jsx @@ -0,0 +1,64 @@ +"use client"; + +import { useState } from "react"; +import { useForm } from "react-hook-form"; + +const useServicesForm = () => { + const [triggerAlert, setTriggerAlert] = useState(false); + const [disableScaling, setDisableScaling] = useState(true); + const [disableReadiness, setDisableReadiness] = useState(true); + const [disableLiveness, setDisableLiveness] = useState(true); + const { + register, + handleSubmit, + watch, + reset, + formState: { errors }, + } = useForm({ + defaultValues: { + minPods: "", + maxPods: "", + readinessPath: "", + readinessPort: "", + livenessPath: "", + livenessPort: "", + }, + }); + + const minPods = watch("minPods"); + const maxPods = watch("maxPods"); + const readinessPath = watch("readinessPath"); + const readinessPort = watch("readinessPort"); + const livenessPath = watch("livenessPath"); + const livenessPort = watch("livenessPort"); + + const onSubmit = (data) => { + setTriggerAlert(true); + + console.log("Submitted data:", data); + }; + + return { + register, + handleSubmit, + watch, + errors, + onSubmit, + triggerAlert, + setTriggerAlert, + setDisableScaling, + disableScaling, + setDisableReadiness, + disableReadiness, + setDisableLiveness, + disableLiveness, + minPods, + maxPods, + readinessPath, + readinessPort, + livenessPort, + livenessPath, + }; +}; + +export default useServicesForm; diff --git a/frontend/src/app/hooks/useUserForm.jsx b/frontend/src/app/hooks/useUserForm.jsx new file mode 100644 index 0000000..06af08d --- /dev/null +++ b/frontend/src/app/hooks/useUserForm.jsx @@ -0,0 +1,33 @@ +"use client"; + +import { useState } from "react"; +import { useForm } from "react-hook-form"; + +const useUserForm = () => { + const [triggerAlert, setTriggerAlert] = useState(false); + + const { + register, + handleSubmit, + watch, + formState: { errors }, + } = useForm(); + + const onSubmit = (data) => { + setTriggerAlert(true); + + console.log("Submitted data:", data); + }; + + return { + register, + handleSubmit, + watch, + errors, + onSubmit, + triggerAlert, + setTriggerAlert, + }; +}; + +export default useUserForm; diff --git a/frontend/src/app/organization/add/page.jsx b/frontend/src/app/organization/add/page.jsx index c3bea80..642ff3a 100644 --- a/frontend/src/app/organization/add/page.jsx +++ b/frontend/src/app/organization/add/page.jsx @@ -8,22 +8,17 @@ import TopToolTip from "@/app/components/topToolTip/TopToolTip"; import TextField from "@/app/components/fields/textfield"; import Alert from "@/app/components/alerts/Alert"; import Prompts from "@/app/components/prompts/Prompts"; +import useOrganizationForm from "@/app/hooks/useOrganizationForm"; const AddCredentials = () => { - const [triggerAlert, setTriggerAlert] = useState(false); - const inputRef = useRef(); - const [error, setError] = useState(false); - const HandleSubmit = (e) => { - e.preventDefault(); - - if (!inputRef.current.value.trim()) { - setError(true); - console.log("alsdjfakjhsks"); // triggers red border - return; - } - - setError(false); - setTriggerAlert(true); - }; + const { + organizationName, + error, + triggerAlert, + handleChange, + handleValidation, + handleSubmit, + setTriggerAlert, + } = useOrganizationForm(); return (
@@ -47,7 +42,7 @@ const AddCredentials = () => {
@@ -105,8 +100,10 @@ const AddCredentials = () => {
diff --git a/frontend/src/app/projects/add/page.jsx b/frontend/src/app/projects/add/page.jsx index ecd45fa..6974cbb 100644 --- a/frontend/src/app/projects/add/page.jsx +++ b/frontend/src/app/projects/add/page.jsx @@ -1,3 +1,4 @@ +"use client"; import React from "react"; import globalStyle from "../../globalStyle.module.css"; import TopHeader from "@/app/components/topHeader/TopHeader"; @@ -5,11 +6,27 @@ import styles from "./styles.module.css"; import TopToolTip from "@/app/components/topToolTip/TopToolTip"; import TextField from "@/app/components/fields/textfield"; import SelectField from "@/app/components/select/SelectField"; -import WarningIcon from "@/app/components/icons/warning"; import Prompts from "@/app/components/prompts/Prompts"; +import Alert from "@/app/components/alerts/Alert"; +import useProjectForm from "@/app/hooks/useProjectForm"; const AddProject = () => { + const { + register, + handleSubmit, + errors, + onSubmit, + triggerAlert, + setTriggerAlert, + } = useProjectForm(); return (
+ {triggerAlert && ( + setEditState(true)} + title="Create Organization" + /> + )}
{ />
- +

@@ -29,8 +50,12 @@ const AddProject = () => {

- - + +
@@ -40,7 +65,11 @@ const AddProject = () => {

- +
diff --git a/frontend/src/app/projects/view/add-from-scratch/page.jsx b/frontend/src/app/projects/view/add-from-scratch/page.jsx index b0bb826..eb69fd6 100644 --- a/frontend/src/app/projects/view/add-from-scratch/page.jsx +++ b/frontend/src/app/projects/view/add-from-scratch/page.jsx @@ -11,23 +11,44 @@ import AddConfigMapModal from "../variableModals/AddConfigMap/AddConfigMapModal" import DeleteIcon from "@/app/components/icons/delete"; import CustomCheckbox from "@/app/components/checkbox/CheckBox"; import SelectField from "@/app/components/select/SelectField"; +import useServicesForm from "@/app/hooks/useServicesForm"; +import Alert from "@/app/components/alerts/Alert"; const AddServices = () => { const [triggerVariableDropDown, setTriggerVariableDropDown] = useState(false); const [triggerAddVariable, setTriggerAddVariable] = useState(false); const [triggerAddVolume, setTriggerAddVolume] = useState(false); const [triggeAddConfigMap, setTriggerAddConfigMap] = useState(false); - const [disableScaling, setDisableScaling] = useState(true); - const [disableReadiness, setDisableReadiness] = useState(true); - const [disableLiveness, setDisableLiveness] = useState(true); - const [minPods, setMinPods] = useState(""); - const [maxPods, setMaxPods] = useState(""); - const [readinessPath, setReadinessPath] = useState(""); - const [readinessPort, setReadinessPort] = useState(""); - const [livenessPath, setLivenessPath] = useState(""); - const [livenessPort, setLivenessPort] = useState(""); + + const { + register, + handleSubmit, + errors, + onSubmit, + triggerAlert, + disableScaling, + disableReadiness, + disableLiveness, + setDisableScaling, + setDisableReadiness, + setDisableLiveness, + setTriggerAlert, + minPods, + maxPods, + readinessPath, + readinessPort, + livenessPort, + livenessPath, + } = useServicesForm(); return (
+ {triggerAlert && ( + setEditState(true)} + title="Add User" + /> + )} {triggerAddVariable && ( )} @@ -47,7 +68,11 @@ const AddServices = () => { requiredButtons={["title", "save"]} />
- +

Project Details

@@ -66,11 +91,19 @@ const AddServices = () => {

Name

- +

Version

- +
@@ -78,13 +111,21 @@ const AddServices = () => {

Image (Optional)

- +

Port

- +
@@ -121,21 +162,37 @@ const AddServices = () => {

CPU Request (MB)

- +

CPU Limit (MB)

- +

Memory Request (MB)

- +

Memory Limit (MB)

- +
@@ -148,11 +205,7 @@ const AddServices = () => {

Auto Scaling

{ - setDisableScaling(!disableScaling); - setMinPods(""); - setMaxPods(""); - }} + setChecked={() => setDisableScaling(!disableScaling)} />
@@ -165,19 +218,21 @@ const AddServices = () => { setMinPods(e.target.value)} - value={minPods} + {...register("minPods", { + required: maxPods.trim() === "" ? false : true, + })} + hasError={!!errors.minPods} />

Maximum pods

setMaxPods(e.target.value)} disabled={disableScaling} + {...register("maxPods", { + required: minPods.trim() === "" ? false : true, + })} + hasError={!!errors.maxPods} />
@@ -192,11 +247,9 @@ const AddServices = () => {

Readiness

{ - setDisableReadiness(!disableReadiness); - setReadinessPath(""); - setReadinessPort(""); - }} + setChecked={() => + setDisableReadiness(!disableReadiness) + } />
@@ -209,9 +262,11 @@ const AddServices = () => { setReadinessPath(e.target.value)} + {...register("readinessPath", { + required: + readinessPort.trim() === "" ? false : true, + })} + hasError={!!errors.readinessPath} />
@@ -219,9 +274,11 @@ const AddServices = () => { setReadinessPort(e.target.value)} + {...register("readinessPort", { + required: + readinessPath.trim() === "" ? false : true, + })} + hasError={!!errors.readinessPort} />
@@ -236,12 +293,9 @@ const AddServices = () => {

Liveness

{ - console.log("alsdjhfkjas"); - setDisableLiveness(!disableLiveness); - setLivenessPath(""); - setLivenessPort(""); - }} + setChecked={() => + setDisableLiveness(!disableLiveness) + } />
@@ -253,9 +307,11 @@ const AddServices = () => { setLivenessPath(e.target.value)} + {...register("livenessPath", { + required: + livenessPort.trim() === "" ? false : true, + })} + hasError={!!errors.livenessPath} />
@@ -263,9 +319,11 @@ const AddServices = () => { setLivenessPort(e.target.value)} + {...register("livenessPort", { + required: + livenessPath.trim() === "" ? false : true, + })} + hasError={!!errors.livenessPort} />
diff --git a/frontend/src/app/roles/add/page.jsx b/frontend/src/app/roles/add/page.jsx index 25a0f17..2d3d4a6 100644 --- a/frontend/src/app/roles/add/page.jsx +++ b/frontend/src/app/roles/add/page.jsx @@ -1,13 +1,31 @@ +"use client"; import React from "react"; import TopHeader from "@/app/components/topHeader/TopHeader"; import globalStyle from "../../globalStyle.module.css"; import addRoleStyle from "./styles.module.css"; import TextField from "@/app/components/fields/textfield"; import Permissions from "@/app/components/permissions/Permissions"; +import useUserForm from "@/app/hooks/useUserForm"; +import Alert from "@/app/components/alerts/Alert"; const page = () => { + const { + register, + handleSubmit, + errors, + onSubmit, + triggerAlert, + setTriggerAlert, + } = useUserForm(); return (
+ {triggerAlert && ( + setEditState(true)} + title="Add Role" + /> + )}
{
{/* Input fields */} - + {/* Email */}
@@ -39,7 +61,11 @@ const page = () => {
{/* Input field */}
- +
@@ -52,7 +78,11 @@ const page = () => { {/* Input field */}
- +
diff --git a/frontend/src/app/users/add/page.jsx b/frontend/src/app/users/add/page.jsx index 252f2a0..d5c144f 100644 --- a/frontend/src/app/users/add/page.jsx +++ b/frontend/src/app/users/add/page.jsx @@ -1,3 +1,4 @@ +"use client"; import React from "react"; import TopHeader from "@/app/components/topHeader/TopHeader"; import globalStyle from "../../globalStyle.module.css"; @@ -5,9 +6,27 @@ import addUserStyle from "./styles.module.css"; import TextField from "@/app/components/fields/textfield"; import SelectField from "@/app/components/select/SelectField"; import Permissions from "@/app/components/permissions/Permissions"; +import useUserForm from "@/app/hooks/useUserForm"; +import Alert from "@/app/components/alerts/Alert"; const page = () => { + const { + register, + handleSubmit, + errors, + onSubmit, + triggerAlert, + setTriggerAlert, + } = useUserForm(); + return (
+ {triggerAlert && ( + setEditState(true)} + title="Add User" + /> + )}
{
{/* Input fields */} - + {/* Role and Dropdown */} {
{/* Input field */}
- +
@@ -61,7 +88,11 @@ const page = () => { {/* Input field */}
- +