RC-10: add new custom hooks

This commit is contained in:
2023-08-27 11:54:59 +01:00
parent fdb173e558
commit e6912e2541
4 changed files with 157 additions and 20 deletions

View File

@@ -1,20 +1,3 @@
import { useState, useEffect } from 'react';
export function useWindowDimensions() {
const getWindowDimensions = () => {
const { innerWidth: width, innerHeight: height } = window;
return { width, height };
};
const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions());
useEffect(() => {
const onRecize = () => setWindowDimensions(getWindowDimensions());
window.addEventListener('resize', onRecize);
return () => window.removeEventListener('resize', onRecize);
}, []);
return windowDimensions;
}
export { default as useWindowDimensions } from './useWindowDimensions';
export { default as useOnClickOutside } from './useOnClickOutside';
export { default as usePropertiesHeader } from './usePropertiesHeader';

View File

@@ -0,0 +1,29 @@
import { useEffect } from 'react';
export default function useOnClickOutside(ref, handler) {
useEffect(() => {
const onEvent = (event) => {
if (!ref.current) {
return;
}
if (event instanceof KeyboardEvent && event.key === 'Escape') {
handler(event);
} else if (ref.current.contains(event.target)) {
return;
}
handler(event);
};
document.addEventListener('mousedown', onEvent);
document.addEventListener('touchstart', onEvent);
document.addEventListener('keydown', onEvent);
return () => {
document.removeEventListener('mousedown', onEvent);
document.removeEventListener('touchstart', onEvent);
document.removeEventListener('keydown', onEvent);
};
}, [ref, handler]);
}

View File

@@ -0,0 +1,105 @@
import { PROPERTIES_LAYOUTS } from 'app/configs/consts';
import { useState, useMemo, useCallback, useEffect } from 'react';
export default function usePropertiesHeader(items) {
const [categories, setCategories] = useState([
{
name: 'all',
amount: 0,
active: true,
},
]);
const [layouts, setLayouts] = useState([
{ name: PROPERTIES_LAYOUTS.list, active: true },
{ name: PROPERTIES_LAYOUTS.grid, active: false },
]);
const activeCategory = useMemo(
() => categories.find(({ active }) => active)?.name ?? categories[0].name,
[categories]
);
const activeLayout = useMemo(
() => layouts.find(({ active }) => active)?.name ?? PROPERTIES_LAYOUTS.list,
[layouts]
);
const onCategory = useCallback(
(value) => {
if (value === activeCategory) {
return;
}
setCategories((prevState) =>
prevState.map((category) => ({ ...category, active: category.name === value }))
);
},
[activeCategory]
);
const onLayout = useCallback(
(value) => {
if (value === activeLayout) {
return;
}
setLayouts((prevState) => prevState.map(({ name }) => ({ name, active: name === value })));
},
[activeLayout]
);
const onItemDelete = (itemCategory) => {
setCategories((prevState) => {
const isItemCategoryLast =
prevState.find((category) => category.name === itemCategory)?.amount === 1;
return prevState
.map((category, idx) => {
if (!idx) {
return {
name: category.name,
amount: category.amount - 1,
active: isItemCategoryLast,
};
}
if (category?.name === itemCategory) {
if (category.amount > 1) {
return { ...category, amount: category.amount - 1 };
}
return null;
}
return category;
})
.filter((category) => category);
});
};
useEffect(() => {
let updatedCategories = [...categories];
items.forEach((item) => {
const hasItemCategory = updatedCategories.find((category) => category.name === item.category);
updatedCategories = updatedCategories.map((category, idx) => {
if (!idx) {
category.amount += 1;
}
return category;
});
if (hasItemCategory) {
updatedCategories = updatedCategories.map((category) => ({
...category,
amount: item.category === category.name ? category.amount + 1 : category.amount,
}));
} else {
updatedCategories.push({ name: item.category, amount: 1, active: false });
}
});
setCategories(updatedCategories);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return { categories, activeCategory, onCategory, layouts, activeLayout, onLayout, onItemDelete };
}

View File

@@ -0,0 +1,20 @@
import { useState, useEffect } from 'react';
export default function useWindowDimensions() {
const getWindowDimensions = () => {
const { innerWidth: width, innerHeight: height } = window;
return { width, height };
};
const [windowDimensions, setWindowDimensions] = useState(getWindowDimensions());
useEffect(() => {
const onRecize = () => setWindowDimensions(getWindowDimensions());
window.addEventListener('resize', onRecize);
return () => window.removeEventListener('resize', onRecize);
}, []);
return windowDimensions;
}