From bd407bb933f8dcda0ffe1cbbbe0ae167ab6e695f Mon Sep 17 00:00:00 2001 From: Loi Phan Date: Thu, 26 Oct 2023 16:49:16 +0700 Subject: [PATCH 1/3] Add common component and helpers --- hotel-management/package.json | 4 +++ hotel-management/src/commons/styles/Button.ts | 30 +++++++++++++++---- .../src/commons/styles/CommonInput.ts | 12 ++++++++ hotel-management/src/commons/styles/Input.ts | 10 +++++++ .../src/commons/styles/TextArea.ts | 10 +++++++ hotel-management/src/globals/interfaces.ts | 7 +++++ hotel-management/src/globals/types.ts | 23 ++++++++++++++ hotel-management/src/helpers/utils.ts | 30 +++++++++++++++++++ hotel-management/src/helpers/validators.ts | 11 +++++++ .../src/styles/abstracts/variables.css | 8 +++++ 10 files changed, 140 insertions(+), 5 deletions(-) create mode 100644 hotel-management/src/commons/styles/CommonInput.ts create mode 100644 hotel-management/src/commons/styles/Input.ts create mode 100644 hotel-management/src/commons/styles/TextArea.ts create mode 100644 hotel-management/src/helpers/utils.ts create mode 100644 hotel-management/src/helpers/validators.ts diff --git a/hotel-management/package.json b/hotel-management/package.json index bdb9e49..546ed0d 100644 --- a/hotel-management/package.json +++ b/hotel-management/package.json @@ -20,6 +20,10 @@ "*.tsx": [ "pnpm run lint", "pnpm run format" + ], + "*.ts": [ + "pnpm run lint", + "pnpm run format" ] }, "dependencies": { diff --git a/hotel-management/src/commons/styles/Button.ts b/hotel-management/src/commons/styles/Button.ts index 40ca5b3..11d30f4 100644 --- a/hotel-management/src/commons/styles/Button.ts +++ b/hotel-management/src/commons/styles/Button.ts @@ -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` 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; diff --git a/hotel-management/src/commons/styles/CommonInput.ts b/hotel-management/src/commons/styles/CommonInput.ts new file mode 100644 index 0000000..d854062 --- /dev/null +++ b/hotel-management/src/commons/styles/CommonInput.ts @@ -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; diff --git a/hotel-management/src/commons/styles/Input.ts b/hotel-management/src/commons/styles/Input.ts new file mode 100644 index 0000000..f1350ab --- /dev/null +++ b/hotel-management/src/commons/styles/Input.ts @@ -0,0 +1,10 @@ +import styled from 'styled-components'; + +// Styled +import CommonInput from './CommonInput'; + +const Input = styled.input` + ${CommonInput} +`; + +export default Input; diff --git a/hotel-management/src/commons/styles/TextArea.ts b/hotel-management/src/commons/styles/TextArea.ts new file mode 100644 index 0000000..dc70668 --- /dev/null +++ b/hotel-management/src/commons/styles/TextArea.ts @@ -0,0 +1,10 @@ +import styled from 'styled-components'; + +// Styled +import CommonInput from './CommonInput'; + +const TextArea = styled.textarea` + ${CommonInput} +`; + +export default TextArea; diff --git a/hotel-management/src/globals/interfaces.ts b/hotel-management/src/globals/interfaces.ts index 6dbad0e..4ea70a6 100644 --- a/hotel-management/src/globals/interfaces.ts +++ b/hotel-management/src/globals/interfaces.ts @@ -19,3 +19,10 @@ export interface ITableBody { data?: T[]; render?: (value: T) => JSX.Element; } + +export interface IDialogProps { + title?: string; + children?: JSX.Element[] | JSX.Element; + onClose?: () => void; + ref?: React.MutableRefObject; +} diff --git a/hotel-management/src/globals/types.ts b/hotel-management/src/globals/types.ts index 3f870af..ec82157 100644 --- a/hotel-management/src/globals/types.ts +++ b/hotel-management/src/globals/types.ts @@ -6,3 +6,26 @@ export type TUser = { phone: string; roomId: string; }; + +export type TStateSchema = { + [key: string]: { + value?: string; + error?: string; + }; +}; + +export type TKeyValue = { + [key: string]: string | undefined | boolean; +}; + +export type TPropValues = 'value' | 'error' | boolean; + +export type TValidator = { + [key: string]: { + required?: boolean; + validator?: { + func?: (value: string) => boolean; + error?: string; + }; + }; +}; diff --git a/hotel-management/src/helpers/utils.ts b/hotel-management/src/helpers/utils.ts new file mode 100644 index 0000000..7befcc7 --- /dev/null +++ b/hotel-management/src/helpers/utils.ts @@ -0,0 +1,30 @@ +import { TKeyValue, TPropValues, TStateSchema } from '../globals/types'; + +export const VALUE = 'value'; +export const ERROR = 'error'; +export const REQUIRED_FIELD_ERROR = 'This is required field'; + +function 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]; + + return field; + }, {} as TKeyValue); +}; + +export { isObject, isRequired, getPropValues }; diff --git a/hotel-management/src/helpers/validators.ts b/hotel-management/src/helpers/validators.ts new file mode 100644 index 0000000..ff6f34b --- /dev/null +++ b/hotel-management/src/helpers/validators.ts @@ -0,0 +1,11 @@ +const isValidString = (value: string): boolean => + /^[a-zA-Z]{4,}(?: [a-zA-Z]+){0,2}$/gm.test(value); + +const isValidNumber = (value: string): boolean => /^[0-9]*$/.test(value); + +const isValidPhoneNumber = (value: string): boolean => + /(84|0[3|5|7|8|9])+([0-9]{8})\b/g.test(value); + +const isValidAddress = (value: string): boolean => value.trim().length >= 10; + +export { isValidString, isValidNumber, isValidPhoneNumber, isValidAddress }; diff --git a/hotel-management/src/styles/abstracts/variables.css b/hotel-management/src/styles/abstracts/variables.css index 98c2c74..6bf698c 100644 --- a/hotel-management/src/styles/abstracts/variables.css +++ b/hotel-management/src/styles/abstracts/variables.css @@ -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; } From b0703ffdd342dd197a34f152ea3919dd7ee8ffcf Mon Sep 17 00:00:00 2001 From: Loi Phan Date: Thu, 26 Oct 2023 16:57:09 +0700 Subject: [PATCH 2/3] Fix coding style --- hotel-management/src/globals/interfaces.ts | 12 +++++++----- hotel-management/src/globals/types.ts | 12 +++++++----- hotel-management/src/helpers/utils.ts | 15 +++++++++++---- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/hotel-management/src/globals/interfaces.ts b/hotel-management/src/globals/interfaces.ts index 4ea70a6..e604962 100644 --- a/hotel-management/src/globals/interfaces.ts +++ b/hotel-management/src/globals/interfaces.ts @@ -1,28 +1,30 @@ -export interface IMenusContext { +interface IMenusContext { openId?: string; close?: () => void; open?: React.Dispatch>; } -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 { +interface ITableBody { data?: T[]; render?: (value: T) => JSX.Element; } -export interface IDialogProps { +interface IDialogProps { title?: string; children?: JSX.Element[] | JSX.Element; onClose?: () => void; ref?: React.MutableRefObject; } + +export type { IMenusContext, IButton, ITable, ITableBody, IDialogProps }; diff --git a/hotel-management/src/globals/types.ts b/hotel-management/src/globals/types.ts index ec82157..1288023 100644 --- a/hotel-management/src/globals/types.ts +++ b/hotel-management/src/globals/types.ts @@ -1,4 +1,4 @@ -export type TUser = { +type TUser = { id: string; name: string; identifiedCode: string; @@ -7,20 +7,20 @@ export type TUser = { roomId: string; }; -export type TStateSchema = { +type TStateSchema = { [key: string]: { value?: string; error?: string; }; }; -export type TKeyValue = { +type TKeyValue = { [key: string]: string | undefined | boolean; }; -export type TPropValues = 'value' | 'error' | boolean; +type TPropValues = 'value' | 'error' | boolean; -export type TValidator = { +type TValidator = { [key: string]: { required?: boolean; validator?: { @@ -29,3 +29,5 @@ export type TValidator = { }; }; }; + +export type { TUser, TStateSchema, TKeyValue, TPropValues, TValidator }; diff --git a/hotel-management/src/helpers/utils.ts b/hotel-management/src/helpers/utils.ts index 7befcc7..89436aa 100644 --- a/hotel-management/src/helpers/utils.ts +++ b/hotel-management/src/helpers/utils.ts @@ -1,8 +1,8 @@ import { TKeyValue, TPropValues, TStateSchema } from '../globals/types'; -export const VALUE = 'value'; -export const ERROR = 'error'; -export const REQUIRED_FIELD_ERROR = 'This is required field'; +const VALUE = 'value'; +const ERROR = 'error'; +const REQUIRED_FIELD_ERROR = 'This is required field'; function isBool(value: unknown) { return typeof value === 'boolean'; @@ -27,4 +27,11 @@ const getPropValues = (stateSchema: TStateSchema, prop?: TPropValues) => { }, {} as TKeyValue); }; -export { isObject, isRequired, getPropValues }; +export { + isObject, + isRequired, + getPropValues, + VALUE, + ERROR, + REQUIRED_FIELD_ERROR, +}; From 22091d4994aefdea9781a3bf8874779803f2b0fd Mon Sep 17 00:00:00 2001 From: Loi Phan Date: Thu, 26 Oct 2023 17:13:02 +0700 Subject: [PATCH 3/3] Fix code styled format --- hotel-management/src/helpers/utils.ts | 4 ++-- hotel-management/src/helpers/validators.ts | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/hotel-management/src/helpers/utils.ts b/hotel-management/src/helpers/utils.ts index 89436aa..767a3d0 100644 --- a/hotel-management/src/helpers/utils.ts +++ b/hotel-management/src/helpers/utils.ts @@ -4,9 +4,9 @@ const VALUE = 'value'; const ERROR = 'error'; const REQUIRED_FIELD_ERROR = 'This is required field'; -function isBool(value: unknown) { +const isBool = (value: unknown) => { return typeof value === 'boolean'; -} +}; const isObject = (value: unknown) => { return typeof value === 'object' && value !== null; diff --git a/hotel-management/src/helpers/validators.ts b/hotel-management/src/helpers/validators.ts index ff6f34b..4157039 100644 --- a/hotel-management/src/helpers/validators.ts +++ b/hotel-management/src/helpers/validators.ts @@ -1,11 +1,17 @@ -const isValidString = (value: string): boolean => - /^[a-zA-Z]{4,}(?: [a-zA-Z]+){0,2}$/gm.test(value); +const isValidString = (value: string): boolean => { + return /^[a-zA-Z]{4,}(?: [a-zA-Z]+){0,2}$/gm.test(value); +}; -const isValidNumber = (value: string): boolean => /^[0-9]*$/.test(value); +const isValidNumber = (value: string): boolean => { + return /^[0-9]*$/.test(value); +}; -const isValidPhoneNumber = (value: string): boolean => - /(84|0[3|5|7|8|9])+([0-9]{8})\b/g.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 => value.trim().length >= 10; +const isValidAddress = (value: string): boolean => { + return value.trim().length >= 10; +}; export { isValidString, isValidNumber, isValidPhoneNumber, isValidAddress };