Merge branch 'DEVELOPMENT' of https://gitea.internship.project-moonshot.com/Laux/Frontend-Internal-Developer-Platform into DEVELOPMENT
This commit is contained in:
@@ -6,98 +6,175 @@ import TopToolTip from "@/app/components/topToolTip/TopToolTip";
|
|||||||
import globalStyle from "../../globalStyle.module.css";
|
import globalStyle from "../../globalStyle.module.css";
|
||||||
import createAgentStyle from "./styles.module.css";
|
import createAgentStyle from "./styles.module.css";
|
||||||
import Prompts from "@/app/components/prompts/Prompts";
|
import Prompts from "@/app/components/prompts/Prompts";
|
||||||
|
import useAgentForm from "@/app/hooks/useAgentForm";
|
||||||
|
import Alert from "@/app/components/alerts/Alert";
|
||||||
|
import Checkbox from "@/app/components/customCheckbox/Checkbox";
|
||||||
|
|
||||||
const ViewAgentPage = () => {
|
const ViewAgentPage = () => {
|
||||||
const [isChecked, setIsChecked] = useState(false);
|
const [useVpn, setUseVpn] = useState(true);
|
||||||
|
const [enableLoki, setEnableLoki] = useState(true);
|
||||||
const handleCheckboxChange = (e) => {
|
const {
|
||||||
setIsChecked(e.target.checked);
|
register,
|
||||||
};
|
handleSubmit,
|
||||||
|
errors,
|
||||||
|
onSubmit,
|
||||||
|
triggerAlert,
|
||||||
|
setTriggerAlert,
|
||||||
|
} = useAgentForm();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={globalStyle.section}>
|
<div className={globalStyle.section}>
|
||||||
|
{triggerAlert && (
|
||||||
|
<Alert
|
||||||
|
setTriggerAlert={setTriggerAlert}
|
||||||
|
onClick={() => setEditState(true)}
|
||||||
|
title="Create New Agent"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<div className={globalStyle.mainContainer}>
|
<div className={globalStyle.mainContainer}>
|
||||||
<div className={globalStyle.container}>
|
<div className={globalStyle.container}>
|
||||||
<TopHeader
|
<TopHeader
|
||||||
buttonText="Save"
|
topbarTitle="View Agent"
|
||||||
cancelButtonText="Cancel"
|
|
||||||
topbarTitle="Update Agent"
|
|
||||||
state="add"
|
state="add"
|
||||||
requiredButtons={["update", "title"]}
|
requiredButtons={["edit", "back"]}
|
||||||
/>
|
/>
|
||||||
{/* Create agent Container */}
|
{/* Create agent Container */}
|
||||||
|
<form
|
||||||
|
className={createAgentStyle.formContainer}
|
||||||
|
id="form"
|
||||||
|
onSubmit={handleSubmit(onSubmit)}
|
||||||
|
>
|
||||||
<div className={createAgentStyle.createAgentContainer}>
|
<div className={createAgentStyle.createAgentContainer}>
|
||||||
<TopToolTip />
|
<div className={createAgentStyle.div}></div>
|
||||||
<div className={createAgentStyle.inputMainContainer}>
|
<div className={createAgentStyle.inputMainContainer}>
|
||||||
{/* Header */}
|
{/* AGENT FORM */}
|
||||||
<div className={createAgentStyle.headerContainer}>
|
<div className={createAgentStyle.headerContainer}>
|
||||||
<div className={createAgentStyle.headerTxt}>
|
<div className={createAgentStyle.headerTxt}>
|
||||||
<p>Agent Details</p>
|
<p>Agent Details</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/* Agent name input */}
|
|
||||||
<div className={createAgentStyle.inputContainer}>
|
<div className={createAgentStyle.inputContainer}>
|
||||||
{/* Label */}
|
|
||||||
<div className={createAgentStyle.labelContainer}>
|
<div className={createAgentStyle.labelContainer}>
|
||||||
<p>Agent Name</p>
|
<p>Agent Name</p>
|
||||||
{/* <p className={createAgentStyle.required}>*</p> */}
|
{/* <p className={createAgentStyle.required}>*</p> */}
|
||||||
</div>
|
</div>
|
||||||
{/* Input Field */}
|
<TextField
|
||||||
<TextField placeHolder="Enter agent name" />
|
placeHolder="Enter agent name"
|
||||||
|
{...register("agentName", { required: true })}
|
||||||
|
hasError={!!errors.agentName}
|
||||||
|
/>
|
||||||
<Prompts show={false} />
|
<Prompts show={false} />
|
||||||
</div>
|
</div>
|
||||||
{/* Kubernetes API input */}
|
|
||||||
<div className={createAgentStyle.inputContainer}>
|
<div className={createAgentStyle.inputContainer}>
|
||||||
{/* Label */}
|
|
||||||
<div className={createAgentStyle.labelContainer}>
|
<div className={createAgentStyle.labelContainer}>
|
||||||
<p>Kubernetes API Proxy Name</p>
|
<p>Kubernetes API Proxy Name</p>
|
||||||
{/* <p className={createAgentStyle.required}>*</p> */}
|
{/* <p className={createAgentStyle.required}>*</p> */}
|
||||||
</div>
|
</div>
|
||||||
{/* Input Field */}
|
<TextField
|
||||||
<TextField placeHolder="Enter proxy name" />
|
placeHolder="Enter proxy name"
|
||||||
|
{...register("proxyName", { required: true })}
|
||||||
|
hasError={!!errors.proxyName}
|
||||||
|
/>
|
||||||
<Prompts show={false} />
|
<Prompts show={false} />
|
||||||
</div>
|
</div>
|
||||||
{/* Checkbox */}
|
<Checkbox
|
||||||
<div className={createAgentStyle.checkboxMainContainer}>
|
checked={useVpn}
|
||||||
<div className={createAgentStyle.checkboxContainer}>
|
onChange={(e) => setUseVpn(e.target.checked)}
|
||||||
<div className={createAgentStyle.checkbox}>
|
label="Use Tailscale VPN"
|
||||||
{/* Checkbox */}
|
description={
|
||||||
<div className={createAgentStyle.check}>
|
<>
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
checked={isChecked}
|
|
||||||
onChange={handleCheckboxChange}
|
|
||||||
className={createAgentStyle.hiddenCheckbox}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/* List */}
|
|
||||||
<div className={createAgentStyle.list}>
|
|
||||||
<p className={createAgentStyle.placeholderTxt}>
|
|
||||||
Use Tailscale VPN
|
|
||||||
</p>
|
|
||||||
<p className={createAgentStyle.secondaryTxt}>
|
|
||||||
Enable Tailscale for secure private networking. When
|
Enable Tailscale for secure private networking. When
|
||||||
enabled, <br /> the endpoint will be automatically
|
enabled, <br />
|
||||||
resolved from Tailscale.
|
the endpoint will be automatically resolved from
|
||||||
</p>
|
Tailscale.
|
||||||
</div>
|
</>
|
||||||
</div>
|
}
|
||||||
</div>
|
/>
|
||||||
</div>
|
|
||||||
{/* Agent endpoint */}
|
{/* Agent endpoint */}
|
||||||
<div className={createAgentStyle.inputContainer}>
|
<div className={createAgentStyle.inputContainer}>
|
||||||
{/* Label */}
|
|
||||||
<div className={createAgentStyle.labelContainer}>
|
<div className={createAgentStyle.labelContainer}>
|
||||||
<p>Agent Endpoint</p>
|
<p>Tailscale Device Prefix</p>
|
||||||
{/* <p className={createAgentStyle.required}>*</p> */}
|
{/* <p className={createAgentStyle.required}>*</p> */}
|
||||||
</div>
|
</div>
|
||||||
{/* Input Field */}
|
<TextField
|
||||||
<TextField placeHolder="e.g., http://agent-01.example.com:8080" />
|
placeHolder="doks-onecbdev-agent"
|
||||||
|
{...register("agentEndpoint", { required: true })}
|
||||||
|
hasError={!!errors.agentEndpoint}
|
||||||
|
/>
|
||||||
|
<Prompts show={false} />
|
||||||
|
</div>
|
||||||
|
<div className={createAgentStyle.inputContainer}>
|
||||||
|
<div className={createAgentStyle.labelContainer}>
|
||||||
|
<p>Tailscale Port</p>
|
||||||
|
{/* <p className={createAgentStyle.required}>*</p> */}
|
||||||
|
</div>
|
||||||
|
<TextField
|
||||||
|
placeHolder="6969"
|
||||||
|
{...register("agentEndpoint", { required: true })}
|
||||||
|
hasError={!!errors.agentEndpoint}
|
||||||
|
/>
|
||||||
<Prompts show={false} />
|
<Prompts show={false} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className={createAgentStyle.lokiContainer}>
|
||||||
|
{/* Header */}
|
||||||
|
<div className={createAgentStyle.headerContainer}>
|
||||||
|
<div className={createAgentStyle.headerTxt}>
|
||||||
|
<p>Loki Integration (Optional)</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<Checkbox
|
||||||
|
checked={enableLoki}
|
||||||
|
onChange={(e) => setEnableLoki(e.target.checked)}
|
||||||
|
label="Enable Loki Logging"
|
||||||
|
description="Configure Loki for centralized logging and log streaming."
|
||||||
|
/>
|
||||||
|
|
||||||
|
{enableLoki && (
|
||||||
|
<>
|
||||||
|
<div className={createAgentStyle.inputContainer}>
|
||||||
|
<div className={createAgentStyle.labelContainer}>
|
||||||
|
<p>Loki Endpoint</p>
|
||||||
|
{/* <p className={createAgentStyle.required}>*</p> */}
|
||||||
|
</div>
|
||||||
|
<TextField
|
||||||
|
placeHolder="https://loki.project-moonshot.com/"
|
||||||
|
{...register("endpoint", { required: true })}
|
||||||
|
hasError={!!errors.endpoint}
|
||||||
|
/>
|
||||||
|
<Prompts show={false} />
|
||||||
|
</div>
|
||||||
|
<div className={createAgentStyle.inputContainer}>
|
||||||
|
<div className={createAgentStyle.labelContainer}>
|
||||||
|
<p>Tenant Name</p>
|
||||||
|
{/* <p className={createAgentStyle.required}>*</p> */}
|
||||||
|
</div>
|
||||||
|
<TextField
|
||||||
|
placeHolder="doks-dev"
|
||||||
|
{...register("tenantName", { required: true })}
|
||||||
|
hasError={!!errors.tenantName}
|
||||||
|
/>
|
||||||
|
<Prompts show={false} />
|
||||||
|
</div>
|
||||||
|
<div className={createAgentStyle.inputContainer}>
|
||||||
|
<div className={createAgentStyle.labelContainer}>
|
||||||
|
<p>Password</p>
|
||||||
|
{/* <p className={createAgentStyle.required}>*</p> */}
|
||||||
|
</div>
|
||||||
|
<TextField
|
||||||
|
placeHolder="Enter Password"
|
||||||
|
{...register("password", { required: true })}
|
||||||
|
hasError={!!errors.password}
|
||||||
|
/>
|
||||||
|
<Prompts show={false} />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,23 +1,31 @@
|
|||||||
.createAgentContainer {
|
.formContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: flex-start;
|
||||||
gap: 48px;
|
gap: 10px;
|
||||||
flex: 1 0 0;
|
flex: 1 0 0;
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.createAgentContainer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
align-self: stretch;
|
||||||
|
gap: 16px;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
padding-top: 48px;
|
||||||
|
height: calc(100vh - 100px - 70px);
|
||||||
|
overflow-y: auto;
|
||||||
|
scrollbar-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
.inputMainContainer {
|
.inputMainContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: 24px;
|
gap: 24px;
|
||||||
border-radius: 8px;
|
|
||||||
height: calc(100vh - 260px);
|
|
||||||
position: relative;
|
|
||||||
overflow: auto;
|
|
||||||
scrollbar-width: none;
|
|
||||||
}
|
}
|
||||||
.headerContainer {
|
.headerContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -34,9 +42,9 @@
|
|||||||
flex: 1 0 0;
|
flex: 1 0 0;
|
||||||
}
|
}
|
||||||
.headerTxt > p {
|
.headerTxt > p {
|
||||||
width: 163px;
|
/* width: 163px; */
|
||||||
|
align-self: stretch;
|
||||||
color: #d2d3e1;
|
color: #d2d3e1;
|
||||||
color: color(display-p3 0.8235 0.8275 0.8784);
|
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -70,112 +78,11 @@
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkboxMainContainer {
|
.lokiContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
width: 548px;
|
||||||
|
padding: 24px;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: 10px;
|
gap: 24px;
|
||||||
align-self: stretch;
|
|
||||||
}
|
|
||||||
.checkboxContainer {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
align-self: stretch;
|
|
||||||
}
|
|
||||||
.checkbox {
|
|
||||||
display: flex;
|
|
||||||
padding: var(--Basic-Forms-Checkbox-Input-Sizing-Y-SM, 10px)
|
|
||||||
var(--Basic-Forms-Checkbox-Input-Sizing-X-SM, 12px);
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: var(--Basic-Forms-Checkbox-Gap-Between, 16px);
|
|
||||||
flex: 1 0 0;
|
|
||||||
border-radius: var(--Basic-Forms-Checkbox-Border-Radius, 8px);
|
|
||||||
background: #1d1e2a;
|
|
||||||
background: color(display-p3 0.1137 0.1176 0.1608);
|
|
||||||
}
|
|
||||||
.check {
|
|
||||||
display: flex;
|
|
||||||
padding-top: var(--Basic-Forms-Checkbox-Inline-Y, 4px);
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: var(--Basic-Forms-Checkbox-Inline-Gap-Between, 10px);
|
|
||||||
}
|
|
||||||
.hiddenCheckbox {
|
|
||||||
appearance: none;
|
|
||||||
-webkit-appearance: none;
|
|
||||||
-moz-appearance: none;
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
border-radius: var(--Basic-Forms-Checkbox-Check-Icon-Border-Radius, 4px);
|
|
||||||
border: 1px solid
|
|
||||||
var(--Basic-Forms-Checkbox-Check-Icon-Border-Border-Active-Color, #0067fd);
|
|
||||||
border: 1px solid
|
|
||||||
var(
|
|
||||||
--Basic-Forms-Checkbox-Check-Icon-Border-Border-Active-Color,
|
|
||||||
color(display-p3 0.1451 0.3882 0.9216)
|
|
||||||
);
|
|
||||||
cursor: pointer;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.hiddenCheckbox:checked {
|
|
||||||
border-radius: var(--Basic-Forms-Checkbox-Check-Icon-Border-Radius, 4px);
|
|
||||||
border: 1px solid
|
|
||||||
var(--Basic-Forms-Checkbox-Check-Icon-Border-Border-Active-Color, #0067fd);
|
|
||||||
border: 1px solid
|
|
||||||
var(
|
|
||||||
--Basic-Forms-Checkbox-Check-Icon-Border-Border-Active-Color,
|
|
||||||
color(display-p3 0.1451 0.3882 0.9216)
|
|
||||||
);
|
|
||||||
background: var(
|
|
||||||
--Basic-Forms-Checkbox-Check-Icon-Background-Bg-Active-Color,
|
|
||||||
#0067fd
|
|
||||||
);
|
|
||||||
background: var(
|
|
||||||
--Basic-Forms-Checkbox-Check-Icon-Background-Bg-Active-Color,
|
|
||||||
color(display-p3 0.1451 0.3882 0.9216)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
.hiddenCheckbox::after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='8' viewBox='0 0 11 8' fill='none'%3E%3Cpath d='M9.83333 0.5L3.41667 6.91667L0.5 4' stroke='white' style='stroke:white;stroke-opacity:1;' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: center;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
.hiddenCheckbox:checked::after {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.list {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: 4px;
|
|
||||||
flex: 1 0 0;
|
|
||||||
}
|
|
||||||
.placeholderTxt {
|
|
||||||
align-self: stretch;
|
|
||||||
color: #d2d3e1;
|
|
||||||
color: color(display-p3 0.8235 0.8275 0.8784);
|
|
||||||
font-family: Inter;
|
|
||||||
font-size: 16px;
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 500;
|
|
||||||
line-height: 24px; /* 150% */
|
|
||||||
letter-spacing: 0.08px;
|
|
||||||
}
|
|
||||||
.secondaryTxt {
|
|
||||||
align-self: stretch;
|
|
||||||
color: #697281;
|
|
||||||
color: color(display-p3 0.4196 0.4471 0.502);
|
|
||||||
font-family: Inter;
|
|
||||||
font-size: 14px;
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 500;
|
|
||||||
line-height: 20px; /* 142.857% */
|
|
||||||
letter-spacing: 0.07px;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,13 +8,11 @@ import createAgentStyle from "./styles.module.css";
|
|||||||
import Prompts from "@/app/components/prompts/Prompts";
|
import Prompts from "@/app/components/prompts/Prompts";
|
||||||
import useAgentForm from "@/app/hooks/useAgentForm";
|
import useAgentForm from "@/app/hooks/useAgentForm";
|
||||||
import Alert from "@/app/components/alerts/Alert";
|
import Alert from "@/app/components/alerts/Alert";
|
||||||
|
import Checkbox from "@/app/components/customCheckbox/Checkbox";
|
||||||
|
|
||||||
const AddAgentPage = () => {
|
const AddAgentPage = () => {
|
||||||
const [isChecked, setIsChecked] = useState(false);
|
const [useVpn, setUseVpn] = useState(false);
|
||||||
|
const [enableLoki, setEnableLoki] = useState(false);
|
||||||
const handleCheckboxChange = (e) => {
|
|
||||||
setIsChecked(e.target.checked);
|
|
||||||
};
|
|
||||||
const {
|
const {
|
||||||
register,
|
register,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
@@ -42,28 +40,27 @@ const AddAgentPage = () => {
|
|||||||
state="add"
|
state="add"
|
||||||
requiredButtons={["title", "save"]}
|
requiredButtons={["title", "save"]}
|
||||||
/>
|
/>
|
||||||
{/* Create agent Container */}
|
|
||||||
<div className={createAgentStyle.createAgentContainer}>
|
|
||||||
<TopToolTip />
|
<TopToolTip />
|
||||||
|
{/* Create agent Container */}
|
||||||
<form
|
<form
|
||||||
className={createAgentStyle.inputMainContainer}
|
className={createAgentStyle.formContainer}
|
||||||
id="form"
|
id="form"
|
||||||
onSubmit={handleSubmit(onSubmit)}
|
onSubmit={handleSubmit(onSubmit)}
|
||||||
>
|
>
|
||||||
{/* Header */}
|
<div className={createAgentStyle.createAgentContainer}>
|
||||||
|
<div className={createAgentStyle.div}></div>
|
||||||
|
<div className={createAgentStyle.inputMainContainer}>
|
||||||
|
{/* AGENT FORM */}
|
||||||
<div className={createAgentStyle.headerContainer}>
|
<div className={createAgentStyle.headerContainer}>
|
||||||
<div className={createAgentStyle.headerTxt}>
|
<div className={createAgentStyle.headerTxt}>
|
||||||
<p>Agent Details</p>
|
<p>Agent Details</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/* Agent name input */}
|
|
||||||
<div className={createAgentStyle.inputContainer}>
|
<div className={createAgentStyle.inputContainer}>
|
||||||
{/* Label */}
|
|
||||||
<div className={createAgentStyle.labelContainer}>
|
<div className={createAgentStyle.labelContainer}>
|
||||||
<p>Agent Name</p>
|
<p>Agent Name</p>
|
||||||
<p className={createAgentStyle.required}>*</p>
|
<p className={createAgentStyle.required}>*</p>
|
||||||
</div>
|
</div>
|
||||||
{/* Input Field */}
|
|
||||||
<TextField
|
<TextField
|
||||||
placeHolder="Enter agent name"
|
placeHolder="Enter agent name"
|
||||||
{...register("agentName", { required: true })}
|
{...register("agentName", { required: true })}
|
||||||
@@ -71,14 +68,11 @@ const AddAgentPage = () => {
|
|||||||
/>
|
/>
|
||||||
<Prompts show={false} />
|
<Prompts show={false} />
|
||||||
</div>
|
</div>
|
||||||
{/* Kubernetes API input */}
|
|
||||||
<div className={createAgentStyle.inputContainer}>
|
<div className={createAgentStyle.inputContainer}>
|
||||||
{/* Label */}
|
|
||||||
<div className={createAgentStyle.labelContainer}>
|
<div className={createAgentStyle.labelContainer}>
|
||||||
<p>Kubernetes API Proxy Name</p>
|
<p>Kubernetes API Proxy Name</p>
|
||||||
<p className={createAgentStyle.required}>*</p>
|
<p className={createAgentStyle.required}>*</p>
|
||||||
</div>
|
</div>
|
||||||
{/* Input Field */}
|
|
||||||
<TextField
|
<TextField
|
||||||
placeHolder="Enter proxy name"
|
placeHolder="Enter proxy name"
|
||||||
{...register("proxyName", { required: true })}
|
{...register("proxyName", { required: true })}
|
||||||
@@ -86,41 +80,25 @@ const AddAgentPage = () => {
|
|||||||
/>
|
/>
|
||||||
<Prompts show={false} />
|
<Prompts show={false} />
|
||||||
</div>
|
</div>
|
||||||
{/* Checkbox */}
|
<Checkbox
|
||||||
<div className={createAgentStyle.checkboxMainContainer}>
|
checked={useVpn}
|
||||||
<div className={createAgentStyle.checkboxContainer}>
|
onChange={(e) => setUseVpn(e.target.checked)}
|
||||||
<div className={createAgentStyle.checkbox}>
|
label="Use Tailscale VPN"
|
||||||
{/* Checkbox */}
|
description={
|
||||||
<div className={createAgentStyle.check}>
|
<>
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
checked={isChecked}
|
|
||||||
onChange={handleCheckboxChange}
|
|
||||||
className={createAgentStyle.hiddenCheckbox}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/* List */}
|
|
||||||
<div className={createAgentStyle.list}>
|
|
||||||
<p className={createAgentStyle.placeholderTxt}>
|
|
||||||
Use Tailscale VPN
|
|
||||||
</p>
|
|
||||||
<p className={createAgentStyle.secondaryTxt}>
|
|
||||||
Enable Tailscale for secure private networking. When
|
Enable Tailscale for secure private networking. When
|
||||||
enabled, <br /> the endpoint will be automatically
|
enabled, <br />
|
||||||
resolved from Tailscale.
|
the endpoint will be automatically resolved from
|
||||||
</p>
|
Tailscale.
|
||||||
</div>
|
</>
|
||||||
</div>
|
}
|
||||||
</div>
|
/>
|
||||||
</div>
|
|
||||||
{/* Agent endpoint */}
|
{/* Agent endpoint */}
|
||||||
<div className={createAgentStyle.inputContainer}>
|
<div className={createAgentStyle.inputContainer}>
|
||||||
{/* Label */}
|
|
||||||
<div className={createAgentStyle.labelContainer}>
|
<div className={createAgentStyle.labelContainer}>
|
||||||
<p>Agent Endpoint</p>
|
<p>Agent Endpoint</p>
|
||||||
<p className={createAgentStyle.required}>*</p>
|
<p className={createAgentStyle.required}>*</p>
|
||||||
</div>
|
</div>
|
||||||
{/* Input Field */}
|
|
||||||
<TextField
|
<TextField
|
||||||
placeHolder="e.g., http://agent-01.example.com:8080"
|
placeHolder="e.g., http://agent-01.example.com:8080"
|
||||||
{...register("agentEndpoint", { required: true })}
|
{...register("agentEndpoint", { required: true })}
|
||||||
@@ -128,8 +106,65 @@ const AddAgentPage = () => {
|
|||||||
/>
|
/>
|
||||||
<Prompts show={false} />
|
<Prompts show={false} />
|
||||||
</div>
|
</div>
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className={createAgentStyle.lokiContainer}>
|
||||||
|
{/* Header */}
|
||||||
|
<div className={createAgentStyle.headerContainer}>
|
||||||
|
<div className={createAgentStyle.headerTxt}>
|
||||||
|
<p>Loki Integration (Optional)</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Checkbox
|
||||||
|
checked={enableLoki}
|
||||||
|
onChange={(e) => setEnableLoki(e.target.checked)}
|
||||||
|
label="Enable Loki Logging"
|
||||||
|
description="Configure Loki for centralized logging and log streaming."
|
||||||
|
/>
|
||||||
|
|
||||||
|
{enableLoki && (
|
||||||
|
<>
|
||||||
|
<div className={createAgentStyle.inputContainer}>
|
||||||
|
<div className={createAgentStyle.labelContainer}>
|
||||||
|
<p>Loki Endpoint</p>
|
||||||
|
{/* <p className={createAgentStyle.required}>*</p> */}
|
||||||
|
</div>
|
||||||
|
<TextField
|
||||||
|
placeHolder="https://loki.project-moonshot.com/"
|
||||||
|
{...register("endpoint", { required: true })}
|
||||||
|
hasError={!!errors.endpoint}
|
||||||
|
/>
|
||||||
|
<Prompts show={false} />
|
||||||
|
</div>
|
||||||
|
<div className={createAgentStyle.inputContainer}>
|
||||||
|
<div className={createAgentStyle.labelContainer}>
|
||||||
|
<p>Tenant Name</p>
|
||||||
|
{/* <p className={createAgentStyle.required}>*</p> */}
|
||||||
|
</div>
|
||||||
|
<TextField
|
||||||
|
placeHolder="doks-dev"
|
||||||
|
{...register("tenantName", { required: true })}
|
||||||
|
hasError={!!errors.tenantName}
|
||||||
|
/>
|
||||||
|
<Prompts show={false} />
|
||||||
|
</div>
|
||||||
|
<div className={createAgentStyle.inputContainer}>
|
||||||
|
<div className={createAgentStyle.labelContainer}>
|
||||||
|
<p>Password</p>
|
||||||
|
{/* <p className={createAgentStyle.required}>*</p> */}
|
||||||
|
</div>
|
||||||
|
<TextField
|
||||||
|
placeHolder="Enter Password"
|
||||||
|
{...register("password", { required: true })}
|
||||||
|
hasError={!!errors.password}
|
||||||
|
/>
|
||||||
|
<Prompts show={false} />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,24 +1,32 @@
|
|||||||
.createAgentContainer {
|
.formContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: flex-start;
|
||||||
gap: 48px;
|
gap: 10px;
|
||||||
flex: 1 0 0;
|
flex: 1 0 0;
|
||||||
|
padding-top: 48px;
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.createAgentContainer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-start;
|
||||||
|
align-self: stretch;
|
||||||
|
/* Ibalhin ni ang padding sa formcontainer maoang nasa figma */
|
||||||
|
gap: 16px;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
height: calc(100vh - 100px - 48px - 110px);
|
||||||
|
overflow-y: auto;
|
||||||
|
scrollbar-width: none;
|
||||||
|
}
|
||||||
|
|
||||||
.inputMainContainer {
|
.inputMainContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 24px;
|
padding: 24px;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: 24px;
|
gap: 24px;
|
||||||
border-radius: 8px;
|
|
||||||
/* Remove ni kung mo ingon si sir grills */
|
|
||||||
height: calc(100vh - 260px);
|
|
||||||
position: relative;
|
|
||||||
overflow: auto;
|
|
||||||
scrollbar-width: none;
|
|
||||||
}
|
}
|
||||||
.headerContainer {
|
.headerContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -35,9 +43,9 @@
|
|||||||
flex: 1 0 0;
|
flex: 1 0 0;
|
||||||
}
|
}
|
||||||
.headerTxt > p {
|
.headerTxt > p {
|
||||||
width: 163px;
|
/* width: 163px; */
|
||||||
|
align-self: stretch;
|
||||||
color: #d2d3e1;
|
color: #d2d3e1;
|
||||||
color: color(display-p3 0.8235 0.8275 0.8784);
|
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -71,112 +79,11 @@
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkboxMainContainer {
|
.lokiContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
width: 548px;
|
||||||
|
padding: 24px;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: 10px;
|
gap: 24px;
|
||||||
align-self: stretch;
|
|
||||||
}
|
|
||||||
.checkboxContainer {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
align-self: stretch;
|
|
||||||
}
|
|
||||||
.checkbox {
|
|
||||||
display: flex;
|
|
||||||
padding: var(--Basic-Forms-Checkbox-Input-Sizing-Y-SM, 10px)
|
|
||||||
var(--Basic-Forms-Checkbox-Input-Sizing-X-SM, 12px);
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: var(--Basic-Forms-Checkbox-Gap-Between, 16px);
|
|
||||||
flex: 1 0 0;
|
|
||||||
border-radius: var(--Basic-Forms-Checkbox-Border-Radius, 8px);
|
|
||||||
background: #1d1e2a;
|
|
||||||
background: color(display-p3 0.1137 0.1176 0.1608);
|
|
||||||
}
|
|
||||||
.check {
|
|
||||||
display: flex;
|
|
||||||
padding-top: var(--Basic-Forms-Checkbox-Inline-Y, 4px);
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: var(--Basic-Forms-Checkbox-Inline-Gap-Between, 10px);
|
|
||||||
}
|
|
||||||
.hiddenCheckbox {
|
|
||||||
appearance: none;
|
|
||||||
-webkit-appearance: none;
|
|
||||||
-moz-appearance: none;
|
|
||||||
width: 16px;
|
|
||||||
height: 16px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
border-radius: var(--Basic-Forms-Checkbox-Check-Icon-Border-Radius, 4px);
|
|
||||||
border: 1px solid
|
|
||||||
var(--Basic-Forms-Checkbox-Check-Icon-Border-Border-Active-Color, #0067fd);
|
|
||||||
border: 1px solid
|
|
||||||
var(
|
|
||||||
--Basic-Forms-Checkbox-Check-Icon-Border-Border-Active-Color,
|
|
||||||
color(display-p3 0.1451 0.3882 0.9216)
|
|
||||||
);
|
|
||||||
cursor: pointer;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.hiddenCheckbox:checked {
|
|
||||||
border-radius: var(--Basic-Forms-Checkbox-Check-Icon-Border-Radius, 4px);
|
|
||||||
border: 1px solid
|
|
||||||
var(--Basic-Forms-Checkbox-Check-Icon-Border-Border-Active-Color, #0067fd);
|
|
||||||
border: 1px solid
|
|
||||||
var(
|
|
||||||
--Basic-Forms-Checkbox-Check-Icon-Border-Border-Active-Color,
|
|
||||||
color(display-p3 0.1451 0.3882 0.9216)
|
|
||||||
);
|
|
||||||
background: var(
|
|
||||||
--Basic-Forms-Checkbox-Check-Icon-Background-Bg-Active-Color,
|
|
||||||
#0067fd
|
|
||||||
);
|
|
||||||
background: var(
|
|
||||||
--Basic-Forms-Checkbox-Check-Icon-Background-Bg-Active-Color,
|
|
||||||
color(display-p3 0.1451 0.3882 0.9216)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
.hiddenCheckbox::after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='8' viewBox='0 0 11 8' fill='none'%3E%3Cpath d='M9.83333 0.5L3.41667 6.91667L0.5 4' stroke='white' style='stroke:white;stroke-opacity:1;' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-position: center;
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
.hiddenCheckbox:checked::after {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.list {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: 4px;
|
|
||||||
flex: 1 0 0;
|
|
||||||
}
|
|
||||||
.placeholderTxt {
|
|
||||||
align-self: stretch;
|
|
||||||
color: #d2d3e1;
|
|
||||||
color: color(display-p3 0.8235 0.8275 0.8784);
|
|
||||||
font-family: Inter;
|
|
||||||
font-size: 16px;
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 500;
|
|
||||||
line-height: 24px; /* 150% */
|
|
||||||
letter-spacing: 0.08px;
|
|
||||||
}
|
|
||||||
.secondaryTxt {
|
|
||||||
align-self: stretch;
|
|
||||||
color: #697281;
|
|
||||||
color: color(display-p3 0.4196 0.4471 0.502);
|
|
||||||
font-family: Inter;
|
|
||||||
font-size: 14px;
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: 500;
|
|
||||||
line-height: 20px; /* 142.857% */
|
|
||||||
letter-spacing: 0.07px;
|
|
||||||
}
|
}
|
||||||
|
|||||||
32
frontend/src/app/components/customCheckbox/Checkbox.jsx
Normal file
32
frontend/src/app/components/customCheckbox/Checkbox.jsx
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import React from "react";
|
||||||
|
import styles from "./styles.module.css";
|
||||||
|
|
||||||
|
const Checkbox = ({ checked, onChange, label, description }) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* Checkbox */}
|
||||||
|
<div className={styles.checkboxMainContainer}>
|
||||||
|
<div className={styles.checkboxContainer}>
|
||||||
|
<div className={styles.checkbox}>
|
||||||
|
{/* Checkbox */}
|
||||||
|
<div className={styles.check}>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={checked}
|
||||||
|
onChange={onChange}
|
||||||
|
className={styles.hiddenCheckbox}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/* List */}
|
||||||
|
<div className={styles.list}>
|
||||||
|
<p className={styles.placeholderTxt}>{label}</p>
|
||||||
|
<p className={styles.secondaryTxt}>{description}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Checkbox;
|
||||||
105
frontend/src/app/components/customCheckbox/styles.module.css
Normal file
105
frontend/src/app/components/customCheckbox/styles.module.css
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
.checkboxMainContainer {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 10px;
|
||||||
|
align-self: stretch;
|
||||||
|
}
|
||||||
|
.checkboxContainer {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
align-self: stretch;
|
||||||
|
}
|
||||||
|
.checkbox {
|
||||||
|
display: flex;
|
||||||
|
padding: var(--Basic-Forms-Checkbox-Input-Sizing-Y-SM, 10px)
|
||||||
|
var(--Basic-Forms-Checkbox-Input-Sizing-X-SM, 12px);
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: var(--Basic-Forms-Checkbox-Gap-Between, 16px);
|
||||||
|
flex: 1 0 0;
|
||||||
|
border-radius: var(--Basic-Forms-Checkbox-Border-Radius, 8px);
|
||||||
|
background: #1d1e2a;
|
||||||
|
background: color(display-p3 0.1137 0.1176 0.1608);
|
||||||
|
}
|
||||||
|
.check {
|
||||||
|
display: flex;
|
||||||
|
padding-top: var(--Basic-Forms-Checkbox-Inline-Y, 4px);
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: var(--Basic-Forms-Checkbox-Inline-Gap-Between, 10px);
|
||||||
|
}
|
||||||
|
.hiddenCheckbox {
|
||||||
|
appearance: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
border-radius: var(--Basic-Forms-Checkbox-Check-Icon-Border-Radius, 4px);
|
||||||
|
border: 1px solid
|
||||||
|
var(--Basic-Forms-Checkbox-Check-Icon-Border-Border-Color, #e5e7eb);
|
||||||
|
|
||||||
|
background: var(--Basic-Forms-Checkbox-Check-Icon-Background-Bg-Color, #fff);
|
||||||
|
}
|
||||||
|
.hiddenCheckbox:checked {
|
||||||
|
border-radius: var(--Basic-Forms-Checkbox-Check-Icon-Border-Radius, 4px);
|
||||||
|
border: 1px solid
|
||||||
|
var(--Basic-Forms-Checkbox-Check-Icon-Border-Border-Active-Color, #0067fd);
|
||||||
|
border: 1px solid
|
||||||
|
var(
|
||||||
|
--Basic-Forms-Checkbox-Check-Icon-Border-Border-Active-Color,
|
||||||
|
color(display-p3 0.1451 0.3882 0.9216)
|
||||||
|
);
|
||||||
|
background: var(
|
||||||
|
--Basic-Forms-Checkbox-Check-Icon-Background-Bg-Active-Color,
|
||||||
|
#0067fd
|
||||||
|
);
|
||||||
|
background: var(
|
||||||
|
--Basic-Forms-Checkbox-Check-Icon-Background-Bg-Active-Color,
|
||||||
|
color(display-p3 0.1451 0.3882 0.9216)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
.hiddenCheckbox::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='11' height='8' viewBox='0 0 11 8' fill='none'%3E%3Cpath d='M9.83333 0.5L3.41667 6.91667L0.5 4' stroke='white' style='stroke:white;stroke-opacity:1;' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
.hiddenCheckbox:checked::after {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 4px;
|
||||||
|
flex: 1 0 0;
|
||||||
|
}
|
||||||
|
.placeholderTxt {
|
||||||
|
align-self: stretch;
|
||||||
|
color: #d2d3e1;
|
||||||
|
color: color(display-p3 0.8235 0.8275 0.8784);
|
||||||
|
font-family: Inter;
|
||||||
|
font-size: 16px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 24px; /* 150% */
|
||||||
|
letter-spacing: 0.08px;
|
||||||
|
}
|
||||||
|
.secondaryTxt {
|
||||||
|
align-self: stretch;
|
||||||
|
color: #697281;
|
||||||
|
font-family: Inter;
|
||||||
|
font-size: 14px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 20px; /* 142.857% */
|
||||||
|
letter-spacing: 0.07px;
|
||||||
|
}
|
||||||
@@ -6,7 +6,6 @@ import useIsMobile from "@/app/hooks/useIsMobile";
|
|||||||
const Profile = () => {
|
const Profile = () => {
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [user, setUser] = useState("");
|
|
||||||
const sampleData = [
|
const sampleData = [
|
||||||
{
|
{
|
||||||
name: "JM Grills",
|
name: "JM Grills",
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
background: #1d1e2a;
|
background: #1d1e2a;
|
||||||
background: color(display-p3 0.1137 0.1176 0.1608);
|
|
||||||
}
|
}
|
||||||
.header {
|
.header {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
28
frontend/src/app/roles/role-card/Card.jsx
Normal file
28
frontend/src/app/roles/role-card/Card.jsx
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import DeleteIcon from "@/app/components/icons/delete";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
const Card = (props) => {
|
||||||
|
return (
|
||||||
|
<div className={styles.cardContainer} {...props}>
|
||||||
|
<div className={styles.cardDetails}>
|
||||||
|
<div className={styles.list}>
|
||||||
|
<p>Name</p>
|
||||||
|
<p>{props?.user?.email}</p>
|
||||||
|
</div>
|
||||||
|
<div className={styles.list}>
|
||||||
|
<p>Organization ID</p>
|
||||||
|
<p>{props?.user?.fullName}</p>
|
||||||
|
</div>
|
||||||
|
<div className={styles.list}>
|
||||||
|
<p>Permissions</p>
|
||||||
|
<p>{props?.user?.createdAt}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.cardAction}>
|
||||||
|
<DeleteIcon />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Card;
|
||||||
43
frontend/src/app/roles/role-card/styles.module.css
Normal file
43
frontend/src/app/roles/role-card/styles.module.css
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
.cardContainer {
|
||||||
|
display: flex;
|
||||||
|
padding: 16px 0;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 16px;
|
||||||
|
align-self: stretch;
|
||||||
|
border-bottom: 1px solid #2c2d3d;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.cardDetails {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 8px;
|
||||||
|
flex: 1 0 0;
|
||||||
|
}
|
||||||
|
.list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 5px;
|
||||||
|
align-self: stretch;
|
||||||
|
}
|
||||||
|
.list p {
|
||||||
|
color: #85869b;
|
||||||
|
font-family: Inter;
|
||||||
|
font-size: 14px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list p:nth-child(2) {
|
||||||
|
color: #eeeffd;
|
||||||
|
font-family: Inter;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
.cardAction {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 17px;
|
||||||
|
}
|
||||||
@@ -22,7 +22,6 @@
|
|||||||
padding: 12px 24px;
|
padding: 12px 24px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
color: #85869b;
|
color: #85869b;
|
||||||
color: color(display-p3 0.5216 0.5255 0.6);
|
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -41,7 +40,6 @@
|
|||||||
.tableBody td {
|
.tableBody td {
|
||||||
padding: 12px 24px;
|
padding: 12px 24px;
|
||||||
color: #eeeffd;
|
color: #eeeffd;
|
||||||
color: color(display-p3 0.9333 0.9373 0.9882);
|
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
@@ -55,9 +53,7 @@
|
|||||||
}
|
}
|
||||||
.tableBody tr:hover {
|
.tableBody tr:hover {
|
||||||
border-bottom: 1px solid rgba(129, 135, 255, 0.25);
|
border-bottom: 1px solid rgba(129, 135, 255, 0.25);
|
||||||
border-bottom: 1px solid color(display-p3 0.5098 0.5294 1 / 0.25);
|
|
||||||
background: rgba(129, 135, 255, 0.05);
|
background: rgba(129, 135, 255, 0.05);
|
||||||
background: color(display-p3 0.5098 0.5294 1 / 0.05);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tableActions {
|
.tableActions {
|
||||||
@@ -68,3 +64,16 @@
|
|||||||
gap: 12px;
|
gap: 12px;
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Mobile */
|
||||||
|
.cardContainer {
|
||||||
|
display: flex;
|
||||||
|
padding: 0 16px;
|
||||||
|
padding-bottom: 50px;
|
||||||
|
height: calc(100vh - 170px);
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 12px;
|
||||||
|
align-self: stretch;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,25 +8,25 @@ import ViewIcon from "../components/icons/view";
|
|||||||
import DeleteIcon from "../components/icons/delete";
|
import DeleteIcon from "../components/icons/delete";
|
||||||
import SuccessToast from "../components/toast/success/successToast";
|
import SuccessToast from "../components/toast/success/successToast";
|
||||||
import ActionButton from "../components/actionButton/ActionButton";
|
import ActionButton from "../components/actionButton/ActionButton";
|
||||||
|
import useIsMobile from "../hooks/useIsMobile";
|
||||||
|
import MobileSearchBar from "../components/mobileSearchBar/MobileSearchBar";
|
||||||
|
import Card from "./user-card/Card";
|
||||||
|
|
||||||
const UsersPage = () => {
|
const UsersPage = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const isMobile = useIsMobile();
|
||||||
const sampleData = [
|
const sampleData = [
|
||||||
{
|
{
|
||||||
id: 1,
|
|
||||||
email: "nino.moonshot@gmail.com",
|
email: "nino.moonshot@gmail.com",
|
||||||
fullName: "Nino Paul Cervantes",
|
fullName: "Nino Paul Cervantes",
|
||||||
createdAt: "2024-10-21 08:01:31.474 +0000 UTC",
|
createdAt: "2024-10-21 08:01:31.474 +0000 UTC",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 2,
|
|
||||||
email: "nino.moonshot@gmail.com",
|
email: "nino.moonshot@gmail.com",
|
||||||
fullName: "Nino Paul Cervantes",
|
fullName: "Nino Paul Cervantes",
|
||||||
createdAt: "2024-10-21 08:01:31.474 +0000 UTC",
|
createdAt: "2024-10-21 08:01:31.474 +0000 UTC",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 3,
|
|
||||||
email: "nino.moonshot@gmail.com",
|
email: "nino.moonshot@gmail.com",
|
||||||
fullName: "Nino Paul Cervantes",
|
fullName: "Nino Paul Cervantes",
|
||||||
createdAt: "2024-10-21 08:01:31.474 +0000 UTC",
|
createdAt: "2024-10-21 08:01:31.474 +0000 UTC",
|
||||||
@@ -42,6 +42,20 @@ const UsersPage = () => {
|
|||||||
topbarTitle="Users"
|
topbarTitle="Users"
|
||||||
requiredButtons={["title", "add", "search"]}
|
requiredButtons={["title", "add", "search"]}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<div className={styles.cardContainer}>
|
||||||
|
<MobileSearchBar />
|
||||||
|
{sampleData.map((user, index) => {
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
user={user}
|
||||||
|
key={index}
|
||||||
|
onClick={() => router.push(`/users/${index}`)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className={styles.tableContainer}>
|
<div className={styles.tableContainer}>
|
||||||
<table className={styles.table}>
|
<table className={styles.table}>
|
||||||
<thead className={styles.tableHeader}>
|
<thead className={styles.tableHeader}>
|
||||||
@@ -56,8 +70,8 @@ const UsersPage = () => {
|
|||||||
{sampleData.map((user, index) => {
|
{sampleData.map((user, index) => {
|
||||||
return (
|
return (
|
||||||
<tr
|
<tr
|
||||||
key={user.id}
|
key={index}
|
||||||
onClick={() => router.push(`/users/${user.id}`)}
|
onClick={() => router.push(`/users/${index}`)}
|
||||||
>
|
>
|
||||||
<td>{user.email}</td>
|
<td>{user.email}</td>
|
||||||
<td>{user.fullName}</td>
|
<td>{user.fullName}</td>
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Table */
|
/* Table */
|
||||||
.table {
|
.table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@@ -22,9 +21,9 @@
|
|||||||
padding: 12px 24px;
|
padding: 12px 24px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
color: #85869b;
|
color: #85869b;
|
||||||
color: color(display-p3 0.5216 0.5255 0.6);
|
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 13px;
|
|
||||||
|
font-size: var(--table-font-size);
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
flex: 1 0 0;
|
flex: 1 0 0;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
@@ -40,9 +39,8 @@
|
|||||||
.tableBody td {
|
.tableBody td {
|
||||||
padding: 12px 24px;
|
padding: 12px 24px;
|
||||||
color: #eeeffd;
|
color: #eeeffd;
|
||||||
color: color(display-p3 0.9333 0.9373 0.9882);
|
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
font-size: 13px;
|
font-size: var(--table-font-size);
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
@@ -54,9 +52,7 @@
|
|||||||
}
|
}
|
||||||
.tableBody tr:hover {
|
.tableBody tr:hover {
|
||||||
border-bottom: 1px solid rgba(129, 135, 255, 0.25);
|
border-bottom: 1px solid rgba(129, 135, 255, 0.25);
|
||||||
border-bottom: 1px solid color(display-p3 0.5098 0.5294 1 / 0.25);
|
|
||||||
background: rgba(129, 135, 255, 0.05);
|
background: rgba(129, 135, 255, 0.05);
|
||||||
background: color(display-p3 0.5098 0.5294 1 / 0.05);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tableActions {
|
.tableActions {
|
||||||
@@ -67,3 +63,24 @@
|
|||||||
gap: 12px;
|
gap: 12px;
|
||||||
align-self: stretch;
|
align-self: stretch;
|
||||||
}
|
}
|
||||||
|
.cardContainer {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.cardContainer {
|
||||||
|
display: flex;
|
||||||
|
padding: 0 16px;
|
||||||
|
padding-bottom: 50px;
|
||||||
|
height: calc(100vh - 170px);
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 12px;
|
||||||
|
align-self: stretch;
|
||||||
|
overflow: auto;
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
.tableContainer {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
29
frontend/src/app/users/user-card/Card.jsx
Normal file
29
frontend/src/app/users/user-card/Card.jsx
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import DeleteIcon from "@/app/components/icons/delete";
|
||||||
|
import React from "react";
|
||||||
|
import styles from "./styles.module.css";
|
||||||
|
|
||||||
|
const Card = (props) => {
|
||||||
|
return (
|
||||||
|
<div className={styles.cardContainer} {...props}>
|
||||||
|
<div className={styles.cardDetails}>
|
||||||
|
<div className={styles.list}>
|
||||||
|
<p>Email</p>
|
||||||
|
<p>{props?.user?.email}</p>
|
||||||
|
</div>
|
||||||
|
<div className={styles.list}>
|
||||||
|
<p>Full Name</p>
|
||||||
|
<p>{props?.user?.fullName}</p>
|
||||||
|
</div>
|
||||||
|
<div className={styles.list}>
|
||||||
|
<p>Date Created</p>
|
||||||
|
<p>{props?.user?.createdAt}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={styles.cardAction}>
|
||||||
|
<DeleteIcon />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Card;
|
||||||
44
frontend/src/app/users/user-card/styles.module.css
Normal file
44
frontend/src/app/users/user-card/styles.module.css
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
.cardContainer {
|
||||||
|
display: flex;
|
||||||
|
padding: 16px 0;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 16px;
|
||||||
|
align-self: stretch;
|
||||||
|
border-bottom: 1px solid #2c2d3d;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
.cardDetails {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 8px;
|
||||||
|
flex: 1 0 0;
|
||||||
|
}
|
||||||
|
.list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 5px;
|
||||||
|
align-self: stretch;
|
||||||
|
}
|
||||||
|
.list p {
|
||||||
|
color: #85869b;
|
||||||
|
font-family: Inter;
|
||||||
|
font-size: 14px;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list p:nth-child(2) {
|
||||||
|
color: #eeeffd;
|
||||||
|
font-family: Inter;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
.cardAction {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 17px;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user