diff --git a/package.json b/package.json index 55eb91251..387ca946b 100644 --- a/package.json +++ b/package.json @@ -74,11 +74,7 @@ "prettier": "^2.3.0", "typescript": "4.3.4" }, - "husky": { - "hooks": { - "pre-commit": "lint-staged" - } - }, + "lint-staged": { "**/*.{js,jsx,ts,tsx}": [ "prettier --write", diff --git a/pages/index.tsx b/pages/index.tsx index 2c7ba2dbb..877f18def 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,8 +1,7 @@ -import { ButtonCommon, Layout } from 'src/components/common' -import { IconBuy } from 'src/components/icons' -import { ButonType, ButtonSize } from 'src/utils/constanst.utils' -import {CarouselCommon, LabelCommon, QuanittyInput } from 'src/components/common' +import { Layout, ProductCard } from 'src/components/common' +import {CarouselCommon } from 'src/components/common' +import image1 from "../public/assets/images/image5.png" const dataTest = [{ text:1 },{ @@ -21,20 +20,8 @@ export default function Home() { return ( <> - - - SEEFOOT - -15% - Waitting - Delivering - Delivered - Button default - {ButonType.light} - Button light - {ButonType.light} - Button light - {ButonType.light} - Button light - {ButtonSize.large} - Button default large - } disabled>Button with icon disabled - } type={ButonType.light}>Button with icon + + ) } diff --git a/public/assets/images/image5.png b/public/assets/images/image5.png new file mode 100644 index 000000000..ed9da336b Binary files /dev/null and b/public/assets/images/image5.png differ diff --git a/public/assets/images/image6.png b/public/assets/images/image6.png new file mode 100644 index 000000000..9598aabdb Binary files /dev/null and b/public/assets/images/image6.png differ diff --git a/public/assets/images/image7.png b/public/assets/images/image7.png new file mode 100644 index 000000000..25dcf3b21 Binary files /dev/null and b/public/assets/images/image7.png differ diff --git a/public/assets/images/image8.png b/public/assets/images/image8.png new file mode 100644 index 000000000..99e966722 Binary files /dev/null and b/public/assets/images/image8.png differ diff --git a/src/components/common/ButtonCommon/ButtonCommon.module.scss b/src/components/common/ButtonCommon/ButtonCommon.module.scss index eaf930670..c9a457973 100644 --- a/src/components/common/ButtonCommon/ButtonCommon.module.scss +++ b/src/components/common/ButtonCommon/ButtonCommon.module.scss @@ -5,12 +5,28 @@ display: flex; justify-content: center; align-items: center; - padding: 1.6rem 3.2rem; + // padding: 1.6rem 3.2rem; + padding: 0.8rem 1.6rem; + width: 100%; &:disabled { filter: brightness(0.9); cursor: not-allowed; color: var(--disabled); } + &:hover { + @apply shadow-md; + &:not(:disabled) { + filter: brightness(1.05); + } + } + &:focus { + outline: none; + filter: brightness(1.05); + } + &:focus-visible { + outline: 2px solid var(--text-active); + } + &.loading { &::before { content: ""; @@ -24,20 +40,6 @@ margin-right: 0.8rem; } } - &:hover { - @apply shadow-md; - &:not(:disabled) { - filter: brightness(1.05); - } - } - - &:focus { - outline: none; - filter: brightness(1.05); - } - &:focus-visible { - outline: 2px solid var(--text-active); - } &.light { @apply text-base bg-white; @@ -48,8 +50,30 @@ } } } + + &.ghost { + @apply bg-white; + color: var(--primary); + border: 1px solid var(--primary); + &.loading { + &::before { + border-top-color: var(--primary); + } + } + } + + &.onlyIcon { + padding: 0.8rem; + .icon { + margin: 0; + } + } + &.large { padding: 3.2rem 4.8rem; + &.onlyIcon { + padding: 1.6rem; + } &.loading { &::before { width: 2.4rem; @@ -58,8 +82,21 @@ } } + + + &.preserve { + flex-direction: row-reverse; + .icon { + margin: 0 0 0 1.6rem; + } + } + + .icon { + margin: 0 1.6rem 0 0; + } + + .label, .icon { - margin-right: 0.8rem; svg path { fill: currentColor; } diff --git a/src/components/common/ButtonCommon/ButtonCommon.tsx b/src/components/common/ButtonCommon/ButtonCommon.tsx index 27a4f3d72..385b35077 100644 --- a/src/components/common/ButtonCommon/ButtonCommon.tsx +++ b/src/components/common/ButtonCommon/ButtonCommon.tsx @@ -1,26 +1,28 @@ import classNames from 'classnames' -import React from 'react' -import { ButonType, ButtonSize } from 'src/utils/constanst.utils' +import React, { memo } from 'react' import s from './ButtonCommon.module.scss' interface Props { - children?: any, - type?: ButonType, - size?: ButtonSize, - icon?: any, + children?: React.ReactNode, + type?: 'primary' | 'light' | 'ghost', + size?: 'default' | 'large', + icon?: React.ReactNode, + isIconSuffix?: boolean, loading?: boolean, disabled?: boolean, onClick?: () => void, } -const ButtonCommon = ({ type = ButonType.primary, size = ButtonSize.default, - icon, loading, disabled, children, onClick }: Props) => { +const ButtonCommon = memo(({ type = 'primary', size = 'default', loading = false, isIconSuffix = false, + icon, disabled, children, onClick }: Props) => { return ( ) -} +}) export default ButtonCommon diff --git a/src/components/common/ButtonIconBuy/ButtonIconBuy.tsx b/src/components/common/ButtonIconBuy/ButtonIconBuy.tsx new file mode 100644 index 000000000..c1209c1f8 --- /dev/null +++ b/src/components/common/ButtonIconBuy/ButtonIconBuy.tsx @@ -0,0 +1,26 @@ +import React, { memo } from 'react' +import { IconBuy } from 'src/components/icons' +import ButtonCommon from '../ButtonCommon/ButtonCommon' + +interface Props { + type?: 'primary' | 'light' | 'ghost', + size?: 'default' | 'large', + loading?: boolean, + disabled?: boolean, + onClick?: () => void, +} + +const ButtonIconBuy = memo(({ type = 'light', size = 'default', loading = false, disabled, onClick }: Props) => { + return ( + } + /> + ) +}) + +export default ButtonIconBuy diff --git a/src/components/common/InputCommon/InputCommon.module.scss b/src/components/common/InputCommon/InputCommon.module.scss new file mode 100644 index 000000000..13e27fd5f --- /dev/null +++ b/src/components/common/InputCommon/InputCommon.module.scss @@ -0,0 +1,43 @@ +@import "../../../styles/utilities"; + +.inputWrap { + @apply flex items-center relative; + .icon { + @apply absolute; + content: ""; + left: 1.6rem; + margin-right: 1.6rem; + svg path { + fill: currentColor; + } + } + .icon + .inputCommon { + padding-left: 4.8rem; + } + .inputCommon { + @apply block w-full transition-all duration-200 rounded; + padding: 1.6rem; + border: 1px solid var(--border-line); + &:hover, + &:focus, + &:active { + outline: none; + border: 1px solid var(--primary); + @apply shadow-md; + } + + &::placeholder { + @apply text-label; + } + + &.custom { + @apply custom-border-radius border-none; + background: var(--gray); + &:hover, + &:focus, + &:active { + border: 1px solid var(--primary); + } + } + } +} diff --git a/src/components/common/InputCommon/InputCommon.tsx b/src/components/common/InputCommon/InputCommon.tsx new file mode 100644 index 000000000..c6446c990 --- /dev/null +++ b/src/components/common/InputCommon/InputCommon.tsx @@ -0,0 +1,59 @@ +import React, { forwardRef, useImperativeHandle, useRef } from 'react'; +import { KEY } from 'src/utils/constanst.utils'; +import s from './InputCommon.module.scss'; + +type Ref = { + focus: () => void +} | null; +interface Props { + children?: React.ReactNode, + value?: string | number, + placeholder?: string, + type?: 'text' | 'number', + styleType?: 'default' | 'custom', + icon?: React.ReactNode, + onChange?: (value: string | number) => void, + onEnter?: (value: string | number) => void, +} + +const InputCommon = forwardRef(({ value, placeholder, type, styleType = 'default', icon, + onChange, onEnter }: Props, ref) => { + const inputElementRef = useRef(null); + + useImperativeHandle(ref, () => ({ + focus: () => { + inputElementRef.current?.focus(); + }, + })); + + const handleChange = (e: React.ChangeEvent) => { + onChange && onChange(e.target.value) + } + + const handleKeyDown = (e: any) => { + if (e.key === KEY.ENTER && onEnter) { + const value = inputElementRef.current?.value || '' + onEnter(value) + } + } + + return ( +
+ { + icon && {icon} + } + +
+ ) + +}) + +export default InputCommon diff --git a/src/components/common/InputSearch/InputSearch.tsx b/src/components/common/InputSearch/InputSearch.tsx new file mode 100644 index 000000000..9c02a239c --- /dev/null +++ b/src/components/common/InputSearch/InputSearch.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import { IconSearch } from 'src/components/icons'; +import { LANGUAGE } from 'src/utils/language.utils'; +import { Inputcommon } from '..'; + +interface Props { + onChange?: (value: string | number) => void, + onEnter?: (value: string | number) => void, +} + +const InputSearch = ({ onChange, onEnter }: Props) => { + return ( + } + onChange={onChange} + onEnter={onEnter} + /> + ) +} + +export default InputSearch diff --git a/src/components/common/ProductCard/ProductCard.module.scss b/src/components/common/ProductCard/ProductCard.module.scss new file mode 100644 index 000000000..a854a7d2b --- /dev/null +++ b/src/components/common/ProductCard/ProductCard.module.scss @@ -0,0 +1,52 @@ +.productCardWarpper{ + max-width: 20.8rem; + max-height: 31.8rem; + padding: 1.2rem 1.2rem 0 1.2rem; + @apply border border-solid border-black; + .cardTop{ + @apply border border-solid border-yellow-300 relative; + max-height: 13.8rem; + .productImage{ + @apply flex justify-center items-center; + img{ + @apply inline; + } + .productLabel{ + @apply absolute left-0 bottom-0; + } + } + } + .cardMid{ + padding: 1.6rem 0; + .cardMid{ + .productname{ + font-weight: bold; + line-height: 2.4rem; + font-size: 1.6rem; + color: var(--text-active); + } + .productWeight{ + font-size: 1.2rem; + line-height: 2rem; + letter-spacing: 0.01em; + color: var(--text-base); + } + } + .cardMidBot{ + margin-top: 2.8rem; + @apply flex justify-between items-center border-t border-solid border-line; + .productPrice{ + @apply font-bold; + font-size: 2rem; + line-height: 2.8rem; + letter-spacing: -0.01em; + } + } + } + .cardBot{ + @apply flex justify-between items-center; + .cardButton{ + width: 13.6rem; + } + } +} \ No newline at end of file diff --git a/src/components/common/ProductCard/ProductCard.tsx b/src/components/common/ProductCard/ProductCard.tsx new file mode 100644 index 000000000..1422c4a3b --- /dev/null +++ b/src/components/common/ProductCard/ProductCard.tsx @@ -0,0 +1,59 @@ +import React from 'react' +import ButtonCommon from '../ButtonCommon/ButtonCommon' +import ButtonIconBuy from '../ButtonIconBuy/ButtonIconBuy' +import ItemWishList from '../ItemWishList/ItemWishList' +import LabelCommon from '../LabelCommon/LabelCommon' +import s from './ProductCard.module.scss' + +interface ProductCardProps { + category: string + name: string + weight: string + price: string + buttonText?: string + imageSrc: string +} + +const ProductCard = ({ + category, + name, + weight, + price, + buttonText = 'Buy Now', + imageSrc, +}: ProductCardProps) => { + return ( +
+
+
+ image +
+ {category} +
+
+
+
+
+
{name}
+
{weight}
+
+
+
{price}
+
+ +
+
+
+
+
+ +
+
+ {buttonText} +
+
+
+ ) +} + +export default ProductCard diff --git a/src/components/common/index.ts b/src/components/common/index.ts index 6cc7b42d9..7ac42e353 100644 --- a/src/components/common/index.ts +++ b/src/components/common/index.ts @@ -3,7 +3,11 @@ export { default as Layout } from './Layout/Layout' export { default as CarouselCommon } from './CarouselCommon/CarouselCommon' export { default as QuanittyInput } from './QuanittyInput/QuanittyInput' export { default as LabelCommon } from './LabelCommon/LabelCommon' +export { default as ProductCard } from './ProductCard/ProductCard' export { default as Head } from './Head/Head' export { default as ViewAllItem} from './ViewAllItem/ViewAllItem' export { default as ItemWishList} from './ItemWishList/ItemWishList' -export { default as Logo} from './Logo/Logo' \ No newline at end of file +export { default as Logo} from './Logo/Logo' +export { default as Inputcommon} from './InputCommon/InputCommon' +export { default as InputSearch} from './InputSearch/InputSearch' +export { default as ButtonIconBuy} from './ButtonIconBuy/ButtonIconBuy' diff --git a/src/components/icons/IconSearch.tsx b/src/components/icons/IconSearch.tsx new file mode 100644 index 000000000..4fc3633b2 --- /dev/null +++ b/src/components/icons/IconSearch.tsx @@ -0,0 +1,11 @@ +import React from 'react' + +const IconSearch = () => { + return ( + + + + ) +} + +export default IconSearch diff --git a/src/components/icons/index.ts b/src/components/icons/index.ts index 155948269..c82e4fa76 100644 --- a/src/components/icons/index.ts +++ b/src/components/icons/index.ts @@ -1 +1,3 @@ export { default as IconBuy } from './IconBuy' +export { default as IconSearch } from './IconSearch' + diff --git a/src/styles/_base.scss b/src/styles/_base.scss index abffa0914..123e581a9 100644 --- a/src/styles/_base.scss +++ b/src/styles/_base.scss @@ -32,7 +32,8 @@ --disabled: #cccccc; --border-line: #ebebeb; - --background: #f8f8f8; + --background: #fff; + --gray: #f8f8f8; --white: #fbfbfb; --background-arrow:rgba(20, 20, 20, 0.05); --font-size: 1.6rem; diff --git a/src/styles/_utilities.scss b/src/styles/_utilities.scss index 53a0d952b..20093a1b2 100644 --- a/src/styles/_utilities.scss +++ b/src/styles/_utilities.scss @@ -89,7 +89,7 @@ } } .custom-border-radius { - border-radius: 60% 10% 60% 2%/ 10% 40% 10% 50%; + border-radius: 60% 10% 60% 2%/ 10% 20% 10% 50%; } .font-heading { diff --git a/src/utils/constanst.utils.ts b/src/utils/constanst.utils.ts index 538cfe306..94f253622 100644 --- a/src/utils/constanst.utils.ts +++ b/src/utils/constanst.utils.ts @@ -1,12 +1,3 @@ - - -export enum ButonType { - primary = 'primary', - light = 'light', +export const KEY = { + ENTER: 'Enter', } - -export enum ButtonSize { - default = 'default', - large = 'large', -} - diff --git a/src/utils/language.utils.ts b/src/utils/language.utils.ts index 4343ed9db..3f8d61926 100644 --- a/src/utils/language.utils.ts +++ b/src/utils/language.utils.ts @@ -3,4 +3,7 @@ export const LANGUAGE = { BUY_NOW: 'Buy now', SHOP_NOW: 'Shop now', }, + PLACE_HOLDER: { + SEARCH: 'Search', + } } \ No newline at end of file diff --git a/tailwind.config.js b/tailwind.config.js index d2fe7ee70..2882c260c 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -52,6 +52,11 @@ module.exports = { 'background-arrow':'var(--background-arrow)', 'disabled': 'var(--text-disabled)', + line: 'var(--border-line)', + background: 'var(--background)', + white: 'var(--white)', + gray: 'var(--gray)', + disabled: 'var(--text-disabled)', // @deprecated (NOT use these variables) 'primary-2': 'var(--primary-2)',