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>
</> </>
) : ( ) : (
<div className={createAgentStyle.inputContainer}> <div className={createAgentStyle.agentInputContainer}>
<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>

View File

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

View File

@@ -123,7 +123,7 @@ const AddAgentPage = () => {
</div> </div>
</> </>
) : ( ) : (
<div className={createAgentStyle.inputContainer}> <div className={createAgentStyle.agentInputContainer}>
<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>

View File

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

View File

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

View File

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

View File

@@ -12,7 +12,7 @@ const SearchIcon = (props) => {
> >
<path <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" 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} strokeWidth={1.5}
strokeLinecap="round" strokeLinecap="round"
strokeLinejoin="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 styles from "./styles.module.css";
import SearchIcon from "../icons/search"; import SearchIcon from "../icons/search";
const MobileSearchBar = (props) => { const MobileSearchBar = (props) => {
const [open, setOpen] = useState(false);
return ( return (
<div className={styles.searchBarContainer}> <form className={`${styles.searchBarContainer} ${open ? styles.open : ""}`}>
<input type="text" className={styles.searchBar} /> <input type="text" placeholder="Search" className={styles.searchBar} />
<SearchIcon className={styles.searchIcon} /> <div
</div> className={styles.searchBtn}
onClick={() => setOpen((open) => !open)}
>
<SearchIcon />
</div>
</form>
); );
}; };

View File

@@ -1,29 +1,68 @@
.searchBarContainer { .searchBarContainer {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 10px; gap: 10px;
align-self: stretch; align-self: stretch;
position: relative; 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%; width: 100%;
padding: 11px 12px; padding: 11px 12px;
padding-left: 40px; padding-left: 40px;
background-color: transparent; background-color: transparent;
border: none; border: none;
opacity: 0;
transition: opacity 0.35s ease;
outline: none; outline: none;
background-color: transparent; color: #85869b;
color: white; text-align: start;
font-family: Inter; font-family: Inter;
font-size: 1.18rem; font-size: 18px;
outline: none;
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
line-height: normal; line-height: normal;
letter-spacing: -0.09px;
caret-color: #575bc7; caret-color: #575bc7;
} }
.searchIcon { .searchBar::placeholder {
position: absolute; color: #85869b;
left: 10; 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 AgentIcon from "../icons/agent";
import DownloadIcon from "../icons/download"; import DownloadIcon from "../icons/download";
import useNavigations from "@/app/hooks/useNagivation"; import useNavigations from "@/app/hooks/useNagivation";
import { usePathname } from "next/navigation";
const Navbar = () => { const Navbar = () => {
const [triggerDropDown, setTriggerDropDown] = useState(false); const [triggerDropDown, setTriggerDropDown] = useState(false);
@@ -27,11 +28,15 @@ const Navbar = () => {
navToHome, navToHome,
navToOrganization, navToOrganization,
navToUsers, navToUsers,
} = useNavigations(); } = useNavigations(setTriggerDropDown);
const pathname = usePathname();
const isMobile = useIsMobile(); const isMobile = useIsMobile();
return ( return (
<div className={styles.mainContainer}> <div
className={`${styles.mainContainer} ${pathname.includes("/add") ? styles.onAdd : ""}`}
>
{/* Mobile Hamburger Button */} {/* Mobile Hamburger Button */}
<div className={styles.mobileHamburger}> <div className={styles.mobileHamburger}>
<div className={styles.hamburgerMenu}> <div className={styles.hamburgerMenu}>

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,6 @@
import React, { useState } from "react"; import React, { useState } from "react";
import searchBarStyle from "./styles.module.css"; import searchBarStyle from "./styles.module.css";
import SearchIcon from "../icons/search";
const SearchBar = () => { const SearchBar = () => {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
@@ -19,21 +20,7 @@ const SearchBar = () => {
className={searchBarStyle.searchBtn} className={searchBarStyle.searchBtn}
onClick={() => setOpen((open) => !open)} onClick={() => setOpen((open) => !open)}
> >
<svg <SearchIcon />
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>
</div> </div>
</form> </form>
); );

View File

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

View File

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

View File

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

View File

@@ -3,6 +3,7 @@
padding: 24px; padding: 24px;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
align-self: stretch; align-self: stretch;
background: #21232f; background: #21232f;
transition: all 0.15s; transition: all 0.15s;
@@ -46,6 +47,7 @@
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
align-items: center; align-items: center;
gap: 5px; gap: 5px;
} }
.searchBarContainer { .searchBarContainer {
@@ -171,7 +173,19 @@
} }
@media (max-width: 768px) { @media (max-width: 768px) {
.container { .container {
background: #21232f00; background: linear-gradient(180deg, #1c1d2b 0%, #191a24 100%);
padding: 16px; 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>
<div className={styles.list}> <div className={styles.list}>
<p>Organization ID</p> <p>Organization ID</p>
<p>{props?.data?.organizationId}</p> <p>{props?.data?.organizationID}</p>
</div> </div>
</div> </div>
<div className={styles.cardAction}> <div className={styles.cardAction}>

View File

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

View File

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

View File

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

View File

@@ -151,26 +151,7 @@
border-radius: 4px; border-radius: 4px;
background: #1d1e2a; 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 { .environmentVariablesContainer {
display: flex; display: flex;
min-height: 200px; min-height: 200px;
@@ -202,16 +183,18 @@
} }
.envVariablesHeader { .envVariablesHeader {
display: flex; display: flex;
flex-direction: column; padding: 12px 24px;
align-items: flex-start; align-items: flex-start;
width: 100%;
align-self: stretch; align-self: stretch;
flex-direction: column;
border-bottom: 1px solid #2c2e3f;
} }
.envVariablesHeader > div { .envVariablesHeader > div {
display: flex; display: flex;
padding: 12px 16px;
align-items: flex-start; align-items: flex-start;
align-self: stretch; align-self: stretch;
border-bottom: 1px solid #2c2e3f;
} }
.envVariablesHeader > div p { .envVariablesHeader > div p {
display: flex; display: flex;
@@ -226,16 +209,43 @@
} }
.variableList { .variableList {
display: flex; display: flex;
padding: 0 16px 16px 16px;
padding: 24px 24px 0 24px;
padding-bottom: 24px;
flex-direction: column; 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; 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 { .emptyVariableList {
display: flex; display: flex;
padding: 24px 16px 0 16px; padding: 24px 16px 0 16px;
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
width: 100%;
gap: 10px; gap: 10px;
flex: 1 0 0; flex: 1 0 0;
} }
@@ -243,6 +253,7 @@
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
align-self: stretch; align-self: stretch;
} }
.emptyVariableList > div > div { .emptyVariableList > div > div {

View File

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

View File

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