Compare commits

...

5 Commits

Author SHA1 Message Date
a4675c843d done searchbar but not final 2026-03-31 14:49:20 +08:00
02d53f69ad few changes, mobile searchbar not done 2026-03-30 17:21:09 +08:00
Laux Dev
992d01ba9b Final 2026-03-26 17:22:32 +08:00
9f0392c9c2 fixed 2026-03-26 15:17:54 +08:00
6e54a9468b fixed padding 2026-03-25 10:48:32 +08:00
26 changed files with 228 additions and 121 deletions

View File

@@ -122,7 +122,7 @@ const ViewAgentPage = () => {
</div>
</>
) : (
<div className={createAgentStyle.inputContainer}>
<div className={createAgentStyle.agentInputContainer}>
<div className={createAgentStyle.labelContainer}>
<p>Agent Endpoint</p>
<p className={createAgentStyle.required}>*</p>

View File

@@ -50,7 +50,8 @@
font-weight: 500;
line-height: normal;
}
.inputContainer {
.inputContainer,
.agentInputContainer {
display: flex;
width: 500px;
flex-direction: column;
@@ -126,9 +127,13 @@
.lokiContainer {
width: 100%;
}
.inputContainer {
.inputContainer,
.agentInputContainer {
width: 100%;
}
.agentInputContainer {
padding-top: 8px;
}
.headerTxt > p {
font-size: 16px;
font-weight: 400;

View File

@@ -123,7 +123,7 @@ const AddAgentPage = () => {
</div>
</>
) : (
<div className={createAgentStyle.inputContainer}>
<div className={createAgentStyle.agentInputContainer}>
<div className={createAgentStyle.labelContainer}>
<p>Agent Endpoint</p>
<p className={createAgentStyle.required}>*</p>

View File

@@ -44,7 +44,8 @@
font-weight: 500;
line-height: normal;
}
.inputContainer {
.inputContainer,
.agentInputContainer {
display: flex;
width: 500px;
flex-direction: column;
@@ -59,7 +60,6 @@
}
.labelContainer > p {
color: #d2d3e1;
color: color(display-p3 0.8235 0.8275 0.8784);
font-family: Inter;
font-size: 16px;
font-style: normal;
@@ -120,9 +120,13 @@
.lokiContainer {
width: 100%;
}
.inputContainer {
.inputContainer,
.agentInputContainer {
width: 100%;
}
.agentInputContainer {
padding-top: 8px;
}
.headerTxt > p {
font-size: 16px;
font-weight: 400;

View File

@@ -4,7 +4,7 @@ import styles from "./styles.module.css";
const Card = (props) => {
return (
<div className={styles.cardContainer}>
<div className={styles.cardContainer} {...props}>
<div className={styles.cardDetails}>
<div className={styles.list}>
<p>Name</p>

View File

@@ -117,7 +117,13 @@ const AgentsPage = () => {
<MobileSearchBar />
{isMobile &&
sampleData.map((data, key) => {
return <Card data={data} key={key} />;
return (
<Card
data={data}
key={key}
onClick={() => router.push(`/agents/${key}`)}
/>
);
})}
</div>

View File

@@ -12,7 +12,7 @@ const SearchIcon = (props) => {
>
<path
d="M19.5527 19.5536L14.7064 14.7074M9.16822 16.7847C13.3741 16.7847 16.7837 13.3751 16.7837 9.1692C16.7837 4.96328 13.3741 1.55371 9.16822 1.55371C4.9623 1.55371 1.55273 4.96328 1.55273 9.1692C1.55273 13.3751 4.9623 16.7847 9.16822 16.7847Z"
stroke="#858699"
stroke="currentColor" //858699
strokeWidth={1.5}
strokeLinecap="round"
strokeLinejoin="round"

View File

@@ -1,12 +1,19 @@
import React from "react";
import React, { useState } from "react";
import styles from "./styles.module.css";
import SearchIcon from "../icons/search";
const MobileSearchBar = (props) => {
const [open, setOpen] = useState(false);
return (
<div className={styles.searchBarContainer}>
<input type="text" className={styles.searchBar} />
<SearchIcon className={styles.searchIcon} />
<form className={`${styles.searchBarContainer} ${open ? styles.open : ""}`}>
<input type="text" placeholder="Search" className={styles.searchBar} />
<div
className={styles.searchBtn}
onClick={() => setOpen((open) => !open)}
>
<SearchIcon />
</div>
</form>
);
};

View File

@@ -1,29 +1,68 @@
.searchBarContainer {
display: flex;
align-items: center;
gap: 10px;
align-self: stretch;
position: relative;
width: 100%;
border: 1px solid #31324a00;
transition: width 0.35s ease;
}
.searchBarContainer > input {
.searchBar:focus-within {
background: #292a36;
border-radius: 6px;
}
.open {
display: flex;
align-items: center;
gap: 8px;
border-radius: 6px;
border: 1px solid #31324a;
}
.searchBar {
width: 100%;
padding: 11px 12px;
padding-left: 40px;
background-color: transparent;
border: none;
opacity: 0;
transition: opacity 0.35s ease;
outline: none;
background-color: transparent;
color: white;
color: #85869b;
text-align: start;
font-family: Inter;
font-size: 1.18rem;
outline: none;
font-size: 18px;
font-style: normal;
font-weight: 400;
line-height: normal;
letter-spacing: -0.09px;
caret-color: #575bc7;
}
.searchIcon {
position: absolute;
left: 10;
.searchBar::placeholder {
color: #85869b;
text-align: start;
font-family: Inter;
font-size: 18px;
font-style: normal;
font-weight: 400;
line-height: normal;
letter-spacing: -0.09px;
}
.open > .searchBar {
opacity: 1;
transition-delay: 0.1s;
}
.searchBtn {
position: absolute;
top: 50%;
left: 10px;
transform: translateY(-40%);
cursor: pointer;
color: #858699;
}
.searchBtn:hover {
color: #959aff;
}

View File

@@ -16,6 +16,7 @@ import CredentialsIcon from "../icons/credentials";
import AgentIcon from "../icons/agent";
import DownloadIcon from "../icons/download";
import useNavigations from "@/app/hooks/useNagivation";
import { usePathname } from "next/navigation";
const Navbar = () => {
const [triggerDropDown, setTriggerDropDown] = useState(false);
@@ -27,11 +28,15 @@ const Navbar = () => {
navToHome,
navToOrganization,
navToUsers,
} = useNavigations();
} = useNavigations(setTriggerDropDown);
const pathname = usePathname();
const isMobile = useIsMobile();
return (
<div className={styles.mainContainer}>
<div
className={`${styles.mainContainer} ${pathname.includes("/add") ? styles.onAdd : ""}`}
>
{/* Mobile Hamburger Button */}
<div className={styles.mobileHamburger}>
<div className={styles.hamburgerMenu}>

View File

@@ -2,6 +2,7 @@ import React, { useState } from "react";
import CreateIcon from "../../icons/create";
import styles from "./styles.module.css";
import useIsMobile from "@/app/hooks/useIsMobile";
import SearchIcon from "../../icons/search";
const HeaderDropdown = ({
setOpen,
@@ -30,7 +31,7 @@ const HeaderDropdown = ({
</div>
{/* Search */}
<div className={styles.srchInputContainer}>
<div className={styles.srchInputGroup}>
<form className={styles.srchInputGroup}>
<svg
xmlns="http://www.w3.org/2000/svg"
width="18"
@@ -67,7 +68,7 @@ const HeaderDropdown = ({
id=""
placeholder="Search"
/>
</div>
</form>
</div>
</div>

View File

@@ -255,7 +255,7 @@
background: linear-gradient(0deg, #2d3143 0%, #191a24 100%);
border-radius: 0;
position: fixed;
top: 90px;
top: 80px;
left: 0;
width: 100%;
margin-top: 0;

View File

@@ -169,7 +169,7 @@
gap: 16px;
background: linear-gradient(0deg, #2d3143 0%, #191a24 100%);
position: fixed;
top: 90px;
top: 80px;
left: 0;
width: 100%;
margin-top: 0;

View File

@@ -168,4 +168,7 @@
.hamburgerMenu {
display: flex;
}
.onAdd {
display: none;
}
}

View File

@@ -1,5 +1,6 @@
import React, { useState } from "react";
import searchBarStyle from "./styles.module.css";
import SearchIcon from "../icons/search";
const SearchBar = () => {
const [open, setOpen] = useState(false);
@@ -19,21 +20,7 @@ const SearchBar = () => {
className={searchBarStyle.searchBtn}
onClick={() => setOpen((open) => !open)}
>
<svg
xmlns="http://www.w3.org/2000/svg"
width={24}
height={24}
viewBox="0 0 24 24"
fill="none"
>
<path
d="M19.5527 19.5536L14.7064 14.7074M9.16822 16.7847C13.3741 16.7847 16.7837 13.3751 16.7837 9.1692C16.7837 4.96328 13.3741 1.55371 9.16822 1.55371C4.9623 1.55371 1.55273 4.96328 1.55273 9.1692C1.55273 13.3751 4.9623 16.7847 9.16822 16.7847Z"
stroke="currentColor"
strokeWidth={1.5}
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
<SearchIcon />
</div>
</form>
);

View File

@@ -10,17 +10,14 @@
transition: width 0.35s ease;
position: absolute;
}
.searchBarContainer:focus-within {
background: #292a36;
background: color(display-p3 0.1608 0.1647 0.2078);
}
.open {
width: 260px;
padding: 6px 6px 6px 12px;
justify-content: space-between;
border: 1px solid #31324a;
border: 1px solid color(display-p3 0.1922 0.1961 0.2824);
border-radius: 6px;
}
.input {
@@ -31,7 +28,6 @@
opacity: 0; /*hide input kung collapse*/
transition: opacity 0.35s ease;
color: #85869b;
color: color(display-p3 0.5216 0.5255 0.6);
font-family: Inter;
font-size: 1.18rem;
font-style: normal;
@@ -48,7 +44,6 @@
.input::placeholder {
color: #85869b;
color: color(display-p3 0.5216 0.5255 0.6);
text-align: start;
font-family: Inter;
font-size: 1.18rem;

View File

@@ -9,7 +9,7 @@
position: absolute;
bottom: 25px;
z-index: 11;
right: 20px;
right: 10px;
animation-name: showToast;
animation-duration: 0.15s;
animation-timing-function: ease-in-out;
@@ -41,7 +41,7 @@
.messageContainer p {
color: #006929;
font-family: Inter;
font-size: 16px;
font-size: 1rem;
font-style: normal;
font-weight: 500;
line-height: normal;

View File

@@ -47,8 +47,12 @@ const TopHeader = (props) => {
editState={editState}
/>
)}
<div className={styles.container}>
<div className={styles.title}>
<div
className={`${styles.container} ${pathName.includes("/add") ? styles.column : ""}`}
>
<div
className={`${styles.title} ${pathName.includes("/add") ? styles.fullWidth : ""}`}
>
{props.requiredButtons.includes("back") && (
<div onClick={() => router.back()}>
<BackIcon />
@@ -56,7 +60,9 @@ const TopHeader = (props) => {
)}
<p>{props.topbarTitle}</p>
</div>
<div className={styles.actionBar}>
<div
className={`${styles.actionBar} ${pathName.includes("/add") ? styles.fullWidth : ""}`}
>
{props?.requiredButtons.includes("search") && (
<div className={styles.searchBarContainer}>
{!isMobile && <SearchBar />}

View File

@@ -3,6 +3,7 @@
padding: 24px;
justify-content: space-between;
align-items: center;
align-self: stretch;
background: #21232f;
transition: all 0.15s;
@@ -46,6 +47,7 @@
display: flex;
justify-content: flex-end;
align-items: center;
gap: 5px;
}
.searchBarContainer {
@@ -171,7 +173,19 @@
}
@media (max-width: 768px) {
.container {
background: #21232f00;
background: linear-gradient(180deg, #1c1d2b 0%, #191a24 100%);
padding: 16px;
}
.column {
flex-direction: column;
gap: 10px;
}
.fullWidth {
width: 100%;
justify-content: flex-start;
}
.fullWidth > button {
width: 100%;
}
}

View File

@@ -12,7 +12,7 @@ const Card = (props) => {
</div>
<div className={styles.list}>
<p>Organization ID</p>
<p>{props?.data?.organizationId}</p>
<p>{props?.data?.organizationID}</p>
</div>
</div>
<div className={styles.cardAction}>

View File

@@ -1,36 +1,22 @@
import { useRouter } from "next/navigation";
const useNavigations = () => {
export default function useNavigations(setTriggerDropDown) {
const router = useRouter();
const navToHome = () => {
router.push("/home");
};
const navToOrganization = () => {
router.push("/organization");
};
const navToProject = () => {
router.push("/projects");
};
const navToUsers = () => {
router.push("/users");
};
const navToRoles = () => {
router.push("/roles");
};
const navToCredentials = () => {
router.push("/credentials");
};
const navToAgents = () => {
router.push("/agents");
const handleNav = (path) => {
if (setTriggerDropDown) {
setTriggerDropDown(false);
}
router.push(path);
};
return {
navToHome,
navToAgents,
navToCredentials,
navToOrganization,
navToProject,
navToRoles,
navToUsers,
navToHome: () => handleNav("/home"),
navToAgents: () => handleNav("/agents"),
navToCredentials: () => handleNav("/credentials"),
navToProject: () => handleNav("/projects"),
navToRoles: () => handleNav("/roles"),
navToOrganization: () => handleNav("/organization"),
navToUsers: () => handleNav("/users"),
};
};
export default useNavigations;
}

View File

@@ -1,6 +1,7 @@
"use client";
import React, { useState } from "react";
import variableStyles from "./variableStyles.module.css";
import DeleteIcon from "@/app/components/icons/delete";
const Settings = ({
setTriggerAddVariable,
setTriggerAddVolume,
@@ -8,7 +9,29 @@ const Settings = ({
...props
}) => {
const [triggerVariableDropDown, setTriggerVariableDropDown] = useState(false);
const sampleData = [
{ id: 1, key: "REQUEST_SERVICE_GRPC", value: "request-service:50053" },
{
id: 2,
key: "DatabaseSettings:ConnectionString",
value:
"mongodb://databaseAdmin:d2OIxck4DHZgOJNuk1A@129.212.210.84:27017/?authSource=admin",
},
{ id: 1, key: "REQUEST_SERVICE_GRPC", value: "request-service:50053" },
{
id: 2,
key: "DatabaseSettings:ConnectionString",
value:
"mongodb://databaseAdmin:d2OIxck4DHZgOJNuk1A@129.212.210.84:27017/?authSource=admin",
},
{ id: 1, key: "REQUEST_SERVICE_GRPC", value: "request-service:50053" },
{
id: 2,
key: "DatabaseSettings:ConnectionString",
value:
"mongodb://databaseAdmin:d2OIxck4DHZgOJNuk1A@129.212.210.84:27017/?authSource=admin",
},
];
return (
<div {...props}>
<div className={variableStyles.variablesHeader}>
@@ -111,16 +134,19 @@ const Settings = ({
</div>
</div>
<div className={variableStyles.variableList}>
<div className={variableStyles.emptyVariableList}>
{/* <div className={variableStyles.emptyVariableList}>
<div>
<p>No Environment Variables added</p>
</div>
</div>
{/* <div className={variableStyles.variable}>
<p>REQUEST_SERVICE_GRPC</p>
<p>request-service:50053</p>
<DeleteIcon />
</div> */}
{sampleData.map((data, key) => {
return (
<div className={variableStyles.variable}>
<p>{data.key}</p>
<p>{data.value}</p>
</div>
);
})}
</div>
</div>
</div>

View File

@@ -324,4 +324,10 @@
.resourceFields .inputGroup div {
width: 100%;
}
.projectDetailsHeader {
display: none;
}
.fieldsContainerCreateNew {
padding-top: 0;
}
}

View File

@@ -151,26 +151,7 @@
border-radius: 4px;
background: #1d1e2a;
}
.variable {
display: flex;
padding: 8px 0;
align-items: center;
align-self: stretch;
border-bottom: 0.5px solid #2e3042;
width: 100%;
}
.variable p {
display: flex;
align-items: center;
flex: 1 0 0;
align-self: stretch;
color: #d2d3e1;
font-size: 0.9rem;
font-style: normal;
font-weight: 400;
line-height: normal;
letter-spacing: 0.15px;
}
.environmentVariablesContainer {
display: flex;
min-height: 200px;
@@ -202,16 +183,18 @@
}
.envVariablesHeader {
display: flex;
flex-direction: column;
padding: 12px 24px;
align-items: flex-start;
width: 100%;
align-self: stretch;
flex-direction: column;
border-bottom: 1px solid #2c2e3f;
}
.envVariablesHeader > div {
display: flex;
padding: 12px 16px;
align-items: flex-start;
align-self: stretch;
border-bottom: 1px solid #2c2e3f;
}
.envVariablesHeader > div p {
display: flex;
@@ -226,16 +209,43 @@
}
.variableList {
display: flex;
padding: 0 16px 16px 16px;
padding: 24px 24px 0 24px;
padding-bottom: 24px;
flex-direction: column;
align-items: center;
align-items: flex-start;
gap: 10px;
width: 100%;
flex: 1 0 0;
}
.variable {
display: flex;
align-items: flex-start;
align-self: stretch;
justify-content: space-between;
gap: 5px;
width: 100%;
}
.variable p {
display: flex;
align-items: start;
flex: 1 0 0;
align-self: stretch;
overflow-wrap: anywhere;
color: #d2d3e1;
font-size: 0.9rem;
font-weight: 400;
letter-spacing: 0.15px;
}
.emptyVariableList {
display: flex;
padding: 24px 16px 0 16px;
flex-direction: column;
align-items: flex-start;
width: 100%;
gap: 10px;
flex: 1 0 0;
}
@@ -243,6 +253,7 @@
display: flex;
justify-content: center;
align-items: center;
align-self: stretch;
}
.emptyVariableList > div > div {

View File

@@ -332,4 +332,10 @@
.resourceFields .inputGroup div {
width: 100%;
}
.projectDetailsHeader {
display: none;
}
.fieldsContainerCreateNew {
padding-top: 0;
}
}

View File

@@ -71,7 +71,7 @@ const AddRolePage = () => {
</div>
<div className={addRoleStyle.inputField}>
<TextField
placeHolder="Enter role name"
placeHolder="Enter name"
{...register("roleName", { required: true })}
hasError={!!errors.roleName}
/>