mirror of
https://github.com/Nezumi-2711/react-training.git
synced 2026-09-23 04:19:48 +00:00
Fix comments
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import { Outlet } from 'react-router-dom';
|
||||
|
||||
// Components
|
||||
import Header from '../Header';
|
||||
import Sidebar from '../Sidebar';
|
||||
import Header from '@component/Header';
|
||||
import Sidebar from '@component/Sidebar';
|
||||
|
||||
// Styled
|
||||
import { Main, StyledAppLayout } from './styled';
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
import { COLOR, SIZE } from '@constant/styles';
|
||||
import { ReactNode } from 'react';
|
||||
import styled, { css } from 'styled-components';
|
||||
|
||||
interface IStyledButtonIcon {
|
||||
isHaveChildren: boolean;
|
||||
style?: {
|
||||
fontSize?: string;
|
||||
backgroundColor?: string;
|
||||
color?: string;
|
||||
};
|
||||
iconStyle?: {
|
||||
color?: string;
|
||||
size?: string;
|
||||
};
|
||||
}
|
||||
|
||||
const StyledButtonIcon = styled.button<IStyledButtonIcon>`
|
||||
background: none;
|
||||
|
||||
padding: 10px;
|
||||
transition: all 0.2s;
|
||||
|
||||
border: none;
|
||||
|
||||
${(props) =>
|
||||
props.style?.fontSize &&
|
||||
css`
|
||||
font-size: ${props.style.fontSize};
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.style?.fontSize &&
|
||||
css`
|
||||
font-size: ${props.style.fontSize};
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.color &&
|
||||
css`
|
||||
font-size: ${props.color};
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.isHaveChildren
|
||||
? css`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
|
||||
text-align: left;
|
||||
width: 100%;
|
||||
`
|
||||
: css`
|
||||
border-radius: var(--radius-md);
|
||||
`}
|
||||
|
||||
&:hover {
|
||||
background-color: var(--hover-background-color);
|
||||
}
|
||||
|
||||
& svg {
|
||||
${(props) =>
|
||||
props.iconStyle?.size &&
|
||||
css`
|
||||
width: ${props.iconStyle.size};
|
||||
height: ${props.iconStyle.size};
|
||||
`}
|
||||
|
||||
${(props) =>
|
||||
props.iconStyle?.color &&
|
||||
css`
|
||||
color: ${props.iconStyle.color};
|
||||
`}
|
||||
transition: all 0.3s;
|
||||
}
|
||||
`;
|
||||
|
||||
StyledButtonIcon.defaultProps = {
|
||||
style: {
|
||||
fontSize: SIZE.DEFAULT,
|
||||
backgroundColor: COLOR.DEFAULT,
|
||||
color: COLOR.BLACK,
|
||||
},
|
||||
iconStyle: {
|
||||
color: COLOR.BLACK,
|
||||
size: SIZE.DEFAULT,
|
||||
},
|
||||
};
|
||||
|
||||
interface IButtonIcon {
|
||||
icon: ReactNode;
|
||||
children?: ReactNode;
|
||||
style?: {
|
||||
fontSize?: string;
|
||||
backgroundColor?: string;
|
||||
color?: string;
|
||||
};
|
||||
iconStyle?: {
|
||||
color?: string;
|
||||
size?: string;
|
||||
};
|
||||
onClick?: () => void;
|
||||
}
|
||||
|
||||
const ButtonIcon = ({
|
||||
icon,
|
||||
children,
|
||||
style,
|
||||
iconStyle,
|
||||
onClick,
|
||||
}: IButtonIcon) => {
|
||||
const isHaveChildren = Boolean(children);
|
||||
|
||||
return (
|
||||
<StyledButtonIcon
|
||||
isHaveChildren={isHaveChildren}
|
||||
style={{
|
||||
fontSize: style?.fontSize,
|
||||
backgroundColor: style?.backgroundColor,
|
||||
color: style?.color,
|
||||
}}
|
||||
iconStyle={iconStyle}
|
||||
onClick={onClick}
|
||||
>
|
||||
{icon} <span>{children}</span>
|
||||
</StyledButtonIcon>
|
||||
);
|
||||
};
|
||||
|
||||
export default ButtonIcon;
|
||||
@@ -1,7 +1,7 @@
|
||||
// Components
|
||||
import { IoPersonCircleOutline } from 'react-icons/io5';
|
||||
import { HiOutlineLogout } from 'react-icons/hi';
|
||||
import ButtonIcon from '../../commons/styles/ButtonIcon';
|
||||
import ButtonIcon from '@component/ButtonIcon/ButtonIcon';
|
||||
|
||||
// Styled
|
||||
import { StyledHeaderMenu } from './styled';
|
||||
@@ -10,14 +10,18 @@ const HeaderMenu = () => {
|
||||
return (
|
||||
<StyledHeaderMenu>
|
||||
<li>
|
||||
<ButtonIcon aria-label="Profile">
|
||||
<IoPersonCircleOutline />
|
||||
</ButtonIcon>
|
||||
<ButtonIcon
|
||||
aria-label="Profile"
|
||||
icon={<IoPersonCircleOutline />}
|
||||
iconStyle={{ size: '23px' }}
|
||||
/>
|
||||
</li>
|
||||
<li>
|
||||
<ButtonIcon aria-label="Logout">
|
||||
<HiOutlineLogout />
|
||||
</ButtonIcon>
|
||||
<ButtonIcon
|
||||
aria-label="Logout"
|
||||
icon={<HiOutlineLogout />}
|
||||
iconStyle={{size: '23px' }}
|
||||
/>
|
||||
</li>
|
||||
</StyledHeaderMenu>
|
||||
);
|
||||
|
||||
@@ -4,16 +4,18 @@ import { MouseEvent, ReactNode, useContext, useState } from 'react';
|
||||
import { HiEllipsisVertical } from 'react-icons/hi2';
|
||||
|
||||
// Hooks
|
||||
import { useOutsideClick } from '../../hooks/useOutsideClick';
|
||||
import { useOutsideClick } from '@hook/useOutsideClick';
|
||||
|
||||
// Styled
|
||||
import { StyledMenu, StyledButton, StyledList, StyledToggle } from './styled';
|
||||
import { StyledMenu, StyledList, StyledToggle } from './styled';
|
||||
|
||||
// Contexts
|
||||
import MenusContext from '../../contexts/MenuContext';
|
||||
import MenusContext from '@context/MenuContext';
|
||||
|
||||
// Types
|
||||
import { Nullable } from '../../types/common';
|
||||
import { Nullable } from '@type/common';
|
||||
import ButtonIcon from '@component/ButtonIcon/ButtonIcon';
|
||||
import { COLOR } from '@constant/styles';
|
||||
|
||||
interface IButton {
|
||||
children?: string;
|
||||
@@ -74,9 +76,14 @@ const Button = ({ children, icon, onClick }: IButton): ReactNode => {
|
||||
|
||||
return (
|
||||
<li>
|
||||
<StyledButton onClick={handleClick}>
|
||||
{icon} <span>{children}</span>
|
||||
</StyledButton>
|
||||
<ButtonIcon
|
||||
icon={icon}
|
||||
onClick={handleClick}
|
||||
iconStyle={{ color: COLOR.PRIMARY, size: '19px' }}
|
||||
style={{ fontSize: '16px' }}
|
||||
>
|
||||
{children}
|
||||
</ButtonIcon>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -8,10 +8,10 @@ import {
|
||||
import { createPortal } from 'react-dom';
|
||||
|
||||
// Hooks
|
||||
import { useOutsideClick } from '../../hooks/useOutsideClick';
|
||||
import { useOutsideClick } from '@hook/useOutsideClick';
|
||||
|
||||
// Contexts
|
||||
import { ModalContext } from '../../contexts/ModalContext';
|
||||
import { ModalContext } from '@context/ModalContext';
|
||||
|
||||
// Styled
|
||||
import { Overlay, StyledModal, StyledModalContent, TitleModal } from './styled';
|
||||
@@ -34,14 +34,14 @@ const Modal = ({ children }: IModal) => {
|
||||
};
|
||||
|
||||
interface IOpen {
|
||||
children: ReactElement;
|
||||
renderChildren: (onCloseModal: () => void) => ReactNode;
|
||||
modalName: string;
|
||||
}
|
||||
|
||||
const Open = ({ children, modalName }: IOpen) => {
|
||||
const Open = ({ renderChildren, modalName }: IOpen) => {
|
||||
const { open } = useContext(ModalContext);
|
||||
|
||||
return cloneElement(children, { onClick: () => open!(modalName) });
|
||||
return renderChildren(() => open!(modalName));
|
||||
};
|
||||
|
||||
interface IWindow {
|
||||
@@ -54,9 +54,6 @@ const Window = ({ children, name, title }: IWindow) => {
|
||||
const { openName, close } = useContext(ModalContext);
|
||||
const ref = useOutsideClick<HTMLDivElement>(close!);
|
||||
|
||||
console.log('name: ', name);
|
||||
console.log('openName: ', openName);
|
||||
|
||||
if (name !== openName) return null;
|
||||
|
||||
return createPortal(
|
||||
|
||||
@@ -7,7 +7,7 @@ import { BsHouseDoorFill } from 'react-icons/bs';
|
||||
import { StyledNav, StyledNavLink } from './styled';
|
||||
|
||||
// Constants
|
||||
import { DASHBOARD, ROOM, USER } from '../../constants/path';
|
||||
import { DASHBOARD, ROOM, USER } from '@constant/path';
|
||||
|
||||
const Nav = () => {
|
||||
return (
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { memo } from 'react';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
|
||||
// Styled
|
||||
@@ -11,7 +10,7 @@ interface IOrderProps {
|
||||
}[];
|
||||
}
|
||||
|
||||
const OrderBy = memo(({ options }: IOrderProps) => {
|
||||
const OrderBy = ({ options }: IOrderProps) => {
|
||||
const field = 'orderBy';
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const currentOrder = searchParams.get(field) || options[0].value;
|
||||
@@ -35,6 +34,6 @@ const OrderBy = memo(({ options }: IOrderProps) => {
|
||||
))}
|
||||
</StyledOrder>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
export default OrderBy;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useEffect, useState } from 'react';
|
||||
import { StyledSearch } from './styled';
|
||||
|
||||
// Hooks
|
||||
import { useDebounce } from '../../hooks/useDebounce';
|
||||
import { useDebounce } from '@hook/useDebounce';
|
||||
|
||||
interface ISearch {
|
||||
setPlaceHolder: string;
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import {
|
||||
FieldValues,
|
||||
RegisterOptions,
|
||||
UseFormRegister,
|
||||
useFormContext,
|
||||
} from 'react-hook-form';
|
||||
import { ChangeEventHandler, ReactNode } from 'react';
|
||||
import { ChangeEventHandler } from 'react';
|
||||
|
||||
// Styled
|
||||
import { StyledSelect } from './styled';
|
||||
@@ -22,46 +21,6 @@ interface ISelect {
|
||||
ariaLabel: string;
|
||||
}
|
||||
|
||||
interface IRender extends ISelect {
|
||||
register: UseFormRegister<FieldValues>;
|
||||
children: ReactNode[];
|
||||
}
|
||||
|
||||
const RenderSelect = ({
|
||||
options,
|
||||
id,
|
||||
value,
|
||||
optionsConfigForm,
|
||||
onChange,
|
||||
register,
|
||||
children,
|
||||
ariaLabel,
|
||||
}: IRender) => {
|
||||
if (options && !register) {
|
||||
return (
|
||||
<StyledSelect
|
||||
aria-label={ariaLabel}
|
||||
id={id}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
>
|
||||
{children}
|
||||
</StyledSelect>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<StyledSelect
|
||||
aria-label={ariaLabel}
|
||||
id={id}
|
||||
value={value}
|
||||
{...register(id!, optionsConfigForm)}
|
||||
>
|
||||
{children}
|
||||
</StyledSelect>
|
||||
);
|
||||
};
|
||||
|
||||
const Select = ({
|
||||
options,
|
||||
id,
|
||||
@@ -75,21 +34,20 @@ const Select = ({
|
||||
if (!options) return;
|
||||
|
||||
return (
|
||||
<RenderSelect
|
||||
register={register}
|
||||
options={options}
|
||||
optionsConfigForm={optionsConfigForm}
|
||||
<StyledSelect
|
||||
aria-label={ariaLabel}
|
||||
id={id}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
ariaLabel={ariaLabel}
|
||||
{...(register
|
||||
? { ...register(id!, optionsConfigForm) }
|
||||
: { onChange: onChange })}
|
||||
>
|
||||
{options.map((option) => (
|
||||
<option value={option.value} key={option.value}>
|
||||
{option.label}
|
||||
</option>
|
||||
))}
|
||||
</RenderSelect>
|
||||
</StyledSelect>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Components
|
||||
import Nav from '../Nav';
|
||||
import Nav from '@component/Nav';
|
||||
|
||||
// Styled
|
||||
import { Heading, StyledSidebar } from './styled';
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { ChangeEvent, memo } from 'react';
|
||||
import { ChangeEvent } from 'react';
|
||||
|
||||
// Components
|
||||
import Select from '../Select';
|
||||
import Select from '@component/Select';
|
||||
|
||||
interface ISortByProps {
|
||||
options: {
|
||||
@@ -11,7 +11,7 @@ interface ISortByProps {
|
||||
}[];
|
||||
}
|
||||
|
||||
const SortBy = memo(({ options }: ISortByProps) => {
|
||||
const SortBy = ({ options }: ISortByProps) => {
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const sortBy = searchParams.get('sortBy') || '';
|
||||
const handleChange = (event: ChangeEvent<HTMLSelectElement>) => {
|
||||
@@ -27,6 +27,6 @@ const SortBy = memo(({ options }: ISortByProps) => {
|
||||
ariaLabel="Sort"
|
||||
/>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
export default SortBy;
|
||||
|
||||
@@ -4,13 +4,17 @@ import { ReactNode, useContext } from 'react';
|
||||
import { StyledBody, StyledHeader, StyledRow, StyledTable } from './styled';
|
||||
|
||||
// Contexts
|
||||
import TableContext from '../../contexts/TableContext';
|
||||
import TableContext from '@context/TableContext';
|
||||
|
||||
export interface ITable {
|
||||
columns?: string;
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export interface IHeader {
|
||||
headerColumn: string[];
|
||||
}
|
||||
|
||||
interface ITableBody<T> {
|
||||
data?: T[];
|
||||
render?: CallbackMapFunc<T>;
|
||||
@@ -26,10 +30,12 @@ const Table = ({ columns, children }: ITable) => {
|
||||
);
|
||||
};
|
||||
|
||||
const Header = ({ children }: ITable) => {
|
||||
const Header = ({ headerColumn }: IHeader) => {
|
||||
const { columns } = useContext(TableContext);
|
||||
|
||||
return <StyledHeader columns={columns}>{children}</StyledHeader>;
|
||||
return <StyledHeader columns={columns}>
|
||||
{headerColumn.map((item) => <div key={item}>{item}</div>)}
|
||||
</StyledHeader>;
|
||||
};
|
||||
|
||||
const Body = <T,>({ data, render }: ITableBody<T>) => {
|
||||
|
||||
Reference in New Issue
Block a user