Skip to content

Commit

Permalink
feat: rename dropdown component to match headlessui docs and updates [g…
Browse files Browse the repository at this point in the history
  • Loading branch information
jakubfolta committed Jul 1, 2024
1 parent a56996d commit f56e2a6
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 53 deletions.
83 changes: 49 additions & 34 deletions frontend/src/app/(app)/people/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@
import { SearchIcon } from '@app/static/icons/SearchIcon';
import { Breadcrumbs } from '@app/components/modules/Breadcrumbs';
import { Tabs } from '@app/components/modules/Tabs';
import { Dropdown } from '@app/components/common/Dropdown/Dropdown';
import { ListboxComponent } from '@app/components/common/ListboxComponent';
import { InputField } from '@app/components/common/InputField/InputField';
import { MouseEvent, useEffect, useMemo, useState } from 'react';
import { Employee } from '@app/types/common';
import { EmployeeCard } from '@app/components/common/EmployeeCard';
import { EmployeeCard } from '@app/components/modules/EmployeeCard';
import { filters, tabs } from '@app/const';
import { generateClassNames } from '@app/utils';

const PEOPLE = [
{
id: 426243,
name: 'John Doe',
title: 'Front End Developer, Junior',
laddersDetails: [
Expand All @@ -24,11 +25,14 @@ const PEOPLE = [
latestActivity: 5,
},
],
active: true,
draft: false,
deactivated: false,
status: {
active: true,
draft: false,
deactivated: false,
}
},
{
id: 5329732,
name: 'Jane Doe',
title: 'Back End Developer, Senior',
laddersDetails: [
Expand All @@ -40,11 +44,14 @@ const PEOPLE = [
latestActivity: 0,
},
],
active: false,
draft: false,
deactivated: true,
status: {
active: false,
draft: false,
deactivated: true,
}
},
{
id: 54328701,
name: 'Jane Does',
title: 'QA, Senior',
laddersDetails: [
Expand All @@ -63,11 +70,14 @@ const PEOPLE = [
latestActivity: 4,
},
],
active: false,
draft: true,
deactivated: false,
status: {
active: false,
draft: true,
deactivated: false,
}
},
{
id: 4321,
name: 'Tim Brooks',
title: 'DevOps, Senior',
laddersDetails: [
Expand All @@ -79,11 +89,14 @@ const PEOPLE = [
latestActivity: 3,
},
],
active: true,
draft: false,
deactivated: false,
status: {
active: true,
draft: false,
deactivated: false,
}
},
{
id: 489901,
name: 'Marvin Joe',
title: 'Engineering Manager, Senior',
laddersDetails: [
Expand All @@ -95,9 +108,11 @@ const PEOPLE = [
latestActivity: 3,
},
],
active: false,
draft: false,
deactivated: true,
status: {
active: false,
draft: false,
deactivated: true,
}
},
];

Expand All @@ -124,22 +139,22 @@ export default function People() {

const selectedFilterLabel = filters.find((option) => option.value === selectedFilter)?.label || '';

const activePeopleAmount = useMemo(() => people.filter((employee) => employee.active).length, [people]);
const draftPeopleAmount = useMemo(() => people.filter((employee) => employee.draft).length, [people]);
const deactivatedPeopleAmount = useMemo(() => people.filter((employee) => employee.deactivated).length, [people]);
const activePeopleAmount = useMemo(() => people.filter((employee) => employee.status.active).length, [people]);
const draftPeopleAmount = useMemo(() => people.filter((employee) => employee.status.draft).length, [people]);
const deactivatedPeopleAmount = useMemo(() => people.filter((employee) => employee.status.deactivated).length, [people]);

const peopleTabs = useMemo(() => {
return [
{
title: tabs[0],
title: tabs[0].title,
employees: activePeopleAmount,
},
{
title: tabs[1],
title: tabs[1].title,
employees: draftPeopleAmount,
},
{
title: tabs[2],
title: tabs[2].title,
employees: deactivatedPeopleAmount,
},
];
Expand All @@ -148,11 +163,11 @@ export default function People() {
useEffect(() => {
if (people) {
if (activeTab === peopleTabs[0].title) {
setSelectedTabPeople(people.filter((employee) => employee.active));
setSelectedTabPeople(people.filter((employee) => employee.status.active));
} else if (activeTab === peopleTabs[1].title) {
setSelectedTabPeople(people.filter((employee) => employee.draft));
setSelectedTabPeople(people.filter((employee) => employee.status.draft));
} else {
setSelectedTabPeople(people.filter((employee) => employee.deactivated));
setSelectedTabPeople(people.filter((employee) => employee.status.deactivated));
}
}
}, [people, activeTab, peopleTabs]);
Expand All @@ -179,7 +194,7 @@ export default function People() {
<div className="flex flex-col gap-6">
<div className="flex items-center justify-between">
<Breadcrumbs breadcrumbs={[{ label: 'People', href: '/people', current: true }]} />
<button className="py-2 px-5 text-white text-sm font-semibold bg-blue-800 rounded-full">+ Employee</button>
<button className="rounded-full bg-blue-800 px-5 py-2 text-sm font-semibold text-white">+ Employee</button>
</div>

<Tabs
Expand All @@ -189,17 +204,17 @@ export default function People() {
className="border-b border-navy-200"
/>

<div className="flex flex-col gap-2 bg-white rounded-2xl p-6 pb-2">
<div className="flex flex-col gap-2 rounded-2xl bg-white p-6 pb-2">
<div className="w-1/3">
<div className="w-full flex gap-4 items-center justify-between">
<div className="flex w-full items-center justify-between gap-4">
<InputField
value={search}
name="people-search"
placeholder="Search"
icon={<SearchIcon />}
onChange={(e) => setSearch(e.target.value)}
/>
<Dropdown
<ListboxComponent
selectedOptionLabel={selectedFilterLabel}
options={filters}
selectedOptionValue={selectedFilter}
Expand All @@ -211,14 +226,14 @@ export default function People() {

<div
className={generateClassNames(
'grid grid-cols-[auto_repeat(3,_160px)_248px_160px_48px] grid-rows-[56px] auto-rows-[minmax(64px,_auto)]',
'grid auto-rows-[minmax(64px,_auto)] grid-cols-[auto_repeat(3,_160px)_248px_160px_48px] grid-rows-[56px]',
{
'grid-cols-[auto_repeat(2,_200px)_400px_48px]': activeTab === peopleTabs[1].title,
'grid-cols-[400px_repeat(3,_minmax(25%,_auto))]': activeTab === peopleTabs[2].title,
'grid-cols-[400px_repeat(3,_1fr)]': activeTab === peopleTabs[2].title,
},
)}
>
<div className="*:self-center contents uppercase font-medium text-xs text-navy-500 *:px-4">
<div className="contents text-xs font-medium uppercase text-navy-500 *:self-center *:px-4">
<div>Employee</div>
<div>Ladder</div>
<div className="text-right">Current band</div>
Expand All @@ -241,4 +256,4 @@ export default function People() {
</div>
</div>
);
}
};
1 change: 0 additions & 1 deletion frontend/src/components/common/Dropdown/index.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export interface Option {
id: number;
}

export interface DropdownProps {
export interface ListboxComponentProps {
options: Option[];
selectedOptionValue: string;
selectedOptionLabel: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,51 +1,51 @@
'use client';

import { DropdownProps } from './Dropdown.interface';
import { Transition } from '@headlessui/react';
import { ListboxComponentProps } from './ListboxComponent.interface';
import { ListboxButton, ListboxOption, ListboxOptions, Transition } from '@headlessui/react';
import { Listbox } from '@headlessui/react';
import { ChevronRightIcon } from '@app/static/icons/ChevronRightIcon';
import { CloseIcon } from '@app/static/icons/CloseIcon';
import { generateClassNames } from '@app/utils';

export const Dropdown = ({
export const ListboxComponent = ({
options,
selectedOptionValue,
selectedOptionLabel,
setSelectedOption,
resetFilter,
}: DropdownProps) => (
}: ListboxComponentProps) => (
<div>
<Listbox value={selectedOptionValue} onChange={setSelectedOption}>
<div className="relative">
<Listbox.Button
<ListboxButton
className={generateClassNames(
'relative flex justify-between items-center gap-3 h-12 border border-navy-200 cursor-default rounded-xl bg-white px-4 text-left focus:outline-none focus-visible:border-indigo-500 focus-visible:ring-2 focus-visible:ring-white/75 focus-visible:ring-offset-2 focus-visible:ring-offset-orange-300',
'focus-visible:border-indigo-500 focus-visible:ring-offset-orange-300 relative flex h-12 cursor-default items-center justify-between gap-3 rounded-xl border border-navy-200 bg-white px-4 text-left focus:outline-none focus-visible:ring-2 focus-visible:ring-white/75 focus-visible:ring-offset-2',
{
'px-0 gap-0 bg-blue-200': selectedOptionValue !== options[0].value,
'gap-0 bg-blue-200 px-0': selectedOptionValue !== options[0].value,
},
)}
>
{selectedOptionValue !== options[0].value ? (
<>
<div className="flex items-center gap-2 h-12 pr-2 pl-3">
<div className="flex h-12 items-center gap-2 pl-3 pr-2">
<span className="pointer-events-none">
<ChevronRightIcon className="h-4 w-4 text-navy-600 rotate-90" aria-hidden="true" />
<ChevronRightIcon className="h-4 w-4 rotate-90 text-navy-600" aria-hidden="true" />
</span>
<span className="block truncate text-navy-900">{selectedOptionLabel}</span>
</div>
<span className="flex items-center h-12 pr-3 pl-2 cursor-pointer" onClick={resetFilter}>
<span className="flex h-12 cursor-pointer items-center pl-2 pr-3" onClick={resetFilter}>
<CloseIcon className="h-3 w-[18px] text-navy-600" aria-hidden="true" />
</span>
</>
) : (
<>
<span className="block truncate text-navy-600">{selectedOptionLabel}</span>
<span className="pointer-events-none flex items-center">
<ChevronRightIcon className="h-4 w-4 text-navy-600 rotate-90" aria-hidden="true" />
<ChevronRightIcon className="h-4 w-4 rotate-90 text-navy-600" aria-hidden="true" />
</span>
</>
)}
</Listbox.Button>
</ListboxButton>
<Transition
enter="transition duration-100 ease-out"
enterFrom="transform scale-95 opacity-0"
Expand All @@ -54,21 +54,21 @@ export const Dropdown = ({
leaveFrom="transform scale-100 opacity-100"
leaveTo="transform scale-95 opacity-0"
>
<Listbox.Options className="absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black/5 focus:outline-none sm:text-sm">
<ListboxOptions className="ring-black/5 absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 focus:outline-none sm:text-sm">
{options.map((option) => (
<Listbox.Option
<ListboxOption
key={option.id}
value={option.value}
className={({ active }) =>
`relative cursor-default select-none py-2 border-navy-200 pl-10 pr-4 ${
`relative cursor-default select-none border-navy-200 py-2 pl-10 pr-4 ${
active ? 'bg-navy-200 text-navy-600' : 'text-gray-900'
}`
}
>
{option.label}
</Listbox.Option>
</ListboxOption>
))}
</Listbox.Options>
</ListboxOptions>
</Transition>
</div>
</Listbox>
Expand Down
1 change: 1 addition & 0 deletions frontend/src/components/common/ListboxComponent/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { ListboxComponent } from './ListboxComponent';

0 comments on commit f56e2a6

Please sign in to comment.