Merge pull request #10 from Nez27/feat/add-common-components-and-ultis

Add common components for form and helpers folder.
This commit is contained in:
Loi Phan
2023-10-26 17:13:57 +07:00
committed by GitHub
10 changed files with 162 additions and 10 deletions
+4
View File
@@ -20,6 +20,10 @@
"*.tsx": [
"pnpm run lint",
"pnpm run format"
],
"*.ts": [
"pnpm run lint",
"pnpm run format"
]
},
"dependencies": {
+25 -5
View File
@@ -1,15 +1,35 @@
import styled from 'styled-components';
import styled, { css } from 'styled-components';
const Button = styled.button`
interface IButtonStyle {
styled?: 'primary' | 'secondary';
}
const Button = styled.button<IButtonStyle>`
padding: 10px 20px;
background-color: var(--primary-color);
color: var(--light-text);
text-transform: uppercase;
font-weight: 500;
font-weight: 600;
cursor: pointer;
border-radius: var(--radius-md);
${(props) =>
props.styled === 'primary' &&
css`
background-color: var(--primary-color);
color: var(--light-text);
`}
${(props) =>
props.styled === 'secondary' &&
css`
background-color: var(--secondary-btn-color);
`}
`;
Button.defaultProps = {
styled: 'primary',
};
export default Button;
@@ -0,0 +1,12 @@
import { css } from 'styled-components';
const CommonInput = css`
border: 1px solid var(--border-color);
border-radius: var(--radius-sm);
padding: 10px 20px;
font-size: var(--fs-sm-x);
width: 200px;
`;
export default CommonInput;
@@ -0,0 +1,10 @@
import styled from 'styled-components';
// Styled
import CommonInput from './CommonInput';
const Input = styled.input`
${CommonInput}
`;
export default Input;
@@ -0,0 +1,10 @@
import styled from 'styled-components';
// Styled
import CommonInput from './CommonInput';
const TextArea = styled.textarea`
${CommonInput}
`;
export default TextArea;
+13 -4
View File
@@ -1,21 +1,30 @@
export interface IMenusContext {
interface IMenusContext {
openId?: string;
close?: () => void;
open?: React.Dispatch<React.SetStateAction<string>>;
}
export interface IButton {
interface IButton {
children?: string;
icon?: JSX.Element;
onClick?: () => void;
}
export interface ITable {
interface ITable {
columns?: string;
children: React.ReactNode;
}
export interface ITableBody<T> {
interface ITableBody<T> {
data?: T[];
render?: (value: T) => JSX.Element;
}
interface IDialogProps {
title?: string;
children?: JSX.Element[] | JSX.Element;
onClose?: () => void;
ref?: React.MutableRefObject<HTMLDialogElement | undefined>;
}
export type { IMenusContext, IButton, ITable, ITableBody, IDialogProps };
+26 -1
View File
@@ -1,4 +1,4 @@
export type TUser = {
type TUser = {
id: string;
name: string;
identifiedCode: string;
@@ -6,3 +6,28 @@ export type TUser = {
phone: string;
roomId: string;
};
type TStateSchema = {
[key: string]: {
value?: string;
error?: string;
};
};
type TKeyValue = {
[key: string]: string | undefined | boolean;
};
type TPropValues = 'value' | 'error' | boolean;
type TValidator = {
[key: string]: {
required?: boolean;
validator?: {
func?: (value: string) => boolean;
error?: string;
};
};
};
export type { TUser, TStateSchema, TKeyValue, TPropValues, TValidator };
+37
View File
@@ -0,0 +1,37 @@
import { TKeyValue, TPropValues, TStateSchema } from '../globals/types';
const VALUE = 'value';
const ERROR = 'error';
const REQUIRED_FIELD_ERROR = 'This is required field';
const isBool = (value: unknown) => {
return typeof value === 'boolean';
};
const isObject = (value: unknown) => {
return typeof value === 'object' && value !== null;
};
const isRequired = (value: string | number, isRequired: unknown) => {
if (!value && isRequired) return REQUIRED_FIELD_ERROR;
return '';
};
const getPropValues = (stateSchema: TStateSchema, prop?: TPropValues) => {
return Object.keys(stateSchema).reduce((field, key) => {
field[key] = isBool(prop)
? prop
: stateSchema[key][prop as Exclude<TPropValues, boolean>];
return field;
}, {} as TKeyValue);
};
export {
isObject,
isRequired,
getPropValues,
VALUE,
ERROR,
REQUIRED_FIELD_ERROR,
};
@@ -0,0 +1,17 @@
const isValidString = (value: string): boolean => {
return /^[a-zA-Z]{4,}(?: [a-zA-Z]+){0,2}$/gm.test(value);
};
const isValidNumber = (value: string): boolean => {
return /^[0-9]*$/.test(value);
};
const isValidPhoneNumber = (value: string): boolean => {
return /(84|0[3|5|7|8|9])+([0-9]{8})\b/g.test(value);
};
const isValidAddress = (value: string): boolean => {
return value.trim().length >= 10;
};
export { isValidString, isValidNumber, isValidPhoneNumber, isValidAddress };
@@ -1,10 +1,17 @@
:root {
--primary-color: #0010ba;
--header-table-color: #ebebeb;
--border-color: #8c8c8c;
--secondary-btn-color: #d1d1d1;
--disabled-btn-color: #7f82a6;
--hover-background-color: #f3f4f6;
--light-text: #fff;
--dark-text: #787878;
--error-text: #ff3d3d;
--radius-sm: 5px;
--radius-md: 10px;
@@ -15,4 +22,5 @@
--fs-lg: 40px;
--fs-sm: 18px;
--fs-sm-x: 16px;
--fs-sm-2x: 12px;
}