-
+
+
diff --git a/src/components/common/draggable/withDraggable.jsx b/src/components/common/draggable/withDraggable.jsx
new file mode 100644
index 00000000..9f322583
--- /dev/null
+++ b/src/components/common/draggable/withDraggable.jsx
@@ -0,0 +1,22 @@
+'use client'
+
+import { useState } from 'react'
+import Draggable from 'react-draggable'
+
+export default function WithDraggable({ isShow, children }) {
+ const [position, setPosition] = useState({ x: 0, y: 0 })
+
+ const handleOnDrag = (data) => {
+ setPosition({ x: data.x, y: data.y })
+ }
+
+ return (
+ <>
+ {isShow && (
+
handleOnDrag(data)}>
+ {children}
+
+ )}
+ >
+ )
+}
diff --git a/src/components/common/select/QSelectBox.jsx b/src/components/common/select/QSelectBox.jsx
new file mode 100644
index 00000000..6e77a539
--- /dev/null
+++ b/src/components/common/select/QSelectBox.jsx
@@ -0,0 +1,19 @@
+'use client'
+import { useState } from 'react'
+
+export default function QSelectBox({ title, option }) {
+ const [selectAct, setSelectAct] = useState(false)
+
+ return (
+
setSelectAct(!selectAct)}>
+
{title}
+
+ {option.map((el, idx) => (
+ -
+
+
+ ))}
+
+
+ )
+}
diff --git a/src/components/floor-plan/CanvasFrame.jsx b/src/components/floor-plan/CanvasFrame.jsx
new file mode 100644
index 00000000..5923888f
--- /dev/null
+++ b/src/components/floor-plan/CanvasFrame.jsx
@@ -0,0 +1,7 @@
+export default function CanvasFrame () {
+ return(
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/floor-plan/CanvasLayout.jsx b/src/components/floor-plan/CanvasLayout.jsx
new file mode 100644
index 00000000..5be6a114
--- /dev/null
+++ b/src/components/floor-plan/CanvasLayout.jsx
@@ -0,0 +1,45 @@
+'use client'
+
+import { useState } from "react"
+import CanvasFrame from "./CanvasFrame";
+
+export default function CanvasLayout () {
+ const [plans, setPlans] = useState([{ id: 0, name: 'Plan 1' }, { id: 1, name: 'Plan 2' }, { id: 2, name: 'Plan 3' }]);
+ const [idxNum, setIdxNum] = useState(null);
+
+ const onClickPlane = (num) => {
+ setIdxNum(num);
+ }
+
+ const handleDeletePlan = (e, id) => {
+ e.stopPropagation(); // 이벤트 버블링 방지
+ setPlans(plans.filter(plan => plan.id !== id)); // 삭제할 아이디와 다른 아이템만 남김
+ }
+
+ const addNewPlan = () => {
+ setPlans([...plans, { id: plans.length, name: `Plan ${plans.length + 1}` }]);
+ }
+
+ return(
+
+
+
+ {plans.map((plan, idx) => (
+
+ ))}
+
+
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/floor-plan/CanvasMenu.jsx b/src/components/floor-plan/CanvasMenu.jsx
new file mode 100644
index 00000000..4533747a
--- /dev/null
+++ b/src/components/floor-plan/CanvasMenu.jsx
@@ -0,0 +1,97 @@
+'use client'
+import { useState } from 'react'
+import MenuDepth01 from './MenuDepth01'
+import QSelectBox from '@/components/common/select/QSelectBox'
+
+export default function CanvasMenu({ setModalOpen }) {
+ const [menuNumber, setMenuNumber] = useState(null)
+ const [vertical, setVertical] = useState(true)
+ const SelectOption = [{ name: '瓦53A' }, { name: '瓦53A' }]
+ const onClickNav = (number) => {
+ setMenuNumber(number)
+ if (menuNumber === number) {
+ setMenuNumber(null)
+ }
+ }
+ return (
+
+
+
+ - onClickNav(0)}>
+
+
+ - onClickNav(1)}>
+
+
+ - onClickNav(2)}>
+
+
+ - onClickNav(3)}>
+
+
+ - onClickNav(4)}>
+
+
+ - onClickNav(5)}>
+
+
+ - onClickNav(6)}>
+
+
+
+
+
+
+
+
+
+
+ 垂直水平モード
+
+
+
+
+
+
+
+
+
+
+
+
+ 100%
+
+
+
+
+
+
+
+
+
+
+ {menuNumber === 0 && }
+ {menuNumber === 1 && }
+ {menuNumber === 2 && }
+ {menuNumber === 3 && }
+ {menuNumber === 4 && }
+ {menuNumber === 5 && }
+ {menuNumber === 6 && }
+
+
+ )
+}
diff --git a/src/components/floor-plan/FloorPlan.jsx b/src/components/floor-plan/FloorPlan.jsx
index 27e03cf6..fecffea7 100644
--- a/src/components/floor-plan/FloorPlan.jsx
+++ b/src/components/floor-plan/FloorPlan.jsx
@@ -1,7 +1,21 @@
+'use client'
+
+import CanvasMenu from '@/components/floor-plan/CanvasMenu'
+import CanvasLayout from '@/components/floor-plan/CanvasLayout'
+import SettingModal01 from '@/components/floor-plan/modal/settoing01/SettingModal01'
+import { useState } from 'react'
+
export default function FloorPlan() {
+ const [modalOpen, setModalOpen] = useState('option')
return (
<>
-
도면 작성 페이지
+
+
+
+
+ {modalOpen === 'option' && }
+
+
>
)
}
diff --git a/src/components/floor-plan/MenuDepth01.jsx b/src/components/floor-plan/MenuDepth01.jsx
new file mode 100644
index 00000000..90ba4e60
--- /dev/null
+++ b/src/components/floor-plan/MenuDepth01.jsx
@@ -0,0 +1,44 @@
+'use client'
+
+import { ToggleonMouse } from '@/components/header/Header'
+
+export default function MenuDepth01() {
+ return (
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+ - ToggleonMouse(e, 'add', 'ul')} onMouseLeave={(e) => ToggleonMouse(e, 'remove', 'ul')}>
+
+
+ - ToggleonMouse(e, 'add', 'ul')} onMouseLeave={(e) => ToggleonMouse(e, 'remove', 'ul')}>
+
+
+ - ToggleonMouse(e, 'add', 'ul')} onMouseLeave={(e) => ToggleonMouse(e, 'remove', 'ul')}>
+
+
+
+
+ )
+}
diff --git a/src/components/floor-plan/modal/settoing01/FirstOption.jsx b/src/components/floor-plan/modal/settoing01/FirstOption.jsx
new file mode 100644
index 00000000..e91f81ab
--- /dev/null
+++ b/src/components/floor-plan/modal/settoing01/FirstOption.jsx
@@ -0,0 +1,39 @@
+import { useRecoilState } from 'recoil'
+import { settingModalFirstOptionsState } from '@/store/settingAtom'
+
+export default function FirstOption() {
+ const [settingsModalOptions, setSettingModalOptions] = useRecoilState(settingModalFirstOptionsState)
+ const { option1, option2 } = settingsModalOptions
+ const onClickOption = (option) => {
+ option.selected = !option.selected
+
+ setSettingModalOptions({ option1, option2 })
+ }
+
+ return (
+ <>
+
+
※図面に表示する項目をクリックすると適用されます。
+
+ {settingsModalOptions?.option1?.map((item) => (
+
+ ))}
+
+
+
+
画面表示
+
+ {settingsModalOptions?.option2?.map((item) => (
+
+ ))}
+
+
+ >
+ )
+}
diff --git a/src/components/floor-plan/modal/settoing01/SecondOption.jsx b/src/components/floor-plan/modal/settoing01/SecondOption.jsx
new file mode 100644
index 00000000..5b417f2b
--- /dev/null
+++ b/src/components/floor-plan/modal/settoing01/SecondOption.jsx
@@ -0,0 +1,45 @@
+import { useRecoilState } from 'recoil'
+import { settingModalSecondOptionsState } from '@/store/settingAtom'
+
+export default function SecondOption() {
+ const [settingsModalOptions, setSettingModalOptions] = useRecoilState(settingModalSecondOptionsState)
+ const { option1, option2 } = settingsModalOptions
+ const onClickOption = (option) => {
+ option.selected = !option.selected
+
+ setSettingModalOptions({ option1: option1, option2: option2 })
+ }
+ return (
+ <>
+
+
フォントとサイズの変更
+
+ {settingsModalOptions.option1.map((item) => (
+
+ ))}
+
+
+
+
吸着範囲の設定
+
+ {settingsModalOptions.option2.map((item) => (
+
+ ))}
+
+
+
+
+
+
+ >
+ )
+}
diff --git a/src/components/floor-plan/modal/settoing01/SettingModal01.jsx b/src/components/floor-plan/modal/settoing01/SettingModal01.jsx
new file mode 100644
index 00000000..5a79c795
--- /dev/null
+++ b/src/components/floor-plan/modal/settoing01/SettingModal01.jsx
@@ -0,0 +1,44 @@
+'use client'
+
+import { useState } from 'react'
+import FirstOption from './FirstOption'
+import WithDraggable from '@/components/common/draggable/withDraggable'
+import SecondOption from '@/components/floor-plan/modal/settoing01/SecondOption'
+
+export default function SettingModal01({ modalOpen, setModalOpen }) {
+ const [buttonAct, setButtonAct] = useState(1)
+ const [close, setClose] = useState(false)
+ const HandleClickClose = () => {
+ setClose(true)
+ setTimeout(() => {
+ setModalOpen('')
+ setClose(false)
+ }, 180)
+ }
+
+ return (
+
+
+
+
Canvas設定
+
+
+
+
+
+
+
+
+ {buttonAct === 1 &&
}
+ {buttonAct === 2 &&
}
+
+
+
+ )
+}
diff --git a/src/components/header/Header.jsx b/src/components/header/Header.jsx
new file mode 100644
index 00000000..efb58a52
--- /dev/null
+++ b/src/components/header/Header.jsx
@@ -0,0 +1,117 @@
+'use client'
+import Link from 'next/link'
+import QSelectBox from '@/components/common/select/QSelectBox'
+import { usePathname } from 'next/navigation'
+
+export const ToggleonMouse = (e, act, target) => {
+ const listWrap = e.target.closest(target)
+ const ListItem = Array.from(listWrap.childNodes)
+ ListItem.forEach((el) => {
+ if (act === 'add') {
+ el.classList.add('mouse')
+ } else {
+ el.classList.remove('mouse')
+ }
+ })
+ if (act === 'add') {
+ e.target.parentElement.classList.remove('mouse')
+ }
+}
+
+export default function Header() {
+ const pathName = usePathname()
+ if (pathName.includes('login')) {
+ return null
+ }
+ const SelectOption = [{ name: 'オンライン保証シ' }, { name: 'ステム' }]
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/src/hooks/useCanvas.js b/src/hooks/useCanvas.js
index e6ae4dbf..044a5e58 100644
--- a/src/hooks/useCanvas.js
+++ b/src/hooks/useCanvas.js
@@ -4,7 +4,7 @@ import { fabric } from 'fabric'
import { actionHandler, anchorWrapper, polygonPositionHandler } from '@/util/canvas-util'
import { useRecoilState } from 'recoil'
-import { canvasSizeState, fontSizeState } from '@/store/canvasAtom'
+import { canvasSizeState, canvasState, fontSizeState } from '@/store/canvasAtom'
import { QLine } from '@/components/fabric/QLine'
import { QPolygon } from '@/components/fabric/QPolygon'
import { defineQLine } from '@/util/qline-utils'
@@ -14,7 +14,7 @@ import { useCanvasEvent } from '@/hooks/useCanvasEvent'
import { post } from '@/lib/Axios'
export function useCanvas(id) {
- const [canvas, setCanvas] = useState()
+ const [canvas, setCanvas] = useRecoilState(canvasState)
const [isLocked, setIsLocked] = useState(false)
const [history, setHistory] = useState([])
const [backImg, setBackImg] = useState()
diff --git a/src/hooks/useMode.js b/src/hooks/useMode.js
index dc3312d2..504724b6 100644
--- a/src/hooks/useMode.js
+++ b/src/hooks/useMode.js
@@ -14,25 +14,26 @@ import { useRecoilState, useRecoilValue } from 'recoil'
import {
canvasSizeState,
+ canvasState,
compassState,
drewRoofCellsState,
fontSizeState,
+ guideLineState,
+ horiGuideLinesState,
modeState,
+ objectPlacementModeState,
roofPolygonArrayState,
roofPolygonPatternArrayState,
roofState,
sortedPolygonArray,
templateTypeState,
- wallState,
- guideLineState,
- horiGuideLinesState,
vertGuideLinesState,
- objectPlacementModeState,
+ wallState,
} from '@/store/canvasAtom'
import { QLine } from '@/components/fabric/QLine'
import { fabric } from 'fabric'
import { QPolygon } from '@/components/fabric/QPolygon'
-import offsetPolygon, { inPolygon } from '@/util/qpolygon-utils'
+import offsetPolygon from '@/util/qpolygon-utils'
import { isObjectNotEmpty } from '@/util/common-utils'
import * as turf from '@turf/turf'
import { INPUT_TYPE, Mode } from '@/common/common'
@@ -43,7 +44,7 @@ export function useMode() {
const historyPoints = useRef([])
const historyLines = useRef([])
const startPoint = useRef()
- const [canvas, setCanvas] = useState(null)
+ const [canvas, setCanvas] = useRecoilState(canvasState)
const [zoom, setZoom] = useState(100)
const [fontSize] = useRecoilState(fontSizeState)
const [sortedArray, setSortedArray] = useRecoilState(sortedPolygonArray)
@@ -83,7 +84,6 @@ export function useMode() {
// return
// }
if (!canvas) return
- setCanvas(canvas)
canvas?.off('mouse:out', removeMouseLines)
canvas?.on('mouse:out', removeMouseLines)
canvas?.off('mouse:move')
@@ -685,7 +685,6 @@ export function useMode() {
mouseAndkeyboardEventClear()
addCommonMouseEvent()
setMode(mode)
- setCanvas(canvas)
// mode별 이벤트 변경
@@ -5150,7 +5149,6 @@ export function useMode() {
mode,
setMode,
changeMode,
- setCanvas,
handleClear,
zoomIn,
zoomOut,
diff --git a/src/lib/authActions.js b/src/lib/authActions.js
index 60fac21a..06c02ef0 100644
--- a/src/lib/authActions.js
+++ b/src/lib/authActions.js
@@ -27,6 +27,28 @@ export async function getSession() {
return session
}
+export async function setSession(data) {
+ const session = await getSession()
+
+ session.userId = data.userId
+ session.name = data.name
+ session.saleStoreId = data.saleStoreId
+ session.mail = data.mail
+ session.tel = data.tel
+ session.storeId = data.storeId
+ session.userNm = data.userNm
+ session.userNmKana = data.userNmKana
+ session.category = data.category
+ session.telNo = data.telNo
+ session.fax = data.fax
+ session.email = data.email
+ session.pwdInitYn = data.pwdInitYn
+ session.isLoggedIn = true
+ // console.log('session:', session)
+
+ await session.save()
+}
+
export async function login(formData) {
const session = await getSession()
diff --git a/src/lib/file.js b/src/lib/file.js
new file mode 100644
index 00000000..418fbe96
--- /dev/null
+++ b/src/lib/file.js
@@ -0,0 +1,22 @@
+'use server'
+import path from 'path'
+import multer from 'multer'
+
+export const upload = (files) => {
+ console.log(files)
+ const storage = multer.diskStorage({
+ destination: (req, file, callback) => {
+ const extension = path.extname(file.originalname)
+ const basename = path.basename(file.originalname, extension)
+ callback(null, `/public/upload/${basename}-${Date.now()}${extension}`)
+ },
+ filename: (req, file, callback) => {
+ callback(null, `${file.fieldname}-${Date.now()}${path.extname(file.originalname)}`)
+ }
+ })
+ const test = multer({
+ storage: storage
+ }).array(files.name, 5)
+
+ console.log(test)
+}
diff --git a/src/store/canvasAtom.js b/src/store/canvasAtom.js
index ae020901..44f29df5 100644
--- a/src/store/canvasAtom.js
+++ b/src/store/canvasAtom.js
@@ -1,5 +1,11 @@
import { atom } from 'recoil'
+export const canvasState = atom({
+ key: 'canvasState',
+ default: null,
+ dangerouslyAllowMutability: true,
+})
+
export const textState = atom({
key: 'textState',
default: 'test text',
diff --git a/src/store/settingAtom.js b/src/store/settingAtom.js
new file mode 100644
index 00000000..0ab99ea1
--- /dev/null
+++ b/src/store/settingAtom.js
@@ -0,0 +1,45 @@
+import { atom } from 'recoil'
+
+export const settingModalFirstOptionsState = atom({
+ key: 'settingModalFirstOptions',
+ default: {
+ option1: [
+ { id: 1, name: '割り当て表示', selected: false },
+ { id: 2, name: '実寸表示', selected: false },
+ { id: 3, name: '図面表示', selected: false },
+ { id: 4, name: '寸法表示なし', selected: false },
+ { id: 5, name: 'グリッド表示', selected: false },
+ { id: 6, name: '架台表示', selected: false },
+ { id: 7, name: '文字表示', selected: false },
+ { id: 8, name: '座標表示', selected: false },
+ { id: 9, name: '流れ方向表示', selected: false },
+ { id: 10, name: '図面切替表示', selected: false },
+ { id: 11, name: 'ü廊下寸法表示', selected: false },
+ ],
+ option2: [
+ { id: 1, name: 'ボーダーのみ', selected: false },
+ { id: 2, name: 'ラインハッチ', selected: false },
+ { id: 3, name: 'All painted', selected: false },
+ ],
+ },
+ dangerouslyAllowMutability: true,
+})
+
+export const settingModalSecondOptionsState = atom({
+ key: 'settingModalSecondOptions',
+ default: {
+ option1: [
+ { id: 1, name: '文字フォントの変更' },
+ { id: 2, name: 'フロー方向フォントの変更' },
+ { id: 3, name: '寸法フォントの変更' },
+ { id: 4, name: '回路番号フォントの変更' },
+ ],
+ option2: [
+ { id: 1, name: '極小', selected: false },
+ { id: 2, name: '牛', selected: false },
+ { id: 3, name: '中', selected: false },
+ { id: 4, name: 'ティーン', selected: false },
+ ],
+ },
+ dangerouslyAllowMutability: true,
+})
diff --git a/src/styles/_contents.scss b/src/styles/_contents.scss
new file mode 100644
index 00000000..b9dbe68e
--- /dev/null
+++ b/src/styles/_contents.scss
@@ -0,0 +1,455 @@
+// CanvasPage
+.canvas-wrap {
+ height: calc(100vh - 47px);
+ display: flex;
+ flex-direction: column;
+
+ .canvas-content {
+ flex: 1 1 auto;
+
+ .canvas-layout {
+ height: 100%;
+ }
+ }
+}
+
+// CanvasMenu
+.canvas-menu-wrap {
+ position: relative;
+ display: block;
+ width: 100%;
+ padding-bottom: 0;
+ background-color: #383838;
+ transition: padding .17s ease-in-out;
+
+ .canvas-menu-inner {
+ position: relative;
+ display: flex;
+ align-items: center;
+ padding: 0 40px 0 20px;
+ background-color: #2C2C2C;
+ z-index: 999;
+
+ .canvas-menu-list {
+ display: flex;
+ align-items: center;
+ height: 100%;
+
+ .canvas-menu-item {
+ display: flex;
+ align-items: center;
+ height: 100%;
+
+ button {
+ display: flex;
+ align-items: center;
+ font-size: 12px;
+ height: 100%;
+ color: #fff;
+ font-weight: 600;
+ padding: 15px 20px;
+ opacity: 0.55;
+ transition: all .17s ease-in-out;
+
+ .menu-icon {
+ display: block;
+ width: 16px;
+ height: 16px;
+ background-repeat: no-repeat;
+ background-position: center;
+ background-size: cover;
+ margin-right: 10px;
+
+ &.con00 {
+ background-image: url(/static/images/canvas/menu_icon00.svg);
+ }
+
+ &.con01 {
+ background-image: url(/static/images/canvas/menu_icon01.svg);
+ }
+
+ &.con02 {
+ background-image: url(/static/images/canvas/menu_icon02.svg);
+ }
+
+ &.con03 {
+ background-image: url(/static/images/canvas/menu_icon03.svg);
+ }
+
+ &.con04 {
+ background-image: url(/static/images/canvas/menu_icon04.svg);
+ }
+
+ &.con05 {
+ background-image: url(/static/images/canvas/menu_icon05.svg);
+ }
+
+ &.con06 {
+ background-image: url(/static/images/canvas/menu_icon06.svg);
+ }
+ }
+ }
+
+ &.active {
+ background-color: #383838;
+
+ button {
+ opacity: 1;
+ }
+ }
+ }
+ }
+
+ .canvas-side-btn-wrap {
+ display: flex;
+ align-items: center;
+ margin-left: auto;
+
+ .select-box {
+ width: 124px;
+ margin-right: 5px;
+
+ > div {
+ width: 100%;
+ }
+ }
+
+ .btn-from {
+ display: flex;
+ align-items: center;
+ gap: 5px;
+
+ button {
+ display: block;
+ width: 30px;
+ height: 30px;
+ border-radius: 2px;
+ background-color: #3D3D3D;
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: 15px 15px;
+ transition: all .17s ease-in-out;
+
+ &.btn01 {
+ background-image: url(../../public/static/images/canvas/side_icon01.svg);
+ }
+
+ &.btn02 {
+ background-image: url(../../public/static/images/canvas/side_icon02.svg);
+ }
+
+ &.btn03 {
+ background-image: url(../../public/static/images/canvas/side_icon03.svg);
+ }
+
+ &.btn04 {
+ background-image: url(../../public/static/images/canvas/side_icon04.svg);
+ }
+
+ &.btn05 {
+ background-image: url(../../public/static/images/canvas/side_icon05.svg);
+ }
+
+ &.btn06 {
+ background-image: url(../../public/static/images/canvas/side_icon06.svg);
+ }
+
+ &.btn07 {
+ background-image: url(../../public/static/images/canvas/side_icon07.svg);
+ }
+
+ &.btn08 {
+ background-image: url(../../public/static/images/canvas/side_icon08.svg);
+ }
+
+ &.btn09 {
+ background-image: url(../../public/static/images/canvas/side_icon09.svg);
+ }
+
+ &:hover {
+ background-color: #1083E3;
+ }
+
+ &.active {
+ background-color: #1083E3;
+ }
+ }
+ }
+
+ .vertical-horizontal {
+ display: flex;
+ min-width: 170px;
+ height: 28px;
+ margin: 0 5px;
+ border-radius: 2px;
+ background: #373737;
+ line-height: 28px;
+ overflow: hidden;
+
+ span {
+ padding: 0 10px;
+ font-size: 13px;
+ color: #fff;
+ }
+
+ button {
+ margin-left: auto;
+ height: 100%;
+ background-color: #4B4B4B;
+ font-size: 13px;
+ font-weight: 400;
+ color: #fff;
+ padding: 0 7.5px;
+ }
+ }
+
+ .size-control {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 10px;
+ background-color: #3D3D3D;
+ border-radius: 2px;
+ width: 100px;
+ height: 30px;
+ margin: 0 5px;
+
+ span {
+ font-size: 13px;
+ color: #fff;
+ }
+
+ .control-btn {
+ display: block;
+ width: 12px;
+ height: 12px;
+ background-repeat: no-repeat;
+ background-size: cover;
+ background-position: center;
+
+ &.minus {
+ background-image: url(../../public/static/images/canvas/minus.svg);
+ }
+
+ &.plus {
+ background-image: url(../../public/static/images/canvas/plus.svg);
+ }
+ }
+ }
+ }
+ }
+
+ .canvas-depth2-wrap {
+ position: absolute;
+ top: -100%;
+ left: 0;
+ background-color: #383838;
+ width: 100%;
+ height: 50px;
+ transition: all .17s ease-in-out;
+
+ .canvas-depth2-inner {
+ display: flex;
+ align-items: center;
+ padding: 0 40px;
+ height: 100%;
+
+ .canvas-depth2-list {
+ display: flex;
+ align-items: center;
+ height: 100%;
+
+ .canvas-depth2-item {
+ display: flex;
+ align-items: center;
+ margin-right: 26px;
+ height: 100%;
+
+ button {
+ position: relative;
+ opacity: 0.55;
+ color: #fff;
+ font-size: 12px;
+ font-weight: normal;
+ height: 100%;
+ padding-right: 12px;
+ }
+
+ &.active {
+ button {
+ opacity: 1;
+ font-weight: 600;
+
+ &:after {
+ content: '';
+ position: absolute;
+ top: 50%;
+ right: 0;
+ transform: translateY(-50%);
+ width: 5px;
+ height: 8px;
+ background: url(../../public/static/images/canvas/depth2-arr.svg) no-repeat center;
+ }
+ }
+ }
+ }
+ }
+
+ .canvas-depth2-btn-list {
+ display: flex;
+ align-items: center;
+ margin-left: auto;
+ height: 100%;
+
+ .depth2-btn-box {
+ display: flex;
+ align-items: center;
+ margin-right: 34px;
+ height: 100%;
+ transition: all .17s ease-in-out;
+
+ button {
+ position: relative;
+ font-size: 12px;
+ font-weight: 400;
+ height: 100%;
+ color: #fff;
+ padding-right: 12px;
+
+ &:after {
+ content: '';
+ position: absolute;
+ top: 50%;
+ right: 0;
+ transform: translateY(-50%);
+ width: 5px;
+ height: 8px;
+ background: url(../../public/static/images/canvas/depth2-arr.svg) no-repeat center;
+ }
+ }
+
+ &:last-child {
+ margin-right: 0;
+ }
+
+ &.mouse {
+ opacity: 0.55;
+ }
+ }
+ }
+ }
+
+ &.active {
+ top: 47px;
+ }
+ }
+
+ &.active {
+ padding-bottom: 50px;
+ }
+}
+
+// canvas-layout
+.canvas-layout {
+ .canvas-page-list {
+ display: flex;
+ background-color: #1C1C1C;
+ border-top: 1px solid #000;
+ width: 100%;
+
+ .canvas-plane-wrap {
+ display: flex;
+ align-items: center;
+ max-width: calc(100% - 45px);
+
+ .canvas-page-box {
+ display: flex;
+ align-items: center;
+ background-color: #1c1c1c;
+ padding: 9.6px 20px;
+ border-right: 1px solid #000;
+ min-width: 0;
+ transition: all .17s ease-in-out;
+
+ span {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ font-size: 12px;
+ font-family: 'Pretendard', sans-serif;
+ color: #AAA;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ }
+
+ .close {
+ flex: none;
+ display: block;
+ width: 7px;
+ height: 8px;
+ margin-left: 15px;
+ background: url(../../public/static/images/canvas/plan_close_gray.svg) no-repeat center;
+ background-size: cover;
+ }
+
+ &.on {
+ background-color: #fff;
+
+ span {
+ font-weight: 600;
+ color: #101010;
+ }
+
+ .close {
+ background: url(../../public/static/images/canvas/plan_close_black.svg) no-repeat center;
+ }
+
+ &:hover {
+ background-color: #fff;
+ }
+ }
+
+ &:hover {
+ background-color: #000;
+ }
+ }
+ }
+
+ .plane-add {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 45px;
+ padding: 13.5px 0;
+ background-color: #1C1C1C;
+ border-right: 1px solid #000;
+ transition: all .17s ease-in-out;
+
+ span {
+ display: block;
+ width: 9px;
+ height: 9px;
+ background: url(../../public/static/images/canvas/plane_add.svg) no-repeat center;
+ background-size: cover;
+ }
+
+ &:hover {
+ background-color: #000;
+ }
+ }
+ }
+}
+
+.canvas-frame {
+ position: relative;
+ height: calc(100% - 36.5px);
+
+ canvas {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ }
+}
\ No newline at end of file
diff --git a/src/styles/_fonts.scss b/src/styles/_fonts.scss
new file mode 100644
index 00000000..b1d16e89
--- /dev/null
+++ b/src/styles/_fonts.scss
@@ -0,0 +1,199 @@
+@font-face {
+ font-family: 'Noto Sans JP';
+ src: url('/fonts/NotoSansJP-ExtraBold.woff2') format('woff2'),
+ url('/fonts/NotoSansJP-ExtraBold.woff') format('woff');
+ font-weight: bold;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Noto Sans JP';
+ src: url('/fonts/NotoSansJP-Bold.woff2') format('woff2'),
+ url('/fonts/NotoSansJP-Bold.woff') format('woff');
+ font-weight: bold;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Noto Sans JP';
+ src: url('/fonts/NotoSansJP-Black.woff2') format('woff2'),
+ url('/fonts/NotoSansJP-Black.woff') format('woff');
+ font-weight: 900;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Noto Sans JP';
+ src: url('/fonts/NotoSansJP-ExtraLight.woff2') format('woff2'),
+ url('/fonts/NotoSansJP-ExtraLight.woff') format('woff');
+ font-weight: 200;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Noto Sans JP';
+ src: url('/fonts/NotoSansJP-Light.woff2') format('woff2'),
+ url('/fonts/NotoSansJP-Light.woff') format('woff');
+ font-weight: 300;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Noto Sans JP';
+ src: url('/fonts/NotoSansJP-Medium.woff2') format('woff2'),
+ url('/fonts/NotoSansJP-Medium.woff') format('woff');
+ font-weight: 500;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Noto Sans JP';
+ src: url('/fonts/NotoSansJP-Regular.woff2') format('woff2'),
+ url('/fonts/NotoSansJP-Regular.woff') format('woff');
+ font-weight: normal;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Noto Sans JP';
+ src: url('/fonts/NotoSansJP-SemiBold.woff2') format('woff2'),
+ url('/fonts/NotoSansJP-SemiBold.woff') format('woff');
+ font-weight: 600;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Noto Sans JP';
+ src: url('/fonts/NotoSansJP-Thin.woff2') format('woff2'),
+ url('/fonts/NotoSansJP-Thin.woff') format('woff');
+ font-weight: 100;
+ font-style: normal;
+ font-display: swap;
+}
+
+// pretendard
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/fonts/Pretendard-Bold.woff2') format('woff2'),
+ url('/fonts/Pretendard-Bold.woff') format('woff');
+ font-weight: bold;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/fonts/Pretendard-ExtraBold.woff2') format('woff2'),
+ url('/fonts/Pretendard-ExtraBold.woff') format('woff');
+ font-weight: bold;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/fonts/Pretendard-ExtraBold.woff2') format('woff2'),
+ url('/fonts/Pretendard-ExtraBold.woff') format('woff');
+ font-weight: bold;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/fonts/Pretendard-ExtraLight.woff2') format('woff2'),
+ url('/fonts/Pretendard-ExtraLight.woff') format('woff');
+ font-weight: 200;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/fonts/Pretendard-ExtraLight.woff2') format('woff2'),
+ url('/fonts/Pretendard-ExtraLight.woff') format('woff');
+ font-weight: 200;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/fonts/Pretendard-Light.woff2') format('woff2'),
+ url('/fonts/Pretendard-Light.woff') format('woff');
+ font-weight: 300;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/fonts/Pretendard-Light.woff2') format('woff2'),
+ url('/fonts/Pretendard-Light.woff') format('woff');
+ font-weight: 300;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/fonts/Pretendard-Medium.woff2') format('woff2'),
+ url('/fonts/Pretendard-Medium.woff') format('woff');
+ font-weight: 500;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/fonts/Pretendard-Medium.woff2') format('woff2'),
+ url('/fonts/Pretendard-Medium.woff') format('woff');
+ font-weight: 500;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/fonts/Pretendard-Regular.woff2') format('woff2'),
+ url('/fonts/Pretendard-Regular.woff') format('woff');
+ font-weight: normal;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/fonts/Pretendard-Black.woff2') format('woff2'),
+ url('/fonts/Pretendard-Black.woff') format('woff');
+ font-weight: 900;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/fonts/Pretendard-Black.woff2') format('woff2'),
+ url('/fonts/Pretendard-Black.woff') format('woff');
+ font-weight: 900;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/fonts/Pretendard-Bold.woff2') format('woff2'),
+ url('/fonts/Pretendard-Bold.woff') format('woff');
+ font-weight: bold;
+ font-style: normal;
+ font-display: swap;
+}
+
diff --git a/src/styles/_inputcommon.scss b/src/styles/_inputcommon.scss
new file mode 100644
index 00000000..97e5cc53
--- /dev/null
+++ b/src/styles/_inputcommon.scss
@@ -0,0 +1,35 @@
+.input-content{
+ max-width: 1600px;
+ margin: 0 auto;
+ padding-bottom: 100px;
+ .input-wrap{
+ padding: 50px 50px 0;
+ h1{
+ margin-bottom: 20px;
+ }
+ .form-btn{
+ button{
+ margin-right: 10px;
+ }
+ }
+ .form-select{
+ width: 168px;
+ > div{
+ width: 100%;
+ }
+ }
+ .form-datepicker{
+ div{
+ margin-bottom: 10px;
+ }
+ }
+ .form-Arrow-btn,
+ .form-Check-btn{
+ padding: 10px;
+ background-color: #272727;
+ > button{
+ margin-bottom: 10px;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/styles/_layout.scss b/src/styles/_layout.scss
new file mode 100644
index 00000000..e33d75ea
--- /dev/null
+++ b/src/styles/_layout.scss
@@ -0,0 +1,216 @@
+.wrap{
+ display: flex;
+ flex-direction: column;
+ min-width: 1600px;
+ min-height: 100vh;
+ overflow-x: hidden;
+}
+.content{
+ flex: 1 1 auto;
+ padding-top: 46px;
+}
+
+// header
+// nav item 공통
+@mixin navitem(){
+ position: relative;
+ display: flex;
+ align-items: center;
+ font-size: 14px;
+ color: #fff;
+ font-weight: 500;
+ height: 100%;
+ padding-right: 12px;
+ transition: color .17s ease-in-out;
+}
+header{
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ min-width: 1600px;
+ height: 46px;
+ background-color: #1C1C1C;
+ border-bottom: 1px solid #000;
+ z-index: 9999;
+ .header-inner{
+ display: flex;
+ align-items: center;
+ height: 100%;
+ padding: 0 40px;
+ .header-right{
+ display: flex;
+ height: 100%;
+ align-items: center;
+ .logo{
+ a{
+ display: block;
+ width: 232px;
+ height: 30px;
+ background: url(/static/images/common/Logo.svg)no-repeat center;
+ background-size: contain;
+ }
+ }
+ nav{
+ margin-left: 50px;
+ height: 100%;
+ .nav-list{
+ display: flex;
+ align-items: center;
+ height: 100%;
+ .nav-item{
+ position: relative;
+ margin-right: 62px;
+ height: 100%;
+ a{
+ @include navitem;
+ }
+ button{
+ @include navitem;
+ &:after{
+ content: '';
+ position: absolute;
+ top: 50%;
+ right: 0;
+ transform: translateY(-50%);
+ width: 6px;
+ height: 10px;
+ background: url(/static/images/common/nav-arr.svg)no-repeat center;
+ transition: all .17s ease-in-out;
+ }
+ }
+ &:last-child{
+ margin-right: 0;
+ }
+ .nav-depth2{
+ position: absolute;
+ top: calc(100% - 2px);
+ left: 50%;
+ transform: translateX(-50%);
+ min-width: 100px;
+ background-color: #1C1C1C;
+ border: 1px solid #464646;
+ padding: 24px;
+ opacity: 0;
+ visibility: hidden;
+ transition: all .17s ease-in-out;
+ .nav-depth2-item{
+ margin-bottom: 10px;
+ transition: all .17s ease-in-out;
+ a{
+ font-size: 13px;
+ font-weight: normal;
+ white-space: nowrap;
+ }
+ &:last-child{
+ margin-bottom: 0;
+ }
+ &.mouse{
+ opacity: 0.55;
+ }
+ }
+ &::before{
+ content: '';
+ position: absolute;
+ top: -5px;
+ left: 50%;
+ transform: translateX(-50%) rotate(45deg);
+ width: 8px;
+ height: 8px;
+ background-color: #1c1c1c;
+ border-top: 1px solid #464646;
+ border-left: 1px solid #464646;
+ }
+ }
+ &.mouse{
+ > a{
+ color: rgba(255, 255, 255, 0.30);
+ }
+ > button{
+ color: rgba(255, 255, 255, 0.30);
+ &:after{
+ opacity: 0.3;
+ }
+ }
+ }
+ &:hover{
+ .nav-depth2{
+ opacity: 1;
+ visibility: visible;
+ }
+ > button{
+ &:after{
+ transform: translateY(-50%) rotate(90deg);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ .header-left{
+ margin-left: auto;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ .profile-box{
+ position: relative;
+ padding-left: 30px;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ margin-right: 20px;
+ cursor: pointer;
+ .profile{
+ font-size: 13px;
+ font-weight: normal;
+ color: #fff;
+ }
+ &::after{
+ content: '';
+ position: absolute;
+ top: 50%;
+ transform: translateY(-50%);
+ left: 0;
+ width: 24px;
+ height: 24px;
+ background: url(/static/images/common/profile_icon.svg)no-repeat center;
+ background-size: cover;
+ }
+ }
+ .sign-out-box{
+ position: relative;
+ padding-left: 30px;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ margin-right: 20px;
+ cursor: pointer;
+ .sign-out{
+ font-size: 13px;
+ font-weight: normal;
+ color: #fff;
+ }
+ &::after{
+ content: '';
+ position: absolute;
+ top: 50%;
+ transform: translateY(-50%);
+ left: 0;
+ width: 24px;
+ height: 24px;
+ background: url(../../public/static/images/common/signout_icon.svg)no-repeat center;
+ background-size: cover;
+ }
+ }
+ .select-box{
+ min-width: 165px;
+ margin-right: 8px;
+ >div{
+ width: 100%;
+ }
+ }
+ }
+ }
+}
+
diff --git a/src/styles/_modal.scss b/src/styles/_modal.scss
new file mode 100644
index 00000000..05b0e4a9
--- /dev/null
+++ b/src/styles/_modal.scss
@@ -0,0 +1,91 @@
+@keyframes mountpop{
+ from{opacity: 0; scale: 0.95;}
+ to{opacity: 1; scale: 1;}
+}
+@keyframes unmountpop{
+ from{opacity: 1; scale: 1;}
+ to{opacity: 0; scale: 0.95;}
+}
+
+.modal-pop-wrap{
+ position: fixed;
+ top: 200px;
+ right: 100px;
+ width: 100%;
+ min-width: 380px;
+ max-width: fit-content;
+ height: -webkit-fit-content;
+ height: -moz-fit-content;
+ height: fit-content;
+ border: 1px solid #000;
+ border-radius: 4px;
+ background-color: #272727;
+ z-index: 9999999;
+ &.sm{
+ max-width: 450px;
+ }
+ &.mount{
+ animation: mountpop .17s ease-in-out forwards;
+ }
+ &.unmount{
+ animation: unmountpop .17s ease-in-out forwards;
+ }
+}
+.modal-head{
+ display: flex;
+ align-items: center;
+ padding: 10px 24px;
+ background-color: #000;
+ cursor: pointer;
+ h1.title{
+ font-size: 13px;
+ color: #fff;
+ font-weight: 700;
+ }
+ .modal-close{
+ margin-left: auto;
+ color: #fff;
+ text-indent: -999999999px;
+ width: 10px;
+ height: 10px;
+ background: url(../../public/static/images/canvas/modal_close.svg)no-repeat center;
+ }
+}
+.modal-body{
+ padding: 15px;
+ .modal-btn-wrap{
+ display: flex;
+ align-items: center;
+ gap: 5px;
+ button{
+ flex: 1;
+ }
+ }
+ .modal-check-btn-wrap{
+ margin-top: 15px;
+ .check-wrap-title{
+ font-size: 12px;
+ color: #fff;
+ font-weight: 600;
+ &.light{
+ font-weight: 400;
+ }
+ }
+ .flex-check-box{
+ display: flex;
+ flex-wrap: wrap;
+ gap: 10px;
+ margin-top: 15px;
+ &.for2{
+ button{
+ width: calc(50% - 5px);
+ }
+ }
+ &.for-line{
+ button{
+ flex: 1;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/styles/_reset.scss b/src/styles/_reset.scss
new file mode 100644
index 00000000..7dc13a69
--- /dev/null
+++ b/src/styles/_reset.scss
@@ -0,0 +1,431 @@
+* {
+ -webkit-text-size-adjust: none;
+ -moz-text-size-adjust: none;
+ -ms-text-size-adjust: none;
+ text-size-adjust: none;
+ box-sizing: content-box
+}
+
+*, ::after, ::before {
+ box-sizing: border-box;
+}
+
+html, body {
+ width: 100%;
+ height: 100%;
+ font-size: 16px;
+}
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed,
+figure, figcaption, footer, header, hgroup,
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font: inherit;
+ vertical-align: baseline;
+ font-family: 'Noto Sans JP', sans-serif;
+}
+
+/* HTML5 display-role reset for older browsers */
+article, aside, details, figcaption, figure,
+footer, header, hgroup, menu, nav, section {
+ display: block;
+}
+
+body {
+ line-height: 1.4;
+}
+
+body:first-of-type caption {
+ display: none;
+}
+
+ol, ul {
+ list-style: none;
+}
+
+blockquote, q {
+ quotes: none;
+}
+
+blockquote:before, blockquote:after,
+q:before, q:after {
+ content: '';
+ content: none;
+}
+
+table {
+ border-collapse: separate;
+ border-spacing: 0;
+ border: 0 none;
+}
+
+caption, th, td {
+ text-align: left;
+ font-weight: normal;
+ border: 0;
+}
+
+a {
+ cursor: pointer;
+ color: #000;
+}
+
+a, a:hover, a:active {
+ text-decoration: none;
+ -webkit-tap-highlight-color: transparent;
+}
+
+/*form_style*/
+input, select, textarea, button, a, label {
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+
+button, input[type=text], input[type=button] {
+ -webkit-appearance: none;
+ -webkit-border-radius: 0;
+ -webkit-appearance: none;
+ appearance: none;
+ border-radius: 0
+}
+
+input[type=checkbox], input[type=radio] {
+ box-sizing: border-box;
+ padding: 0;
+}
+
+input, select, button {
+ border: 0 none;
+ outline: none;
+ margin: 0;
+}
+
+select {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ appearance: none;
+}
+
+select::-ms-expand {
+ display: none;
+}
+
+::-webkit-input-placeholder {
+ line-height: 1;
+ font-weight: 300;
+ font-size: 0.938rem;
+ letter-spacing: -0.6px;
+ color: #8b8b8b;
+}
+
+.log-box ::-webkit-input-placeholder {
+ color: #8b8b8b;
+}
+
+button {
+ background: transparent;
+ font-family: 'Noto Sans JP', sans-serif;
+ border: none;
+ padding: 0;
+ margin: 0;
+ line-height: 1.4;
+ color: inherit;
+ outline: none;
+ cursor: pointer;
+}
+
+
+// button
+.btn-frame {
+ display: inline-block;
+ padding: 0 10px;
+ height: 34px;
+ line-height: 34px;
+ border-radius: 2px;
+ color: #fff;
+ font-size: 12px;
+ font-weight: 400;
+ border: 1px solid #000;
+ text-align: center;
+ font-family: 'Pretendard', sans-serif;
+ transition: all .17s ease-in-out;
+ cursor: pointer;
+
+ &.block {
+ width: 100%;
+ }
+
+ &.small {
+ font-family: 'Noto Sans JP', sans-serif;
+ height: 30px;
+ line-height: 30px;
+ font-size: 13px;
+ }
+
+ &.deepgray {
+ background-color: #2C2C2C;
+ border: 1px solid #484848;
+ }
+
+ &.gray {
+ background-color: #3C3C3C;
+ border: 1px solid #545454;
+ }
+
+ &.dark {
+ background-color: #1C1C1C;
+ border: 1px solid #484848;
+ }
+
+ &.modal {
+ background-color: #272727;
+ border: 1px solid #484848;
+ color: #aaa;
+
+ &:hover {
+ background-color: #1083E3;
+ border: 1px solid #1083E3;
+ color: #fff;
+ font-weight: 500;
+ }
+ }
+
+ &.act {
+ background-color: #1083E3;
+ border: 1px solid #1083E3;
+ color: #fff;
+ font-weight: 500;
+ }
+
+ &.block {
+ display: block;
+ width: 100%;
+ }
+}
+
+// select
+.sort-select {
+ position: relative;
+ display: inline-block;
+ min-width: 100px;
+ height: 30px;
+ line-height: 30px;
+ padding: 0 10px;
+ background-color: #373737;
+ border: 1px solid #3F3F3F;
+ border-radius: 2px;
+ border-top-left-radius: 2px;
+ color: #fff;
+ cursor: pointer;
+
+ p {
+ font-size: 13px;
+ color: #fff;
+ height: 100%;
+ }
+
+ .select-item-wrap {
+ position: absolute;
+ top: 100%;
+ left: -1px;
+ clip-path: inset(0 0 100% 0);
+ width: calc(100% + 2px);
+ padding: 8px 0;
+ background-color: #373737;
+ border: 1px solid #3F3F3F;
+ border-radius: 2px;
+ transition: all 0.17s ease-in-out;
+ visibility: hidden;
+
+ .select-item {
+ display: flex;
+ align-items: center;
+ padding: 8px 20px;
+ line-height: 1.4;
+ transition: all .17s ease-in-out;
+
+ button {
+ font-size: 12px;
+ color: #fff;
+ line-height: 1.4;
+ }
+
+ &:hover {
+ background-color: #2C2C2C;
+ }
+ }
+ }
+
+ &::after {
+ content: '';
+ position: absolute;
+ top: 50%;
+ right: 7px;
+ transform: translateY(-50%);
+ width: 10px;
+ height: 6px;
+ background: url(/static/images/common/select-arr.svg) no-repeat center;
+ background-size: cover;
+ transition: all .17s ease-in-out;
+ }
+
+ &.active {
+ .select-item-wrap {
+ clip-path: inset(0 0 0 0);
+ visibility: visible;
+ }
+
+ &:after {
+ transform: translateY(-50%) rotate(-180deg);
+ }
+ }
+}
+
+// input
+input[type=text] {
+ &.input-origin {
+ display: inline-block;
+ height: 30px;
+ line-height: 30px;
+ border-radius: 2px;
+ background-color: #313131;
+ color: #fff;
+ font-size: 12px;
+ font-weight: 500;
+ font-family: 'Pretendard', sans-serif;
+ padding: 0 10px;
+
+ &::placeholder {
+ font-size: 12px;
+ }
+ }
+}
+
+// date-picker
+.single-date {
+ input {
+ border-radius: 2px;
+ color: #fff;
+ font-size: 12px;
+ font-family: 'Pretendard', sans-serif;
+ background-color: #313131;
+ }
+}
+
+.range-date {
+ input {
+ border-radius: 2px;
+ color: #fff;
+ font-size: 12px;
+ font-family: 'Pretendard', sans-serif;
+ background-color: #313131;
+ }
+
+ .react-datepicker__input-container {
+ button {
+ &:after {
+ display: none;
+ }
+ }
+ }
+}
+
+// check-btn
+.check-btn {
+ display: flex;
+ align-items: center;
+ height: 30px;
+ background-color: #3A3A3A;
+ border-radius: 3px;
+ transition: all .17s ease-in-out;
+
+ .check-area {
+ flex: none;
+ width: 30px;
+ height: 100%;
+ border-right: 1px solid #272727;
+ background: url(../../public/static/images/canvas/check-grey.svg) no-repeat center;
+ background-size: 11px 9px;
+ }
+
+ .title-area {
+ padding: 0 10px;
+ font-size: 12px;
+ color: #898989;
+ font-weight: 400;
+ }
+
+ &.block {
+ width: 100%;
+ }
+
+ &:hover,
+ &.act {
+ background-color: #fff;
+
+ .check-area {
+ border-right: 1px solid #101010;
+ background: url(../../public/static/images/canvas/check-black.svg) no-repeat center;
+ }
+
+ .title-area {
+ color: #101010;
+ font-weight: 600;
+ }
+ }
+}
+
+// arr-btn
+.arr-btn {
+ display: block;
+ height: 30px;
+ border-radius: 3px;
+ background-color: #3A3A3A;
+ padding: 0 11px;
+ text-align: left;
+ transition: all .17s ease-in-out;
+
+ span {
+ position: relative;
+ font-size: 12px;
+ color: #898989;
+ font-weight: 400;
+ padding-right: 15px;
+
+ &:after {
+ content: '';
+ position: absolute;
+ top: 50%;
+ right: 0;
+ transform: translateY(-50%);
+ width: 5px;
+ height: 8px;
+ background: url(../../public/static/images/canvas/arr_btn_ico.svg) no-repeat center;
+ }
+ }
+
+ &:hover,
+ &.act {
+ background-color: #fff;
+
+ span {
+ color: #101010;
+ font-weight: 500;
+
+ &:after {
+ background: url(../../public/static/images/canvas/arr_btn_ico_black.svg) no-repeat center;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/styles/common.scss b/src/styles/common.scss
new file mode 100644
index 00000000..8152784c
--- /dev/null
+++ b/src/styles/common.scss
@@ -0,0 +1,2 @@
+@import 'fonts.scss';
+@import 'reset.scss';
\ No newline at end of file
diff --git a/src/styles/style.scss b/src/styles/style.scss
index 862bf204..67e19244 100644
--- a/src/styles/style.scss
+++ b/src/styles/style.scss
@@ -1,18 +1,3 @@
-@import '_test.scss';
-@import 'react-toastify/dist/ReactToastify.css';
-
-body {
- padding: 0;
- margin: 0;
- font-family: -apple-system, RoomNo, sans-serif;
-}
-
-.font-test {
- font-family: 'RoomNo';
-}
-
-@font-face {
- font-family: 'RoomNo';
- font-weight: 200;
- src: url('/fonts/Room No.703.ttf') format('truetype');
-}
+@import '_layout.scss';
+@import '_contents.scss';
+@import '_modal.scss';
\ No newline at end of file
diff --git a/yarn.lock b/yarn.lock
index ed3490ac..62434324 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4107,7 +4107,7 @@ buffer@^6.0.3:
busboy@1.6.0:
version "1.6.0"
- resolved "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz"
+ resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893"
integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==
dependencies:
streamsearch "^1.1.0"
@@ -4161,7 +4161,7 @@ client-only@0.0.1, client-only@^0.0.1:
resolved "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz"
integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==
-clsx@^1.2.1:
+clsx@^1.1.1, clsx@^1.2.1:
version "1.2.1"
resolved "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz"
integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==
@@ -5520,6 +5520,14 @@ react-hook-form@^7.53.0:
resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.53.0.tgz#3cf70951bf41fa95207b34486203ebefbd3a05ab"
integrity sha512-M1n3HhqCww6S2hxLxciEXy2oISPnAzxY7gvwVPrtlczTM/1dDadXgUxDpHMrMTblDOcm/AXtXxHwZ3jpg1mqKQ==
+react-draggable@^4.4.6:
+ version "4.4.6"
+ resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.4.6.tgz#63343ee945770881ca1256a5b6fa5c9f5983fe1e"
+ integrity sha512-LtY5Xw1zTPqHkVmtM3X8MUOxNDOUhv/khTgBgrUvwaS064bwVvxT+q5El0uUFNx5IEPKXuRejr7UqLwBIg5pdw==
+ dependencies:
+ clsx "^1.1.1"
+ prop-types "^15.8.1"
+
react-icons@^5.3.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-5.3.0.tgz#ccad07a30aebd40a89f8cfa7d82e466019203f1c"