From 01a2efabbaaf46131441725c597f47bd98ef9e32 Mon Sep 17 00:00:00 2001 From: "yeondu._" Date: Thu, 15 Aug 2024 19:50:49 +0900 Subject: [PATCH] =?UTF-8?q?Feat=20:=20=EB=AA=A8=EB=8B=AC/=EC=9D=B8?= =?UTF-8?q?=ED=92=8B/=EB=B2=84=ED=8A=BC=20=EC=99=84=EC=84=B1=20~~:?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 49 +++++++ package.json | 4 + src/Component/Button/button.tsx | 26 ++++ src/Component/Chart/chart.tsx | 212 ++++++------------------------ src/Component/Input/input.tsx | 56 ++++++++ src/Component/Modal/modal.tsx | 86 ++++++++++++ src/Component/Modal/modalStyle.ts | 54 ++++++++ src/Pages/home.tsx | 2 + src/Styles/Fonts.ts | 5 - src/Styles/button.ts | 58 ++++++++ src/Styles/input.ts | 36 +++++ src/constants/interface.ts | 46 ++++++- src/fonts/fonts.css | 4 +- 13 files changed, 451 insertions(+), 187 deletions(-) create mode 100644 src/Component/Button/button.tsx create mode 100644 src/Component/Input/input.tsx create mode 100644 src/Component/Modal/modal.tsx create mode 100644 src/Component/Modal/modalStyle.ts delete mode 100644 src/Styles/Fonts.ts create mode 100644 src/Styles/button.ts create mode 100644 src/Styles/input.ts diff --git a/package-lock.json b/package-lock.json index 8ff607c..08b993b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,11 +18,15 @@ "apexcharts": "^3.52.0", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-modal": "^3.16.1", "react-router-dom": "^6.26.0", "react-scripts": "5.0.1", "styled-components": "^6.1.12", "typescript": "^4.9.5", "web-vitals": "^2.1.4" + }, + "devDependencies": { + "@types/react-modal": "^3.16.3" } }, "node_modules/@adobe/css-tools": { @@ -4196,6 +4200,15 @@ "@types/react": "*" } }, + "node_modules/@types/react-modal": { + "version": "3.16.3", + "resolved": "https://registry.npmjs.org/@types/react-modal/-/react-modal-3.16.3.tgz", + "integrity": "sha512-xXuGavyEGaFQDgBv4UVm8/ZsG+qxeQ7f77yNrW3n+1J6XAstUy5rYHeIHPh1KzsGc6IkCIdu6lQ2xWzu1jBTLg==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/resolve": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", @@ -7995,6 +8008,11 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/exenv": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz", + "integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw==" + }, "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -14786,6 +14804,29 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "node_modules/react-modal": { + "version": "3.16.1", + "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.16.1.tgz", + "integrity": "sha512-VStHgI3BVcGo7OXczvnJN7yT2TWHJPDXZWyI/a0ssFNhGZWsPmB8cF0z33ewDXq4VfYMO1vXgiv/g8Nj9NDyWg==", + "dependencies": { + "exenv": "^1.2.0", + "prop-types": "^15.7.2", + "react-lifecycles-compat": "^3.0.0", + "warning": "^4.0.3" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18", + "react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18" + } + }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -17342,6 +17383,14 @@ "makeerror": "1.0.12" } }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/watchpack": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", diff --git a/package.json b/package.json index c7d004f..8e1c699 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "apexcharts": "^3.52.0", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-modal": "^3.16.1", "react-router-dom": "^6.26.0", "react-scripts": "5.0.1", "styled-components": "^6.1.12", @@ -42,5 +43,8 @@ "last 1 firefox version", "last 1 safari version" ] + }, + "devDependencies": { + "@types/react-modal": "^3.16.3" } } diff --git a/src/Component/Button/button.tsx b/src/Component/Button/button.tsx new file mode 100644 index 0000000..ed5d506 --- /dev/null +++ b/src/Component/Button/button.tsx @@ -0,0 +1,26 @@ +import styled from "styled-components" +import React from "react" +import { buttonSize, buttonType } from "../../Styles/button"; +import { ButtonStyleProps, ButtonProps } from "../../constants/interface"; + +const ButtonStyle = styled.button` + border-radius: 10px; + + ${(props) => buttonSize[props.size]} + ${(props) => buttonType[props.colorType]?.[props.state]} +` + +const Button = ({onClick, children, ...styleprops}: ButtonProps) => { + return ( + <> + + {children} + + + ) +} + +export default Button; + +// 버튼 사용 예시 +{/* */} \ No newline at end of file diff --git a/src/Component/Chart/chart.tsx b/src/Component/Chart/chart.tsx index c022309..71d8d12 100644 --- a/src/Component/Chart/chart.tsx +++ b/src/Component/Chart/chart.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useRef } from "react"; +import React, { useEffect, useRef, useState } from "react"; import ApexCharts from "apexcharts"; const Chart = () => { @@ -8,251 +8,108 @@ const Chart = () => { if (chartRef.current) { const options = { series: [{ - data: [{ - x: new Date(1538778600000), + data: [ + { + x: new Date(2016,0,1), y: [6629.81, 6650.5, 6623.04, 6633.33] }, { - x: new Date(1538780400000), + x: new Date(2016,0,2), y: [6632.01, 6643.59, 6620, 6630.11] }, { - x: new Date(1538782200000), + x: new Date(2016,0,3), y: [6630.71, 6648.95, 6623.34, 6635.65] }, { - x: new Date(1538784000000), + x: new Date(2016,0,4), y: [6635.65, 6651, 6629.67, 6638.24] }, { - x: new Date(1538785800000), + x: new Date(2016,0,5), y: [6638.24, 6640, 6620, 6624.47] }, { - x: new Date(1538787600000), + x: new Date(2016,0,6), y: [6624.53, 6636.03, 6621.68, 6624.31] }, { - x: new Date(1538789400000), + x: new Date(2016,0,7), y: [6624.61, 6632.2, 6617, 6626.02] }, { - x: new Date(1538791200000), + x: new Date(2016,0,8), y: [6627, 6627.62, 6584.22, 6603.02] }, { - x: new Date(1538793000000), + x: new Date(2016,0,9), y: [6605, 6608.03, 6598.95, 6604.01] }, { - x: new Date(1538794800000), + x: new Date(2016,0,10), y: [6604.5, 6614.4, 6602.26, 6608.02] }, { - x: new Date(1538796600000), + x: new Date(2016,0,11), y: [6608.02, 6610.68, 6601.99, 6608.91] }, { - x: new Date(1538798400000), + x: new Date(2016,0,12), y: [6608.91, 6618.99, 6608.01, 6612] }, { - x: new Date(1538800200000), + x: new Date(2016,0,13), y: [6612, 6615.13, 6605.09, 6612] }, { - x: new Date(1538802000000), + x: new Date(2016,0,14), y: [6612, 6624.12, 6608.43, 6622.95] }, { - x: new Date(1538803800000), + x: new Date(2016,0,15), y: [6623.91, 6623.91, 6615, 6615.67] }, { - x: new Date(1538805600000), + x: new Date(2016,0,16), y: [6618.69, 6618.74, 6610, 6610.4] }, { - x: new Date(1538807400000), + x: new Date(2016,0,17), y: [6611, 6622.78, 6610.4, 6614.9] }, { - x: new Date(1538809200000), + x: new Date(2016,0,18), y: [6614.9, 6626.2, 6613.33, 6623.45] }, { - x: new Date(1538811000000), + x: new Date(2016,0,19), y: [6623.48, 6627, 6618.38, 6620.35] }, { - x: new Date(1538812800000), + x: new Date(2016,0,20), y: [6619.43, 6620.35, 6610.05, 6615.53] }, { - x: new Date(1538814600000), + x: new Date(2016,0,21), y: [6615.53, 6617.93, 6610, 6615.19] }, { - x: new Date(1538816400000), + x: new Date(2016,0,22), y: [6615.19, 6621.6, 6608.2, 6620] }, { - x: new Date(1538818200000), + x: new Date(2016,0,23), y: [6619.54, 6625.17, 6614.15, 6620] }, { - x: new Date(1538820000000), + x: new Date(2016,0,24), y: [6620.33, 6634.15, 6617.24, 6624.61] }, - { - x: new Date(1538821800000), - y: [6625.95, 6626, 6611.66, 6617.58] - }, - { - x: new Date(1538823600000), - y: [6619, 6625.97, 6595.27, 6598.86] - }, - { - x: new Date(1538825400000), - y: [6598.86, 6598.88, 6570, 6587.16] - }, - { - x: new Date(1538827200000), - y: [6588.86, 6600, 6580, 6593.4] - }, - { - x: new Date(1538829000000), - y: [6593.99, 6598.89, 6585, 6587.81] - }, - { - x: new Date(1538830800000), - y: [6587.81, 6592.73, 6567.14, 6578] - }, - { - x: new Date(1538832600000), - y: [6578.35, 6581.72, 6567.39, 6579] - }, - { - x: new Date(1538834400000), - y: [6579.38, 6580.92, 6566.77, 6575.96] - }, - { - x: new Date(1538836200000), - y: [6575.96, 6589, 6571.77, 6588.92] - }, - { - x: new Date(1538838000000), - y: [6588.92, 6594, 6577.55, 6589.22] - }, - { - x: new Date(1538839800000), - y: [6589.3, 6598.89, 6589.1, 6596.08] - }, - { - x: new Date(1538841600000), - y: [6597.5, 6600, 6588.39, 6596.25] - }, - { - x: new Date(1538843400000), - y: [6598.03, 6600, 6588.73, 6595.97] - }, - { - x: new Date(1538845200000), - y: [6595.97, 6602.01, 6588.17, 6602] - }, - { - x: new Date(1538847000000), - y: [6602, 6607, 6596.51, 6599.95] - }, - { - x: new Date(1538848800000), - y: [6600.63, 6601.21, 6590.39, 6591.02] - }, - { - x: new Date(1538850600000), - y: [6591.02, 6603.08, 6591, 6591] - }, - { - x: new Date(1538852400000), - y: [6591, 6601.32, 6585, 6592] - }, - { - x: new Date(1538854200000), - y: [6593.13, 6596.01, 6590, 6593.34] - }, - { - x: new Date(1538856000000), - y: [6593.34, 6604.76, 6582.63, 6593.86] - }, - { - x: new Date(1538857800000), - y: [6593.86, 6604.28, 6586.57, 6600.01] - }, - { - x: new Date(1538859600000), - y: [6601.81, 6603.21, 6592.78, 6596.25] - }, - { - x: new Date(1538861400000), - y: [6596.25, 6604.2, 6590, 6602.99] - }, - { - x: new Date(1538863200000), - y: [6602.99, 6606, 6584.99, 6587.81] - }, - { - x: new Date(1538865000000), - y: [6587.81, 6595, 6583.27, 6591.96] - }, - { - x: new Date(1538866800000), - y: [6591.97, 6596.07, 6585, 6588.39] - }, - { - x: new Date(1538868600000), - y: [6587.6, 6598.21, 6587.6, 6594.27] - }, - { - x: new Date(1538870400000), - y: [6596.44, 6601, 6590, 6596.55] - }, - { - x: new Date(1538872200000), - y: [6598.91, 6605, 6596.61, 6600.02] - }, - { - x: new Date(1538874000000), - y: [6600.55, 6605, 6589.14, 6593.01] - }, - { - x: new Date(1538875800000), - y: [6593.15, 6605, 6592, 6603.06] - }, - { - x: new Date(1538877600000), - y: [6603.07, 6604.5, 6599.09, 6603.89] - }, - { - x: new Date(1538879400000), - y: [6604.44, 6604.44, 6600, 6603.5] - }, - { - x: new Date(1538881200000), - y: [6603.5, 6603.99, 6597.5, 6603.86] - }, - { - x: new Date(1538883000000), - y: [6603.85, 6605, 6600, 6604.07] - }, - { - x: new Date(1538884800000), - y: [6604.98, 6606, 6604.07, 6606] - }, - ] + ] }], chart: { type: 'candlestick', - height: 350 + height: 350, }, title: { text: 'CandleStick Chart', @@ -277,8 +134,17 @@ const Chart = () => { } },[]); + const [isOpen, setIsOpen] = useState(true); + + const handleConfirm = () => { + // Logic to add the asset + setIsOpen(false); + }; + return ( -
+ <> +
+ ); } diff --git a/src/Component/Input/input.tsx b/src/Component/Input/input.tsx new file mode 100644 index 0000000..5013c26 --- /dev/null +++ b/src/Component/Input/input.tsx @@ -0,0 +1,56 @@ +import React, { forwardRef } from 'react'; +import { InputStyleProps, inputProps } from '../../constants/interface'; +import styled from 'styled-components'; +import { inputSize, inputType } from '../../Styles/input'; + +const InputContainer = styled.div` + position: relative; + display: inline-block; + width: 100%; +`; + +const IconWrapper = styled.span` + position: absolute; + top: 50%; + left: 10px; + transform: translateY(-50%); + display: flex; + align-items: center; + justify-content: center; + pointer-events: none; +`; + +const InputStyle = styled.input` + border-radius: 5px; + padding: ${(props) => (props.hasIcon ? '0.5rem 1rem 0.5rem 2.5rem' : '0.5rem 1rem')}; + font-size: 12px; + font-family: "SCDream4"; + color : black; + ::placeholder { + color: #B6B6B6; + opacity: 1; + } + ${(props) => inputSize[props.size]} + ${(props) => inputType[props.colorType]?.normal} +` + +export const Input = forwardRef ( + ({ placeholder, value, onChange, onBlur, name, icon, ...styleProps }, ref) => { + return ( + + {icon && {icon}} + + + ); + } +); \ No newline at end of file diff --git a/src/Component/Modal/modal.tsx b/src/Component/Modal/modal.tsx new file mode 100644 index 0000000..0d92932 --- /dev/null +++ b/src/Component/Modal/modal.tsx @@ -0,0 +1,86 @@ +import React from "react"; +import Button from "../Button/button"; +import { ButtonStyle, ModalBody, ModalHeader, ModalStyles } from "./modalStyle"; +import { ModalProps } from "../../constants/interface"; +import ReactModal from "react-modal"; + +const ModalOpen: React.FC = ({ + title, + isOpen, + onRequestClose, + onConfirm, + confirmLabel = "확인", + cancelLabel = "취소", + showConfirmButton = true, + showCancelButton = true, + showOneConfirmBtn = false, + text, + children, + }) => { + return( + + + {title &&

{title}

} + × +
+ {children} + {showOneConfirmBtn ? ( + // 하나의 텍스트 버튼만 있는 모달 +
+ {onConfirm && ( + + )} +
+ ) : ( + // 확인/취소 버튼이 있는 모달 +
+ {showCancelButton && ( + + )} + {showConfirmButton && onConfirm && ( + + )} +
+ )} +
+ ) +} + +export default ModalOpen; + + +// 모달 사용 예시 +{/* setIsOpen(false)} + showOneConfirmBtn={true} + text="자산 추가" + onConfirm={handleConfirm} + > +
+
+

APS

+

05462

+
+
+
수량
+ +
단가
+ +
+
+
*/} \ No newline at end of file diff --git a/src/Component/Modal/modalStyle.ts b/src/Component/Modal/modalStyle.ts new file mode 100644 index 0000000..cbc0dac --- /dev/null +++ b/src/Component/Modal/modalStyle.ts @@ -0,0 +1,54 @@ +import styled from "styled-components"; +import ReactModal from "react-modal"; + +export const ModalStyles : ReactModal.Styles = { + overlay : { + backgroundColor: "rgb(255 255 255 / 100%)", + width: "100%", + height: "100%", + zIndex: 10, + top: "0", + left: "0", + }, + content : { + width: "400px", + height: "auto", + zIndex: "11", + position: "fixed", + top: "50%", + left: "50%", + transform: "translate(-50%, -50%)", + overflow : "auto" + } +} + +export const ModalHeader = styled.div` + display: flex; + justify-content: space-between; + align-items: center; + padding-bottom: 10px; + margin-bottom: 20px; + + h2 { + margin: 0; + font-size: 15px; + } + + button { + background: none; + border: none; + font-size: 18px; + cursor: pointer; + } +`; + +export const ModalBody = styled.div` + font-family: 'SCDream4'; + padding: 10px 0; + font-size: 14px; +`; + +export const ButtonStyle = styled.button` + border: none; + background: none; +`; diff --git a/src/Pages/home.tsx b/src/Pages/home.tsx index 8bf6022..2a3dd89 100644 --- a/src/Pages/home.tsx +++ b/src/Pages/home.tsx @@ -1,5 +1,7 @@ import React from "react"; import Chart from "../Component/Chart/chart"; +import { Input } from "../Component/Input/input"; +import Candy from "../img/candy.png"; const Home = () => { return ( diff --git a/src/Styles/Fonts.ts b/src/Styles/Fonts.ts deleted file mode 100644 index c41c075..0000000 --- a/src/Styles/Fonts.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const Fonts = { - MainColor : "", - subColor : "", - -} \ No newline at end of file diff --git a/src/Styles/button.ts b/src/Styles/button.ts new file mode 100644 index 0000000..8b939ef --- /dev/null +++ b/src/Styles/button.ts @@ -0,0 +1,58 @@ +import { css } from "styled-components" +import { Colors } from "./Colors" + +export const buttonSize = { + small : css` + width : 140px; + height: 40px; + `, + medium : css` + width : 170px; + height: 44px; + `, + large : css` + width : 330px; + height: 60px; + `, + plusBtn : css` + width : 340px; + height: 45px; + `, + gradientBtn : css` + width : 250px; + height: 50px; + ` +} + +export const mainColorBtn = { + normal : css` + background : ${Colors.main}; + color : #fff; + border: none; + font-size : 14px; + ` +} + +export const gradientBtnStyle = { + normal : css` + background : radial-gradient(circle, #4834D4 0%, #686DE0 100%); + color : #fff; + border: none; + font-size : 14px; + ` +} + +export const cancelBtnStyle = { + normal : css` + background: none; + border : 1px solid ${Colors.red}; + color: ${Colors.red}; + font-size : 14px; + ` +} + +export const buttonType = { + main: mainColorBtn, + gradient: gradientBtnStyle, + cancel : cancelBtnStyle +}; \ No newline at end of file diff --git a/src/Styles/input.ts b/src/Styles/input.ts new file mode 100644 index 0000000..2a75d4c --- /dev/null +++ b/src/Styles/input.ts @@ -0,0 +1,36 @@ +import {css} from "styled-components" +import { Colors } from "./Colors"; + +export const inputSize = { + small : css` + width : 264px; + height: 42px; + `, + medium: css` + width : 340px; + height: 40px; + `, + large: css` + width : 350px; + height: 42px; + ` +}; + +export const fillTypeInput = { + normal: css` + background : rgba(97, 94, 252, 0.16); + border: none; + ` +} + +export const strokTypeInput = { + normal: css` + background : none; + border : 1px solid ${Colors.main}; + ` +} + +export const inputType = { + fillType : fillTypeInput, + strokeType : strokTypeInput +} \ No newline at end of file diff --git a/src/constants/interface.ts b/src/constants/interface.ts index e095905..0d50a37 100644 --- a/src/constants/interface.ts +++ b/src/constants/interface.ts @@ -1,8 +1,40 @@ -export interface NewsProps { - title: string; - content: string; - image: string; - writer: string; - date: Date; - company: string; +export type ButtonStyleProps = { + state: "normal"; + size : "small" | "medium" | "large" | "plusBtn" | "gradientBtn"; + colorType : 'main' | 'gradient' | 'cancel'; +}; + +export interface ButtonProps extends ButtonStyleProps{ + onClick?: () => void; + children: React.ReactNode; +} + + +export type InputStyleProps = { + size : 'small' | 'medium' | 'large'; + colorType : 'fillType' | 'strokeType'; + disabled?: boolean; +} + +export interface inputProps extends InputStyleProps { + placeholder : string; + value?: string; + onChange?: (event: React.ChangeEvent) => void; + onBlur ?: (event: React.FocusEvent) => void; + name?: string; + icon?: React.ReactNode; +} + +export interface ModalProps { + title?: string; + isOpen: boolean; + onRequestClose?: () => void; + onConfirm?: () => void; + confirmLabel?: string; + cancelLabel?: string; + showConfirmButton?: string; + showCancelButton?: string; + showOneConfirmBtn?: boolean; + children?: React.ReactNode; + text ?: string; } \ No newline at end of file diff --git a/src/fonts/fonts.css b/src/fonts/fonts.css index c8ff059..0b6501e 100644 --- a/src/fonts/fonts.css +++ b/src/fonts/fonts.css @@ -13,14 +13,14 @@ } @font-face { - font-family: "SCDream5"; + font-family: "SCDream3"; font-style: normal; font-weight: 300; src: url("./SCDream5.otf") format("woff"); } @font-face { - font-family: "SCDream5"; + font-family: "SCDream4"; font-style: normal; font-weight: 400; src: url("./SCDream5.otf") format("woff");