Skip to content

Commit

Permalink
116 search for consultant (#117)
Browse files Browse the repository at this point in the history
* Create searchbar and sidebar

* use React-Feather for icons

* Add min height to side bar

* Implement filtering of variants based on input to search bar

* Add focus to searchbar on keystrokes

* remove gitignore for prettierrc

* Try to fix lowercase filenames in components

* Rename FilteredVariantsList

* add func eslint rule

* Fix linting error

* Change to more general naming

---------

Co-authored-by: Sigrid Elnan <[email protected]>
Co-authored-by: Jonas Bjøralt <[email protected]>
  • Loading branch information
3 people authored Oct 11, 2023
1 parent 5529a94 commit be42426
Show file tree
Hide file tree
Showing 16 changed files with 190 additions and 84 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -455,4 +455,3 @@ $RECYCLE.BIN/
!.vscode/extensions.json

*.[Ll]ocal.json
frontend/.prettierrc
5 changes: 4 additions & 1 deletion frontend/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
{
"extends": ["next"]
"extends": ["next"],
"rules": {
"func-style": ["error", "declaration"]
}
}
1 change: 1 addition & 0 deletions frontend/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"postcss": "^8.4.31",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-feather": "^2.0.10",
"react-query": "^3.39.3",
"tailwindcss": "^3.3.3",
"typescript": "5.2.2"
Expand Down
3 changes: 0 additions & 3 deletions frontend/public/icons/chevron-down.svg

This file was deleted.

18 changes: 18 additions & 0 deletions frontend/src/app/bemanning/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import SearchBarComponent from "@/components/SearchBarComponent";

export default function BemanningLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div className="flex flex-row">
<div className="bg-primary_l4 py-6 px-4 flex flex-col gap-6 min-h-screen">
<h3 className="">Filter</h3>
<SearchBarComponent />
</div>

<div className="p-6 w-full">{children}</div>
</div>
);
}
22 changes: 22 additions & 0 deletions frontend/src/app/bemanning/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"use client";

import FilteredConsultantsList from "@/components/FilteredConsultantsList";
import useVibesApi from "@/hooks/useVibesApi";
import { CircularProgress } from "@mui/material";

export default function Bemanning() {
const { data, isLoading } = useVibesApi(true);

if (isLoading) {
return <CircularProgress />;
}

if (data) {
return (
<div>
<h1>Konsulenter</h1>
<FilteredConsultantsList consultants={data} />
</div>
);
}
}
5 changes: 5 additions & 0 deletions frontend/src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,9 @@
font-family: "Graphik-Medium";
line-height: 1.25rem;
}

.input {
flex: 1;
background-color: transparent;
}
}
4 changes: 1 addition & 3 deletions frontend/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ export default function RootLayout({
/>
</Head>
<body>
<AppProviders>
<div className="p-6">{children}</div>
</AppProviders>
<AppProviders>{children}</AppProviders>
</body>
</html>
);
Expand Down
32 changes: 1 addition & 31 deletions frontend/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1 @@
"use client";
import VariantListElement from "@/components/variantListElement";
import useVibesApi from "@/hooks/useVibesApi";
import { CircularProgress } from "@mui/material";

export default function Bemanning() {
const { data, isLoading } = useVibesApi(true);

if (isLoading) {
return <CircularProgress />;
}

if (data) {
return (
<div>
<h1>Konsulenter</h1>

<div className="flex flex-row gap-3 pt-16 pb-4 items-center">
<p className="body-large-bold ">Konsulentliste</p>

<div className="rounded-full bg-black bg-opacity-5 px-2 py-1">
<p className="text-black body-small">{data.length}</p>
</div>
</div>
{data.map((variant) => (
<VariantListElement key={variant.id} variant={variant} />
))}
</div>
);
}
}
export default function Root() {}
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
"use client";
import { Variant } from "@/types";
import { useState } from "react";
import { ChevronDown } from "react-feather";

interface VariantListElementProps {
variant: Variant;
interface ConsultantListElementProps {
consultant: Variant;
}

const VariantListElement = ({ variant }: VariantListElementProps) => {
export default function ConsultantListElement({
consultant,
}: ConsultantListElementProps) {
const [isListElementVisible, setIsListElementVisible] = useState(false);

const toggleListElementVisibility = () => {
function toggleListElementVisibility() {
setIsListElementVisible(!isListElementVisible);
};
}

return (
<div
Expand All @@ -24,16 +27,14 @@ const VariantListElement = ({ variant }: VariantListElementProps) => {
onClick={toggleListElementVisibility}
>
<div className={`w-6 h-6 m-3 ${isListElementVisible && "rotate-180"}`}>
<img src="icons/chevron-down.svg" alt="chevron-down" className="" />
<ChevronDown className={`text-primary_default`} />
</div>
<div className="flex flex-col gap-1 justify-center items-start">
<p className="body text-black"> {variant.name}</p>
<p className="detail text-neutral_l1">{variant.email}</p>
<p className="body text-black"> {consultant.name}</p>
<p className="detail text-neutral_l1">{consultant.email}</p>
</div>
</button>
<div className={`${!isListElementVisible && "hidden"} h-[198px] `}></div>
</div>
);
};

export default VariantListElement;
}
41 changes: 41 additions & 0 deletions frontend/src/components/FilteredConsultantsList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"use client";
import { useEffect, useState } from "react";
import ConsultantListElement from "./ConsultantListElement";
import { Variant } from "@/types";
import { useSearchParams } from "next/navigation";

export default function FilteredConsultantList({
consultants,
}: {
consultants: Variant[];
}) {
const searchParams = useSearchParams();
const search = searchParams.get("search");
const [filteredConsultants, setFilteredConsultants] = useState(consultants);

useEffect(() => {
if (search && search.length > 0) {
const filtered = consultants?.filter((consultant) =>
consultant.name.toLowerCase().includes(search.toLowerCase()),
);
setFilteredConsultants(filtered);
} else {
setFilteredConsultants(consultants);
}
}, [search, consultants]);

return (
<div>
<div className="flex flex-row gap-3 pt-16 pb-4 items-center">
<p className="body-large-bold ">Konsulentliste</p>

<div className="rounded-full bg-black bg-opacity-5 px-2 py-1">
<p className="text-black body-small">{filteredConsultants?.length}</p>
</div>
</div>
{filteredConsultants?.map((consultant) => (
<ConsultantListElement key={consultant.id} consultant={consultant} />
))}
</div>
);
}
61 changes: 28 additions & 33 deletions frontend/src/components/PageLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,33 @@
"use client"
import { AuthenticatedTemplate, UnauthenticatedTemplate } from "@azure/msal-react";
"use client";
import {
AuthenticatedTemplate,
UnauthenticatedTemplate,
} from "@azure/msal-react";
import { Box, Container, Grid } from "@mui/material";
import VibesAppBar from "./VibesNavBar";
import SignInSignOutButton from "./vibes-buttons/SignInSignOutButton";

export default function PageLayout({ children }: { children: React.ReactNode }) {
return (
<Grid container justifyContent="center">
<VibesAppBar />
<Box
component="main"
sx={{
flexGrow: 1,
bgcolor: 'background.default',
}}
>
<AuthenticatedTemplate>
<Container>
{children}
</Container>
</AuthenticatedTemplate>
export default function PageLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<div>
<VibesAppBar />
<AuthenticatedTemplate>{children}</AuthenticatedTemplate>

<UnauthenticatedTemplate>
<Box
display="flex"
justifyContent="center"
alignItems="center"
minHeight="50vh"
>
Please log in first
<SignInSignOutButton />
</Box>
</UnauthenticatedTemplate>
</Box>
</Grid>
);
}
<UnauthenticatedTemplate>
<Box
display="flex"
justifyContent="center"
alignItems="center"
minHeight="50vh"
>
Please log in first
<SignInSignOutButton />
</Box>
</UnauthenticatedTemplate>
</div>
);
}
47 changes: 47 additions & 0 deletions frontend/src/components/SearchBarComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"use client";
import { useRouter } from "next/navigation";
import { useEffect, useRef, useState } from "react";
import { Search } from "react-feather";

export default function SearchBarComponent() {
const router = useRouter();
const [searchText, setSearchText] = useState("");
const inputRef = useRef<HTMLInputElement>(null);

useEffect(() => {
router.push(`/bemanning?search=${searchText}`);
}, [searchText, router]);

useEffect(() => {
function keyDownHandler(e: { code: string }) {
if (
(e.code.startsWith("Key") || e.code.includes("Backspace")) &&
inputRef.current
) {
inputRef.current.focus();
}
}
document.addEventListener("keydown", keyDownHandler);

// clean up
return () => {
document.removeEventListener("keydown", keyDownHandler);
};
}, []);

return (
<div className="flex flex-col gap-2">
<p className="body-small">Søk</p>
<div className="flex flex-row gap-2 rounded-lg border border-primary_l1 px-3 py-2 w-max">
<Search className="text-primary_default" />
<input
placeholder="Søk etter konsulent"
className="input w-36 focus:outline-none body-small "
onChange={(e) => setSearchText(e.target.value)}
autoFocus
ref={inputRef}
></input>
</div>
</div>
);
}
1 change: 1 addition & 0 deletions frontend/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module.exports = {
black: "#333333",
white: "#FFFFFF",
primary_default: "#423D89",
primary_l1: "#A09EC4",
primary_l3: "#ECECF3",
primary_l4: "#F6F5F9",
secondary_default: "#F076A6",
Expand Down
9 changes: 8 additions & 1 deletion frontend/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2461,7 +2461,7 @@ [email protected]:
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.0.3.tgz#432a51f7ba422d1469096c0fdc28e235db8f9643"
integrity sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==

prop-types@^15.6.2, prop-types@^15.8.1:
prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
Expand All @@ -2488,6 +2488,13 @@ react-dom@^18.2.0:
loose-envify "^1.1.0"
scheduler "^0.23.0"

react-feather@^2.0.10:
version "2.0.10"
resolved "https://registry.yarnpkg.com/react-feather/-/react-feather-2.0.10.tgz#0e9abf05a66754f7b7bb71757ac4da7fb6be3b68"
integrity sha512-BLhukwJ+Z92Nmdcs+EMw6dy1Z/VLiJTzEQACDUEnWMClhYnFykJCGWQx+NmwP/qQHGX/5CzQ+TGi8ofg2+HzVQ==
dependencies:
prop-types "^15.7.2"

react-is@^16.13.1, react-is@^16.7.0:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
Expand Down

0 comments on commit be42426

Please sign in to comment.