mirror of
https://github.com/pawelmalak/flame.git
synced 2024-12-19 08:02:16 +03:00
Components: refactored UI components to use new state. Minor changes to exports and props
This commit is contained in:
parent
adc017c48d
commit
89d935e27f
@ -2,55 +2,45 @@ import { Fragment } from 'react';
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import classes from './ActionButton.module.css';
|
import classes from './ActionButton.module.css';
|
||||||
import Icon from '../../Icons/Icon/Icon';
|
import { Icon } from '../..';
|
||||||
|
|
||||||
interface ComponentProps {
|
interface Props {
|
||||||
name: string;
|
name: string;
|
||||||
icon: string;
|
icon: string;
|
||||||
link?: string;
|
link?: string;
|
||||||
handler?: () => void;
|
handler?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ActionButton = (props: ComponentProps): JSX.Element => {
|
export const ActionButton = (props: Props): JSX.Element => {
|
||||||
const body = (
|
const body = (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<div className={classes.ActionButtonIcon}>
|
<div className={classes.ActionButtonIcon}>
|
||||||
<Icon icon={props.icon} />
|
<Icon icon={props.icon} />
|
||||||
</div>
|
</div>
|
||||||
<div className={classes.ActionButtonName}>
|
<div className={classes.ActionButtonName}>{props.name}</div>
|
||||||
{props.name}
|
|
||||||
</div>
|
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
|
|
||||||
if (props.link) {
|
if (props.link) {
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link to={props.link} tabIndex={0}>
|
||||||
to={props.link}
|
|
||||||
tabIndex={0}>
|
|
||||||
{body}
|
{body}
|
||||||
</Link>
|
</Link>
|
||||||
)
|
);
|
||||||
} else if (props.handler) {
|
} else if (props.handler) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classes.ActionButton}
|
className={classes.ActionButton}
|
||||||
onClick={props.handler}
|
onClick={props.handler}
|
||||||
onKeyPress={(e) => {
|
onKeyPress={(e) => {
|
||||||
if (e.key === 'Enter' && props.handler) props.handler()
|
if (e.key === 'Enter' && props.handler) props.handler();
|
||||||
}}
|
}}
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
>{body}
|
>
|
||||||
</div>
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={classes.ActionButton}>
|
|
||||||
{body}
|
{body}
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
|
} else {
|
||||||
|
return <div className={classes.ActionButton}>{body}</div>;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
export default ActionButton;
|
|
||||||
|
@ -1,21 +1,16 @@
|
|||||||
import classes from './Button.module.css';
|
import classes from './Button.module.css';
|
||||||
|
|
||||||
interface ComponentProps {
|
interface Props {
|
||||||
children: string;
|
children: string;
|
||||||
click?: any;
|
click?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Button = (props: ComponentProps): JSX.Element => {
|
export const Button = (props: Props): JSX.Element => {
|
||||||
const {
|
const { children, click } = props;
|
||||||
children,
|
|
||||||
click
|
|
||||||
} = props;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button className={classes.Button} onClick={click ? click : () => {}} >
|
<button className={classes.Button} onClick={click ? click : () => {}}>
|
||||||
{children}
|
{children}
|
||||||
</button>
|
</button>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default Button;
|
|
||||||
|
@ -1,15 +1,10 @@
|
|||||||
|
import { ReactNode } from 'react';
|
||||||
import classes from './InputGroup.module.css';
|
import classes from './InputGroup.module.css';
|
||||||
|
|
||||||
interface ComponentProps {
|
interface Props {
|
||||||
children: JSX.Element | JSX.Element[];
|
children: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const InputGroup = (props: ComponentProps): JSX.Element => {
|
export const InputGroup = (props: Props): JSX.Element => {
|
||||||
return (
|
return <div className={classes.InputGroup}>{props.children}</div>;
|
||||||
<div className={classes.InputGroup}>
|
};
|
||||||
{props.children}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default InputGroup;
|
|
||||||
|
@ -1,31 +1,27 @@
|
|||||||
import { SyntheticEvent } from 'react';
|
import { ReactNode, SyntheticEvent } from 'react';
|
||||||
|
|
||||||
import classes from './ModalForm.module.css';
|
import classes from './ModalForm.module.css';
|
||||||
import Icon from '../../Icons/Icon/Icon';
|
import { Icon } from '../..';
|
||||||
|
|
||||||
interface ComponentProps {
|
interface ComponentProps {
|
||||||
children: JSX.Element | JSX.Element[];
|
children: ReactNode;
|
||||||
modalHandler?: () => void;
|
modalHandler?: () => void;
|
||||||
formHandler: (e: SyntheticEvent<HTMLFormElement>) => void;
|
formHandler: (e: SyntheticEvent<HTMLFormElement>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ModalForm = (props: ComponentProps): JSX.Element => {
|
export const ModalForm = (props: ComponentProps): JSX.Element => {
|
||||||
const _modalHandler = (): void => {
|
const _modalHandler = (): void => {
|
||||||
if (props.modalHandler) {
|
if (props.modalHandler) {
|
||||||
props.modalHandler();
|
props.modalHandler();
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.ModalForm}>
|
<div className={classes.ModalForm}>
|
||||||
<div className={classes.ModalFormIcon} onClick={_modalHandler}>
|
<div className={classes.ModalFormIcon} onClick={_modalHandler}>
|
||||||
<Icon icon='mdiClose' />
|
<Icon icon="mdiClose" />
|
||||||
</div>
|
</div>
|
||||||
<form onSubmit={(e) => props.formHandler(e)}>
|
<form onSubmit={(e) => props.formHandler(e)}>{props.children}</form>
|
||||||
{props.children}
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default ModalForm;
|
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
import { Fragment } from 'react';
|
import { Fragment, ReactNode } from 'react';
|
||||||
import classes from './Headline.module.css';
|
import classes from './Headline.module.css';
|
||||||
|
|
||||||
interface ComponentProps {
|
interface Props {
|
||||||
title: string;
|
title: string;
|
||||||
subtitle?: string | JSX.Element;
|
subtitle?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Headline = (props: ComponentProps): JSX.Element => {
|
export const Headline = (props: Props): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<h1 className={classes.HeadlineTitle}>{props.title}</h1>
|
<h1 className={classes.HeadlineTitle}>{props.title}</h1>
|
||||||
{props.subtitle && <p className={classes.HeadlineSubtitle}>{props.subtitle}</p>}
|
{props.subtitle && (
|
||||||
|
<p className={classes.HeadlineSubtitle}>{props.subtitle}</p>
|
||||||
|
)}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default Headline;
|
|
||||||
|
@ -2,17 +2,15 @@ import { Link } from 'react-router-dom';
|
|||||||
|
|
||||||
import classes from './SectionHeadline.module.css';
|
import classes from './SectionHeadline.module.css';
|
||||||
|
|
||||||
interface ComponentProps {
|
interface Props {
|
||||||
title: string;
|
title: string;
|
||||||
link: string
|
link: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SectionHeadline = (props: ComponentProps): JSX.Element => {
|
export const SectionHeadline = (props: Props): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<Link to={props.link}>
|
<Link to={props.link}>
|
||||||
<h2 className={classes.SectionHeadline}>{props.title}</h2>
|
<h2 className={classes.SectionHeadline}>{props.title}</h2>
|
||||||
</Link>
|
</Link>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default SectionHeadline;
|
|
||||||
|
@ -4,8 +4,6 @@ interface Props {
|
|||||||
text: string;
|
text: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SettingsHeadline = (props: Props): JSX.Element => {
|
export const SettingsHeadline = (props: Props): JSX.Element => {
|
||||||
return <h2 className={classes.SettingsHeadline}>{props.text}</h2>;
|
return <h2 className={classes.SettingsHeadline}>{props.text}</h2>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SettingsHeadline;
|
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
.Icon {
|
.Icon {
|
||||||
color: var(--color-primary);
|
color: var(--color-primary);
|
||||||
/* for settings */
|
|
||||||
/* color: var(--color-background); */
|
|
||||||
width: 90%;
|
width: 90%;
|
||||||
}
|
}
|
@ -2,12 +2,12 @@ import classes from './Icon.module.css';
|
|||||||
|
|
||||||
import { Icon as MDIcon } from '@mdi/react';
|
import { Icon as MDIcon } from '@mdi/react';
|
||||||
|
|
||||||
interface ComponentProps {
|
interface Props {
|
||||||
icon: string;
|
icon: string;
|
||||||
color?: string;
|
color?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Icon = (props: ComponentProps): JSX.Element => {
|
export const Icon = (props: Props): JSX.Element => {
|
||||||
const MDIcons = require('@mdi/js');
|
const MDIcons = require('@mdi/js');
|
||||||
let iconPath = MDIcons[props.icon];
|
let iconPath = MDIcons[props.icon];
|
||||||
|
|
||||||
@ -22,7 +22,5 @@ const Icon = (props: ComponentProps): JSX.Element => {
|
|||||||
path={iconPath}
|
path={iconPath}
|
||||||
color={props.color ? props.color : 'var(--color-primary)'}
|
color={props.color ? props.color : 'var(--color-primary)'}
|
||||||
/>
|
/>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default Icon;
|
|
||||||
|
@ -1,39 +1,32 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { Skycons } from 'skycons-ts';
|
import { Skycons } from 'skycons-ts';
|
||||||
import { GlobalState, Theme } from '../../../../interfaces';
|
import { State } from '../../../../store/reducers';
|
||||||
import { IconMapping, TimeOfDay } from './IconMapping';
|
import { IconMapping, TimeOfDay } from './IconMapping';
|
||||||
|
|
||||||
interface ComponentProps {
|
interface Props {
|
||||||
theme: Theme;
|
|
||||||
weatherStatusCode: number;
|
weatherStatusCode: number;
|
||||||
isDay: number;
|
isDay: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const WeatherIcon = (props: ComponentProps): JSX.Element => {
|
export const WeatherIcon = (props: Props): JSX.Element => {
|
||||||
|
const { theme } = useSelector((state: State) => state.theme);
|
||||||
|
|
||||||
const icon = props.isDay
|
const icon = props.isDay
|
||||||
? new IconMapping().mapIcon(props.weatherStatusCode, TimeOfDay.day)
|
? new IconMapping().mapIcon(props.weatherStatusCode, TimeOfDay.day)
|
||||||
: new IconMapping().mapIcon(props.weatherStatusCode, TimeOfDay.night);
|
: new IconMapping().mapIcon(props.weatherStatusCode, TimeOfDay.night);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const delay = setTimeout(() => {
|
const delay = setTimeout(() => {
|
||||||
const skycons = new Skycons({'color': props.theme.colors.accent});
|
const skycons = new Skycons({ color: theme.colors.accent });
|
||||||
skycons.add(`weather-icon`, icon);
|
skycons.add(`weather-icon`, icon);
|
||||||
skycons.play();
|
skycons.play();
|
||||||
}, 1);
|
}, 1);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
clearTimeout(delay);
|
clearTimeout(delay);
|
||||||
}
|
};
|
||||||
}, [props.weatherStatusCode, icon, props.theme.colors.accent]);
|
}, [props.weatherStatusCode, icon, theme.colors.accent]);
|
||||||
|
|
||||||
return <canvas id={`weather-icon`} width='50' height='50'></canvas>
|
return <canvas id={`weather-icon`} width="50" height="50"></canvas>;
|
||||||
}
|
};
|
||||||
|
|
||||||
const mapStateToProps = (state: GlobalState) => {
|
|
||||||
return {
|
|
||||||
theme: state.theme.theme
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default connect(mapStateToProps)(WeatherIcon);
|
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
|
import { ReactNode } from 'react';
|
||||||
import classes from './Layout.module.css';
|
import classes from './Layout.module.css';
|
||||||
|
|
||||||
interface ComponentProps {
|
interface ComponentProps {
|
||||||
children: JSX.Element | JSX.Element[];
|
children: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Container = (props: ComponentProps): JSX.Element => {
|
export const Container = (props: ComponentProps): JSX.Element => {
|
||||||
return (
|
return <div className={classes.Container}>{props.children}</div>;
|
||||||
<div className={classes.Container}>
|
};
|
||||||
{props.children}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
@ -1,28 +1,29 @@
|
|||||||
import { MouseEvent, useRef } from 'react';
|
import { MouseEvent, ReactNode, useRef } from 'react';
|
||||||
|
|
||||||
import classes from './Modal.module.css';
|
import classes from './Modal.module.css';
|
||||||
|
|
||||||
interface ComponentProps {
|
interface Props {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
setIsOpen: Function;
|
setIsOpen: Function;
|
||||||
children: JSX.Element;
|
children: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Modal = (props: ComponentProps): JSX.Element => {
|
export const Modal = (props: Props): JSX.Element => {
|
||||||
const modalRef = useRef(null);
|
const modalRef = useRef(null);
|
||||||
const modalClasses = [classes.Modal, props.isOpen ? classes.ModalOpen : classes.ModalClose].join(' ');
|
const modalClasses = [
|
||||||
|
classes.Modal,
|
||||||
|
props.isOpen ? classes.ModalOpen : classes.ModalClose,
|
||||||
|
].join(' ');
|
||||||
|
|
||||||
const clickHandler = (e: MouseEvent) => {
|
const clickHandler = (e: MouseEvent) => {
|
||||||
if (e.target === modalRef.current) {
|
if (e.target === modalRef.current) {
|
||||||
props.setIsOpen(false);
|
props.setIsOpen(false);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={modalClasses} onClick={clickHandler} ref={modalRef}>
|
<div className={modalClasses} onClick={clickHandler} ref={modalRef}>
|
||||||
{props.children}
|
{props.children}
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default Modal;
|
|
||||||
|
@ -1,18 +1,21 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { useDispatch } from 'react-redux';
|
||||||
import { clearNotification } from '../../../store/actions';
|
import { bindActionCreators } from 'redux';
|
||||||
|
import { actionCreators } from '../../../store';
|
||||||
|
|
||||||
import classes from './Notification.module.css';
|
import classes from './Notification.module.css';
|
||||||
|
|
||||||
interface ComponentProps {
|
interface Props {
|
||||||
title: string;
|
title: string;
|
||||||
message: string;
|
message: string;
|
||||||
id: number;
|
id: number;
|
||||||
url: string | null;
|
url: string | null;
|
||||||
clearNotification: (id: number) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Notification = (props: ComponentProps): JSX.Element => {
|
export const Notification = (props: Props): JSX.Element => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const { clearNotification } = bindActionCreators(actionCreators, dispatch);
|
||||||
|
|
||||||
const [isOpen, setIsOpen] = useState(true);
|
const [isOpen, setIsOpen] = useState(true);
|
||||||
const elementClasses = [
|
const elementClasses = [
|
||||||
classes.Notification,
|
classes.Notification,
|
||||||
@ -24,13 +27,13 @@ const Notification = (props: ComponentProps): JSX.Element => {
|
|||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
}, 3500);
|
}, 3500);
|
||||||
|
|
||||||
const clearNotification = setTimeout(() => {
|
const clearNotificationTimeout = setTimeout(() => {
|
||||||
props.clearNotification(props.id);
|
clearNotification(props.id);
|
||||||
}, 3600);
|
}, 3600);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
window.clearTimeout(closeNotification);
|
window.clearTimeout(closeNotification);
|
||||||
window.clearTimeout(clearNotification);
|
window.clearTimeout(clearNotificationTimeout);
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@ -48,5 +51,3 @@ const Notification = (props: ComponentProps): JSX.Element => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(null, { clearNotification })(Notification);
|
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
import classes from './Spinner.module.css';
|
import classes from './Spinner.module.css';
|
||||||
|
|
||||||
const Spinner = (): JSX.Element => {
|
export const Spinner = (): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<div className={classes.SpinnerWrapper}>
|
<div className={classes.SpinnerWrapper}>
|
||||||
<div className={classes.Spinner}>Loading...</div>
|
<div className={classes.Spinner}>Loading...</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default Spinner;
|
|
||||||
|
@ -1,26 +1,26 @@
|
|||||||
import classes from './Table.module.css';
|
import classes from './Table.module.css';
|
||||||
|
|
||||||
interface ComponentProps {
|
interface Props {
|
||||||
children: JSX.Element | JSX.Element[];
|
children: React.ReactNode;
|
||||||
headers: string[];
|
headers: string[];
|
||||||
innerRef?: any;
|
innerRef?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Table = (props: ComponentProps): JSX.Element => {
|
export const Table = (props: Props): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<div className={classes.TableContainer} ref={props.innerRef}>
|
<div className={classes.TableContainer} ref={props.innerRef}>
|
||||||
<table className={classes.Table}>
|
<table className={classes.Table}>
|
||||||
<thead className={classes.TableHead}>
|
<thead className={classes.TableHead}>
|
||||||
<tr>
|
<tr>
|
||||||
{props.headers.map((header: string, index: number): JSX.Element => (<th key={index}>{header}</th>))}
|
{props.headers.map(
|
||||||
|
(header: string, index: number): JSX.Element => (
|
||||||
|
<th key={index}>{header}</th>
|
||||||
|
)
|
||||||
|
)}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody className={classes.TableBody}>
|
<tbody className={classes.TableBody}>{props.children}</tbody>
|
||||||
{props.children}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default Table;
|
|
||||||
|
14
client/src/components/UI/index.ts
Normal file
14
client/src/components/UI/index.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
export * from './Table/Table';
|
||||||
|
export * from './Spinner/Spinner';
|
||||||
|
export * from './Notification/Notification';
|
||||||
|
export * from './Modal/Modal';
|
||||||
|
export * from './Layout/Layout';
|
||||||
|
export * from './Icons/Icon/Icon';
|
||||||
|
export * from './Icons/WeatherIcon/WeatherIcon';
|
||||||
|
export * from './Headlines/Headline/Headline';
|
||||||
|
export * from './Headlines/SectionHeadline/SectionHeadline';
|
||||||
|
export * from './Headlines/SettingsHeadline/SettingsHeadline';
|
||||||
|
export * from './Forms/InputGroup/InputGroup';
|
||||||
|
export * from './Forms/ModalForm/ModalForm';
|
||||||
|
export * from './Buttons/ActionButton/ActionButton';
|
||||||
|
export * from './Buttons/Button/Button';
|
Loading…
Reference in New Issue
Block a user