>
)
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 7b7cc48..ac97ef3 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,43 +1,10 @@
-import Link from 'next/link'
-import User from '@/components/User'
+import Main from '@/components/ui/Main'
export default async function Home() {
return (
<>
-
-
Index
-
-
-
- Zustand Counter Example
-
-
-
-
-
- Session Login Example
-
-
-
-
-
- 적합성 예제
-
-
-
-
-
- PDF 다운로드
-
-
-
-
-
- 조사 매물
-
-
-
-
+
+
>
)
diff --git a/src/app/pdf-download/page.tsx b/src/app/pdf-download/page.tsx
deleted file mode 100644
index a971c31..0000000
--- a/src/app/pdf-download/page.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import PdfDownloadNew from '@/components/PdfDownloadNew'
-
-export default function page() {
- return (
- <>
-
PDF 다운로드
-
- >
- )
-}
diff --git a/src/app/suitable/[slug]/page.tsx b/src/app/suitable/[slug]/page.tsx
deleted file mode 100644
index 6c1959a..0000000
--- a/src/app/suitable/[slug]/page.tsx
+++ /dev/null
@@ -1,12 +0,0 @@
-import SuitableDetails from '@/components/SuitableDetails'
-
-export default async function page({ params }: { params: Promise<{ slug: string }> }) {
- const { slug } = await params
- console.log('🚀 ~ page ~ slug:', slug)
- return (
- <>
-
Suitable Details
-
- >
- )
-}
diff --git a/src/app/suitable/page.tsx b/src/app/suitable/page.tsx
index 9bd4694..10e60d6 100644
--- a/src/app/suitable/page.tsx
+++ b/src/app/suitable/page.tsx
@@ -1,13 +1,7 @@
-import Suitable from '@/components/Suitable'
-import SuitableSearch from '@/components/SuitableSearch'
-
-export default function suitablePage() {
+export default function page() {
return (
<>
-
-
- {/* 최초 한번 밀어넣음 */}
- {/*
*/}
+
지붕재 적합성
>
)
}
diff --git a/src/app/survey-sale/@navTab/default.tsx b/src/app/survey-sale/@navTab/default.tsx
new file mode 100644
index 0000000..6fefef5
--- /dev/null
+++ b/src/app/survey-sale/@navTab/default.tsx
@@ -0,0 +1,5 @@
+import NavTab from '@/components/survey-sale/common/NavTab'
+
+export default function page() {
+ return
+}
diff --git a/src/app/survey-sale/[id]/page.tsx b/src/app/survey-sale/[id]/page.tsx
new file mode 100644
index 0000000..52202ca
--- /dev/null
+++ b/src/app/survey-sale/[id]/page.tsx
@@ -0,0 +1,11 @@
+import DataTable from '@/components/survey-sale/detail/DataTable'
+import DetailForm from '@/components/survey-sale/detail/DetailForm'
+
+export default function page() {
+ return (
+ <>
+
+
+ >
+ )
+}
diff --git a/src/app/survey-sale/basic-info/page.tsx b/src/app/survey-sale/basic-info/page.tsx
new file mode 100644
index 0000000..20cbeb8
--- /dev/null
+++ b/src/app/survey-sale/basic-info/page.tsx
@@ -0,0 +1,9 @@
+import BasicForm from '@/components/survey-sale/detail/BasicForm'
+
+export default function page() {
+ return (
+ <>
+
+ >
+ )
+}
diff --git a/src/app/survey-sale/layout.tsx b/src/app/survey-sale/layout.tsx
new file mode 100644
index 0000000..c4e7854
--- /dev/null
+++ b/src/app/survey-sale/layout.tsx
@@ -0,0 +1,19 @@
+import { ReactNode } from 'react'
+
+interface SurveySaleLayoutProps {
+ children: ReactNode
+ navTab: ReactNode
+}
+
+export default function layout({ children, navTab }: SurveySaleLayoutProps) {
+ return (
+ <>
+
+
+ {navTab}
+ {children}
+
+
+ >
+ )
+}
diff --git a/src/app/survey-sale/page.tsx b/src/app/survey-sale/page.tsx
new file mode 100644
index 0000000..fc6e6a3
--- /dev/null
+++ b/src/app/survey-sale/page.tsx
@@ -0,0 +1,11 @@
+import ListTable from '@/components/survey-sale/list/ListTable'
+import SearchForm from '@/components/survey-sale/list/SearchForm'
+
+export default function page() {
+ return (
+ <>
+
+
+ >
+ )
+}
diff --git a/src/app/survey-sale/roof-info/page.tsx b/src/app/survey-sale/roof-info/page.tsx
new file mode 100644
index 0000000..2bdfea5
--- /dev/null
+++ b/src/app/survey-sale/roof-info/page.tsx
@@ -0,0 +1,9 @@
+import RoofInfoForm from '@/components/survey-sale/detail/RoofInfoForm'
+
+export default function page() {
+ return (
+ <>
+
+ >
+ )
+}
diff --git a/src/app/survey-sales/page.tsx b/src/app/survey-sales/page.tsx
deleted file mode 100644
index 6671ce4..0000000
--- a/src/app/survey-sales/page.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import SurveySales from '@/components/SurveySales'
-
-export default function page() {
- return (
- <>
-
조사 매물 정보
-
- >
- )
-}
diff --git a/src/components/Counter.tsx b/src/components/Counter.tsx
deleted file mode 100644
index 0808d41..0000000
--- a/src/components/Counter.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-'use client'
-
-import { useCountStore } from '@/store/counter'
-
-export default function Counter() {
- const { count, increment, decrement, paramSetting, resetCount } = useCountStore()
-
- return (
-
-
{count}
-
-
- -
-
-
- +
-
-
-
- paramSetting({ count: 500 })}>
- 임의 숫자
-
-
-
-
- 리셋
-
-
-
- )
-}
diff --git a/src/components/Login.tsx b/src/components/Login.tsx
index 4efa60b..8f6e373 100644
--- a/src/components/Login.tsx
+++ b/src/components/Login.tsx
@@ -1,79 +1,48 @@
'use client'
-import { userApi } from '@/api/user'
-import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
-import { AxiosError } from 'axios'
-import { useRouter } from 'next/navigation'
import { useState } from 'react'
export default function Login() {
- const [username, setUsername] = useState('')
- const [password, setPassword] = useState('')
- const [isLogin, setIsLogin] = useState(false)
- const router = useRouter()
-
- const { data, error, isPending } = useQuery({
- queryKey: ['login-user'],
- queryFn: async () => {
- try {
- const result = await userApi.getUser({ username, password })
- router.push('/')
- return result
- } catch (error: unknown) {
- if (error instanceof AxiosError) {
- console.log('🚀 ~ handleLogin ~ error:', error.response?.data?.error)
- setUsername('')
- setPassword('')
- setIsLogin(false)
- }
- throw error
- }
- },
- enabled: isLogin,
- retry: false,
- staleTime: 0,
- })
-
- const handleLogin = async () => {
- console.log('🚀 ~ Login ~ username:', username)
- console.log('🚀 ~ Login ~ password:', password)
-
- setIsLogin(true)
- }
-
- const queryClient = useQueryClient()
- const { mutate: createUser } = useMutation({
- mutationFn: userApi.create,
- onSuccess: () => {
- queryClient.invalidateQueries({ queryKey: ['user-list'] })
- },
- })
+ const [pwShow, setPwShow] = useState(false) //비밀번호 보이기 숨기기
return (
<>
-
-
setUsername(e.target.value)}
- />
+
+
+
+
+
+ setPwShow(!pwShow)}>
+
+
+
+
+
+
+
+ お問い合わせ
+
+
-
- setPassword(e.target.value)}
- />
-
-
- Login
-
>
)
}
diff --git a/src/components/PdfDownloadNew.tsx b/src/components/PdfDownloadNew.tsx
deleted file mode 100644
index e7d8b96..0000000
--- a/src/components/PdfDownloadNew.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-'use client'
-
-import { useRef } from 'react'
-import generatePDF, { usePDF } from 'react-to-pdf'
-
-export default function PdfDownloadNew() {
- const { toPDF, targetRef } = usePDF({ filename: 'page.pdf' })
- const myTargetRef = useRef(null)
-
- return (
-
-
toPDF()}>Download PDF
-
Content to be generated to PDF
-
generatePDF(myTargetRef, { filename: 'mypage.pdf' })}>Download PDF
-
-
Hello
-
-
- )
-}
diff --git a/src/components/Suitable.tsx b/src/components/Suitable.tsx
deleted file mode 100644
index e21b4d4..0000000
--- a/src/components/Suitable.tsx
+++ /dev/null
@@ -1,69 +0,0 @@
-'use client'
-
-import { useSuitableStore } from '@/store/useSuitableStore'
-import { useQuery, useQueryClient } from '@tanstack/react-query'
-import { useRouter } from 'next/navigation'
-import type { Suitable as SuitableType } from '@/api/suitable'
-
-export default function Suitable() {
- const router = useRouter()
- const queryClient = useQueryClient()
- const { selectedItems, addSelectedItem, removeSelectedItem } = useSuitableStore()
-
- const handleItemClick = (item: SuitableType) => {
- if (!item.id) return // 초기 데이터 import 때문에 Suitable.id가 optional 타입이라서 방어 처리 추가
- selectedItems.some((selected) => selected.id === item.id) ? removeSelectedItem(item.id) : addSelectedItem(item)
- }
-
- const { data: suitableList, isLoading } = useQuery
({
- queryKey: ['suitables', 'search'],
- queryFn: async () => {
- const data = queryClient.getQueryData(['suitables', 'search']) as SuitableType[]
- return data ?? []
- },
- enabled: false,
- })
-
- if (isLoading || !suitableList || suitableList.length === 0) {
- return Loading...
- }
-
- return (
- <>
- Suitable
- {
- router.push('/')
- }}
- >
- HOME
-
-
-
선택된 아이템
- {selectedItems.length > 0 ? (
- selectedItems.map((item) => (
-
handleItemClick(item)}>
- {item.product_name}
-
- ))
- ) : (
-
선택된 아이템이 없습니다.
- )}
-
-
-
-
데이터 목록
- {suitableList ? (
- suitableList.map((item: SuitableType) => (
-
handleItemClick(item)}>
- {item.product_name}
-
- ))
- ) : (
-
검색 결과가 없습니다.
- )}
-
- >
- )
-}
diff --git a/src/components/SuitableCreateBtn.tsx b/src/components/SuitableCreateBtn.tsx
deleted file mode 100644
index bf31aac..0000000
--- a/src/components/SuitableCreateBtn.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-'use client'
-
-import { suitableApi } from '@/api/suitable'
-import { useMutation, useQueryClient } from '@tanstack/react-query'
-
-export default function SuitableCreateBtn() {
- const queryClient = useQueryClient()
-
- const {
- mutate: createSuitable,
- isPending,
- error,
- } = useMutation({
- mutationFn: suitableApi.create,
- onSuccess: () => {
- queryClient.invalidateQueries({ queryKey: ['suitable-list'] })
- },
- })
-
- return (
- <>
-
- createSuitable()}>
- suitable create!!
-
-
- >
- )
-}
diff --git a/src/components/SuitableDetails.tsx b/src/components/SuitableDetails.tsx
deleted file mode 100644
index 748c28f..0000000
--- a/src/components/SuitableDetails.tsx
+++ /dev/null
@@ -1,71 +0,0 @@
-'use client'
-
-import { suitableApi } from '@/api/suitable'
-import { useQuery } from '@tanstack/react-query'
-import generatePDF, { usePDF, Options } from 'react-to-pdf'
-import PDFContent from './SuitablePdf'
-
-const pdfOptions: Options = {
- filename: 'page.pdf',
- method: 'save',
- page: { format: 'a4', margin: 10 },
- overrides: {
- pdf: {
- compress: true,
- },
- },
-}
-
-export default function SuitableDetails({ roofMaterial }: { roofMaterial: string }) {
- const { data, isLoading } = useQuery({
- queryKey: ['suitable-details'],
- queryFn: () => suitableApi.getDetails(roofMaterial),
- staleTime: 0,
- enabled: !!roofMaterial,
- })
-
- const { toPDF, targetRef } = usePDF({ ...pdfOptions, method: 'open' })
-
- if (isLoading) {
- return Loading...
- }
-
- return (
- <>
- toPDF()}>
- OPEN PDF
-
- generatePDF(targetRef, pdfOptions)}
- >
- SAVE PDF
-
- {/* Download PDF */}
- {/* */}
-
-
Searched Roof Material: {decodeURIComponent(roofMaterial as string)}
- {data &&
- data.map((item) => (
-
-
-
product_name: {item.product_name}
-
manufacturer: {item.manufacturer}
-
roof_material: {item.roof_material}
-
shape: {item.shape}
-
support_roof_tile: {item.support_roof_tile}
-
support_roof_bracket: {item.support_roof_bracket}
-
yg_anchor: {item.yg_anchor}
-
- ))}
-
- {/*
*/}
-
- >
- )
-}
diff --git a/src/components/SuitableSearch.tsx b/src/components/SuitableSearch.tsx
deleted file mode 100644
index 4e3aa13..0000000
--- a/src/components/SuitableSearch.tsx
+++ /dev/null
@@ -1,88 +0,0 @@
-'use client'
-
-import { useEffect, useState } from 'react'
-import { useRouter } from 'next/navigation'
-import { useQuery } from '@tanstack/react-query'
-import { useSuitable } from '@/hooks/useSuitable'
-import Link from 'next/link'
-
-export default function SuitableSearch() {
- const router = useRouter()
- const [selectedCategory, setSelectedCategory] = useState
('')
- const [searchValue, setSearchValue] = useState('')
- const { getCategories, getSuitables } = useSuitable()
-
- const { data: categories } = useQuery({
- queryKey: ['categories'],
- queryFn: getCategories,
- staleTime: 1000 * 60 * 60, // 60분
- })
-
- const { data: suitableList } = useQuery({
- queryKey: ['suitables', 'list'],
- queryFn: async () => await getSuitables(),
- staleTime: 1000 * 60 * 10, // 10분
- gcTime: 1000 * 60 * 10, // 10분
- })
-
- const { data: suitableSearch, refetch: refetchBySearch } = useQuery({
- queryKey: ['suitables', 'search'],
- queryFn: async () => {
- // api를 호출하는 검색 방법
- // return await updateSearchResults(selectedCategory || undefined, searchValue || undefined)
- // useQuery 캐시 데이터를 사용하는 검색 방법
- return (
- suitableList?.filter((item) => {
- const categoryMatch = !selectedCategory || item.roof_material === selectedCategory
- const searchMatch = !searchValue || item.product_name.includes(searchValue)
- return categoryMatch && searchMatch
- }) ?? []
- )
- },
- staleTime: 1000 * 60 * 10,
- gcTime: 1000 * 60 * 10,
- enabled: false,
- })
-
- // 초기 데이터 로딩된 후 검색 결과 없으면 검색 결과 로딩
- useEffect(() => {
- if (suitableList && (!suitableSearch || suitableSearch.length === 0)) {
- refetchBySearch()
- }
- }, [suitableList, suitableSearch])
-
- // 카테고리 선택 시 검색 결과 로딩
- useEffect(() => {
- refetchBySearch()
- }, [selectedCategory])
-
- const handleSearch = async () => {
- if (!searchValue.trim()) {
- alert('검색어를 입력하세요.')
- return
- }
- refetchBySearch()
- }
-
- return (
- <>
-
- setSelectedCategory(e.target.value)}>
- 지붕재 카테고리 선택 고고
- {categories?.map((category) => (
-
- {category.roof_material}
-
- ))}
-
-
- 지붕재 종류 상세보기 페이지 이동
-
-
-
- setSearchValue(e.target.value)} />
- 검색
-
- >
- )
-}
diff --git a/src/components/SurveySales.tsx b/src/components/SurveySales.tsx
deleted file mode 100644
index f0dba94..0000000
--- a/src/components/SurveySales.tsx
+++ /dev/null
@@ -1,127 +0,0 @@
-'use client'
-
-import { surveySalesApi, SurveySalesBasicInfo, SurveySalesDetailInfo } from '@/api/surveySales'
-import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
-import { useState } from 'react'
-
-export default function SurveySales() {
- const [isSearch, setIsSearch] = useState(false)
-
- const queryClient = useQueryClient()
-
- const {
- mutate: createSurveySales,
- isPending,
- error,
- } = useMutation({
- mutationFn: surveySalesApi.create,
- onSuccess: () => {
- queryClient.invalidateQueries({ queryKey: ['survey-sales', 'list'] })
- },
- })
-
- const handleSurveySales = () => {
- const data: SurveySalesBasicInfo = {
- representative: 'keyy1315',
- store: 'HWJ(T01)',
- construction_point: 'HWJ(T01)',
- investigation_date: '2025-04-28',
- building_name: 'Hanwha Japan Building',
- customer_name: 'Hong Gil Dong',
- post_code: '1050013',
- address: 'Tokyo, Japan',
- address_detail: '1-1-1',
- submission_status: false,
- }
-
- createSurveySales(data)
- }
-
- const { data, error: errorList } = useQuery({
- queryKey: ['survey-sales', 'list'],
- queryFn: surveySalesApi.getList,
- enabled: isSearch,
- })
-
- const { mutate: updateSurveySales } = useMutation({
- mutationFn: surveySalesApi.update,
- onSuccess: () => {
- queryClient.invalidateQueries({ queryKey: ['survey-sales', 'list'] })
- },
- })
-
- const handleUpdateSurveySales = () => {
- const detailData: SurveySalesDetailInfo = {
- contract_capacity: '1100',
- retail_company: 'test company',
- supplementary_facilities: 1,
- supplementary_facilities_etc: '',
- installation_system: 3,
- installation_system_etc: '',
- construction_year: 4,
- construction_year_etc: '',
- roof_material: 1,
- roof_material_etc: '',
- roof_shape: 2,
- roof_shape_etc: '',
- roof_slope: '4.5',
- house_structure: 1,
- house_structure_etc: '',
- rafter_material: 5,
- rafter_material_etc: 'test message',
- rafter_size: 3,
- rafter_size_etc: '',
- rafter_pitch: 2,
- rafter_pitch_etc: '',
- rafter_direction: 3,
- open_field_plate_kind: 3,
- open_field_plate_kind_etc: '',
- open_field_plate_thickness: '',
- leak_trace: false,
- waterproof_material: 2,
- waterproof_material_etc: '',
- insulation_presence: 3,
- insulation_presence_etc: '',
- structure_order: 2,
- structure_order_etc: '',
- installation_availability: 1,
- installation_availability_etc: '',
- memo: 'test memo',
- }
-
- if (!data) return
-
- const surveySalesData: SurveySalesBasicInfo = {
- ...data[0],
- detail_info: { ...detailData },
- }
-
- updateSurveySales(surveySalesData)
- }
-
- return (
- <>
-
-
-
- 신규 등록
-
- setIsSearch(true)}>
- 조회
-
-
- 수정 (detail info add)
-
-
-
- {/*
-
Be Warned
-
기본 데이터 세팅 되어있습니다.
-
*/}
-
- {errorList &&
Error: {errorList.message}
}
- {data && data.map((item) =>
{JSON.stringify(item)}
)}
-
- >
- )
-}
diff --git a/src/components/User.tsx b/src/components/User.tsx
deleted file mode 100644
index 9a61069..0000000
--- a/src/components/User.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-'use client'
-
-import { useMutation, useQueryClient } from '@tanstack/react-query'
-import { userApi } from '@/api/user'
-import { logout } from '@/api/auth'
-import UserList from '@/components/UserList'
-
-export default function User() {
- const queryClient = useQueryClient()
-
- const {
- mutate: createUser,
- isPending,
- error,
- } = useMutation({
- mutationFn: userApi.create,
- onSuccess: () => {
- queryClient.invalidateQueries({ queryKey: ['user-list'] })
- },
- })
-
- return (
- <>
-
- createUser({ username: 'user1', email: 'user1@example.com', password: 'password1' })}
- >
- User Create1
-
-
-
- createUser({ username: 'user2', email: 'user2@example.com', password: 'password2' })}
- >
- User Create2
-
-
-
- {error &&
Error: {error.message}
}
- {isPending ?
Loading...
:
}
-
-
-
-
- Logout
-
-
- >
- )
-}
diff --git a/src/components/UserList.tsx b/src/components/UserList.tsx
deleted file mode 100644
index 0cdee4a..0000000
--- a/src/components/UserList.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-'use client'
-
-import { useQuery } from '@tanstack/react-query'
-import { userApi, User } from '@/api/user'
-
-export default function UserList() {
- const { data, error, isPending } = useQuery({
- queryKey: ['user-list'],
- queryFn: userApi.getList,
- })
-
- return (
-
- {isPending &&
Loading...
}
- {error &&
Error: {error.message}
}
- {data && (
-
- {data.map((user: User) => (
-
{user.username}
- ))}
-
- )}
-
- )
-}
diff --git a/src/components/common/Footer.tsx b/src/components/common/Footer.tsx
deleted file mode 100644
index 359a311..0000000
--- a/src/components/common/Footer.tsx
+++ /dev/null
@@ -1,13 +0,0 @@
-import Link from 'next/link'
-
-export default function Footer() {
- return (
- <>
-
-
- HOME
-
-
- >
- )
-}
diff --git a/src/components/inquiry/Answer.tsx b/src/components/inquiry/Answer.tsx
new file mode 100644
index 0000000..c1a5ec9
--- /dev/null
+++ b/src/components/inquiry/Answer.tsx
@@ -0,0 +1,38 @@
+'use client'
+
+export default function Answer() {
+ return (
+ <>
+
+
+
Hanwha Japan 回答
+
+ 佐藤一貴 / 2025.04.02 16:54:00
+
+
+
+
回答
+
+ 一次側接続は, 自動切替開閉器と住宅分電盤昼間遮断器との間に蓄電システム遮断器を配線する方法です. 二次側接続は,
+ 住宅分電盤週間ブレーカの二次側に蓄電システムブレーカを接続する
+
+
+
+
ファイル添付
+
+
+
+ 添付ファイル名.jpg
+
+
+
+
+ 添付ファイル名.jpg
+
+
+
+
+
+ >
+ )
+}
diff --git a/src/components/inquiry/Detail.tsx b/src/components/inquiry/Detail.tsx
new file mode 100644
index 0000000..d41d5a0
--- /dev/null
+++ b/src/components/inquiry/Detail.tsx
@@ -0,0 +1,87 @@
+'use client'
+
+import { useState } from 'react'
+import Answer from './Answer'
+
+export default function Detail() {
+ //todo: 답변 완료 표시를 위해 임시로 추가 해 놓은 state
+ // 추후에 api 작업 완료후 삭제
+ // 답변 완료 클래스 & 하단 답변내용 출력도
+ const [inquiry, setInquiry] = useState(false)
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+ 登録日
+ 2025.04.10
+
+
+ 作者
+ Hong gi
+
+
+ 販売店
+ interplug
+
+
+ 施工店
+ interplugs
+
+
+ E-mail
+ Hong@interplug.co.kr
+
+
+
+
+
+
屋根適合
+
屋根材適合性確認依頼
+
+ 入力した内容が表示されます.
+
+ インストール可能であることを確認してください.
+
+ 屋根の写真を添付しました.
+
+
+
+
ファイル添付
+
+
+
+ 添付ファイル名.jpg
+
+
+
+
+ 添付ファイル名.jpg
+
+
+
+
+
+
+ {inquiry &&
}
+
+
+
+ リスト
+
+
+
+ >
+ )
+}
diff --git a/src/components/inquiry/ListForm.tsx b/src/components/inquiry/ListForm.tsx
new file mode 100644
index 0000000..0b6ff3f
--- /dev/null
+++ b/src/components/inquiry/ListForm.tsx
@@ -0,0 +1,20 @@
+'use client'
+export default function ListForm() {
+ return (
+ <>
+
+ >
+ )
+}
diff --git a/src/components/inquiry/ListTable.tsx b/src/components/inquiry/ListTable.tsx
new file mode 100644
index 0000000..4735ef1
--- /dev/null
+++ b/src/components/inquiry/ListTable.tsx
@@ -0,0 +1,70 @@
+'use client'
+export default function ListTable() {
+ return (
+ <>
+
+
+
+
+
+ 全体
+ 全体
+ 全体
+ 全体
+ 全体
+
+
+
+
+
+ 合計 98 個
+
+
+
+
+
屋根
+
屋根材適合性確認依頼
+
2025.04.02
+
回答待ち
+
+
+
+
+
設計
+
設置可能ですか?
+
2025.04.02
+
回答完了
+
+
+
+
+
屋根
+
屋根材適合性確認依頼屋根材適合性確認依頼屋根材適合性確認依頼屋根材適合性確認依頼
+
2025.04.02
+
回答待ち
+
+
+
+
+
設計
+
設置可能ですか?
+
2025.04.02
+
回答完了
+
+
+
+
+
+ もっと見る
+
+
+
+
+ >
+ )
+}
diff --git a/src/components/inquiry/RegistForm.tsx b/src/components/inquiry/RegistForm.tsx
new file mode 100644
index 0000000..ea27aa8
--- /dev/null
+++ b/src/components/inquiry/RegistForm.tsx
@@ -0,0 +1,79 @@
+'use client'
+export default function RegistForm() {
+ return (
+ <>
+
+
+
+
+ お問い合わせタイプ *
+
+
+
+ 屋根適合
+ 屋根適合
+ 屋根適合
+ 屋根適合
+ 屋根適合
+
+
+
+
+
+ お問い合わせタイトル *
+
+
+
+ モジュールの取り付けを確認するかどうか
+ モジュールの取り付けを確認するかどうか
+ モジュールの取り付けを確認するかどうか
+ モジュールの取り付けを確認するかどうか
+ モジュールの取り付けを確認するかどうか
+
+
+
+
+
+ お問い合わせタイプ *
+
+
+
+
+
+
+
+
+
+ Attach ファイル
+
+
+
+
+
+
+ 登録
+
+
+
+
+ >
+ )
+}
diff --git a/src/components/popup/MemberInformationPopup.tsx b/src/components/popup/MemberInformationPopup.tsx
new file mode 100644
index 0000000..d7a8268
--- /dev/null
+++ b/src/components/popup/MemberInformationPopup.tsx
@@ -0,0 +1,58 @@
+'use client'
+
+import { usePopupController } from '@/store/popupController'
+
+export default function MemberInformationPopup() {
+ const popupController = usePopupController()
+
+ return (
+
+
+
+
+
+
+
+
+
+
会員情報
+
+
popupController.setMemberInfomationPopup(false)}>
+
+
+
+
+
+
+ )
+}
diff --git a/src/components/popup/ZipCodePopup.tsx b/src/components/popup/ZipCodePopup.tsx
new file mode 100644
index 0000000..45dd486
--- /dev/null
+++ b/src/components/popup/ZipCodePopup.tsx
@@ -0,0 +1,90 @@
+'use client'
+
+import { usePopupController } from '@/store/popupController'
+import { useState } from 'react'
+
+export default function ZipCodePopup() {
+ const [searchValue, setSearchValue] = useState('') //search 데이터 유무
+
+ //search 데이터 value 추가
+ const handleChange = (e: React.ChangeEvent) => {
+ setSearchValue(e.target.value)
+ }
+
+ const popupController = usePopupController()
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
住所検索
+
+
popupController.setZipCodePopup(false)}>
+
+
+
+
+
+
+
+ {/*input에 데이터 있으면 삭제버튼 보임 */}
+ {searchValue && setSearchValue('')}> }
+
+
+
+
+
名前
+
+
+
+ 都道府県
+ 市区町村
+ 市区町村以下
+
+
+
+
+ 東京都
+ 浜松
+ 浜松町
+
+
+ 東京都
+ 浜松
+ 浜松町
+
+
+ 東京都
+ 浜松
+ 浜松町
+
+
+
+
+
+
+ 住所の適用
+
+
+
+
+ 閉じる
+
+
+
+
+
+
+
+
+
+ >
+ )
+}
diff --git a/src/components/survey-sale/common/NavTab.tsx b/src/components/survey-sale/common/NavTab.tsx
new file mode 100644
index 0000000..8029afd
--- /dev/null
+++ b/src/components/survey-sale/common/NavTab.tsx
@@ -0,0 +1,47 @@
+'use client'
+
+import { useSurveySaleTabState } from '@/store/surveySaleTabState'
+import { usePathname, useRouter } from 'next/navigation'
+import { useEffect } from 'react'
+
+export default function NavTab() {
+ const router = useRouter()
+ const pathname = usePathname()
+
+ if (pathname === '/survey-sale') {
+ return null
+ }
+
+ const { basicInfoSelected, roofInfoSelected, reset } = useSurveySaleTabState()
+
+ useEffect(() => {
+ return () => {
+ reset()
+ }
+ }, [])
+
+ const handleBasicInfoClick = () => {
+ router.push('/survey-sale/basic-info')
+ }
+
+ const handleRoofInfoClick = () => {
+ router.push('/survey-sale/roof-info')
+ }
+
+ return (
+ <>
+
+
+
+
+ 基本情報
+
+
+ 電気 / 屋根情報
+
+
+
+
+ >
+ )
+}
diff --git a/src/components/survey-sale/detail/BasicForm.tsx b/src/components/survey-sale/detail/BasicForm.tsx
new file mode 100644
index 0000000..f293495
--- /dev/null
+++ b/src/components/survey-sale/detail/BasicForm.tsx
@@ -0,0 +1,98 @@
+'use client'
+
+import { useEffect } from 'react'
+import { useSurveySaleTabState } from '@/store/surveySaleTabState'
+
+export default function BasicForm() {
+ const { setBasicInfoSelected } = useSurveySaleTabState()
+
+ useEffect(() => {
+ setBasicInfoSelected()
+ }, [])
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
建物名
+
+
+
+
+
+
+ 東京都
+ 東京都
+ 東京都
+ 東京都
+ 東京都
+
+
+
+
+
+ 郵便番号
+
+
+
+
+
+
+
+
+ 一時保存
+
+
+
+
+ 保存
+
+
+
+
+ リスト
+
+
+
+
+ >
+ )
+}
diff --git a/src/components/survey-sale/detail/DataTable.tsx b/src/components/survey-sale/detail/DataTable.tsx
new file mode 100644
index 0000000..414164c
--- /dev/null
+++ b/src/components/survey-sale/detail/DataTable.tsx
@@ -0,0 +1,42 @@
+'use client'
+
+export default function DataTable() {
+ return (
+ <>
+
+
+
+
+
+
+
+
+ 登録番号
+ 0000000020
+
+
+ 登録日
+ 2025.04.11
+
+
+ 更新日時
+ 2025.04.11 15:06:29
+
+
+ 提出可否
+ 2025.04.12 10:00:00 (INTERPLUG –販売店)
+
+
+ ダウンロード
+
+
+ HWJ現地調査票確認
+
+
+
+
+
+
+ >
+ )
+}
diff --git a/src/components/survey-sale/detail/DetailForm.tsx b/src/components/survey-sale/detail/DetailForm.tsx
new file mode 100644
index 0000000..9462e95
--- /dev/null
+++ b/src/components/survey-sale/detail/DetailForm.tsx
@@ -0,0 +1,63 @@
+'use client'
+
+export default function DetailForm() {
+ return (
+ <>
+
+
+
+
+
+
+
+ リスト
+
+
+
+
+ 提出
+
+
+
+
+ 修正
+
+
+
+
+ 削除
+
+
+
+
+ >
+ )
+}
diff --git a/src/components/survey-sale/detail/RoofInfoForm.tsx b/src/components/survey-sale/detail/RoofInfoForm.tsx
new file mode 100644
index 0000000..e8850ca
--- /dev/null
+++ b/src/components/survey-sale/detail/RoofInfoForm.tsx
@@ -0,0 +1,370 @@
+'use client'
+
+import { useEffect } from 'react'
+import { useSurveySaleTabState } from '@/store/surveySaleTabState'
+
+export default function RoofInfoForm() {
+ const { setRoofInfoSelected } = useSurveySaleTabState()
+
+ useEffect(() => {
+ setRoofInfoSelected()
+ }, [])
+
+ return (
+ <>
+
+
電気関係
+
+
+
電気契約容量
+
+
+
+
+
+ kVA
+ kVA
+ kVA
+ kVA
+ kVA
+
+
+
+
+
+
+ 電気袋設備※複数選択可能
+
+
+
+
+
+
+
+
設置希望システム
+
+
+ 太陽光発電
+ 太陽光発電
+ 太陽光発電
+ 太陽光発電
+ 太陽光発電
+
+
+
+
+
+
+
+
+
+
+
屋根関係
+
+
+
建築研修
+
+
+ 新築
+ 新築
+ 新築
+ 新築
+ 新築
+
+
+
+
+ 年
+
+
+
+
+ 屋根材※最大2個まで選択可能
+
+
+
+
+
+
+
+
建築研修
+
+
+ 太陽光発電
+ 太陽光発電
+ 太陽光発電
+ 太陽光発電
+ 太陽光発電
+
+
+
+
+
+
+
+
+
住宅構造
+
+
+ 木製
+
+
+
+ その他 (直接入力)
+
+
+
+
+
+
+
+
垂木サイズ
+
+
+ 幅35mm以上×高さ48mm以上
+ 幅35mm以上×高さ48mm以上
+ 幅35mm以上×高さ48mm以上
+ 幅35mm以上×高さ48mm以上
+ 幅35mm以上×高さ48mm以上
+
+
+
+
+
+
+
+
垂木サイズ
+
+
+ 455mm以下
+ 455mm以下
+ 455mm以下
+ 455mm以下
+ 455mm以下
+
+
+
+
+
+
+
+
+
路地板の種類
+
+
+ 構造用合板
+ 構造用合板
+ 構造用合板
+ 構造用合板
+ 構造用合板
+
+
+
+
+
+
+
+
+ 路地板厚※小幅板を選択した場合, 厚さ. 小幅板間の間隔寸法を記載
+
+
+
+ mm
+
+
+
+
+
住宅構造
+
+
+ アスファルト屋根940(22kg以上)
+
+
+
+ その他 (直接入力)
+
+
+
+
+
+
+
断熱材の有無
+
+
+ あり
+
+
+
+
+
+
+ なし
+
+
+
+
路地板の種類
+
+
+ 材/防水材/屋根基礎/垂木
+ 材/防水材/屋根基礎/垂木
+ 材/防水材/屋根基礎/垂木
+ 材/防水材/屋根基礎/垂木
+ 材/防水材/屋根基礎/垂木
+
+
+
+
+
+
+
+
屋根製品名 設置可否確認
+
+
+ 確認済み
+ 確認済み
+ 確認済み
+ 確認済み
+ 確認済み
+
+
+
+
+
+
+
+
メモ
+
+
+ 確認済み
+ 確認済み
+ 確認済み
+ 確認済み
+ 確認済み
+
+
+
+
+
+
+
+
+
+
+ 一時保存
+
+
+
+
+ 保存
+
+
+
+
+ リスト
+
+
+
+
+ >
+ )
+}
diff --git a/src/components/survey-sale/list/ListTable.tsx b/src/components/survey-sale/list/ListTable.tsx
new file mode 100644
index 0000000..6d15b1e
--- /dev/null
+++ b/src/components/survey-sale/list/ListTable.tsx
@@ -0,0 +1,33 @@
+'use client'
+
+export default function ListTable() {
+ return (
+ <>
+
+
+ {Array.from({ length: 4 }).map((_, idx) => (
+
+
+
+
0000000021
+
2025.04.22
+
+
Hanwha Building
+
Gil dong
+
+
Hong Gildong
+
2025.04.22 10:00:21
+
+
+
+ ))}
+
+
+
+ もっと見る
+
+
+
+ >
+ )
+}
diff --git a/src/components/survey-sale/list/SearchForm.tsx b/src/components/survey-sale/list/SearchForm.tsx
new file mode 100644
index 0000000..5763dbf
--- /dev/null
+++ b/src/components/survey-sale/list/SearchForm.tsx
@@ -0,0 +1,43 @@
+'use client'
+
+export default function SearchForm() {
+ return (
+
+
+
+ 新規売買登録
+
+
+
+
+ 全体
+ 全体
+ 全体
+ 全体
+ 全体
+
+
+
+
+
+
+ 最近の登録日
+ 最近の登録日
+ 最近の登録日
+ 最近の登録日
+ 最近の登録日
+
+
+
+ )
+}
diff --git a/src/components/ui/Main.tsx b/src/components/ui/Main.tsx
new file mode 100644
index 0000000..a9eb336
--- /dev/null
+++ b/src/components/ui/Main.tsx
@@ -0,0 +1,80 @@
+'use client'
+
+import { useHeaderStore } from '@/store/header'
+import { useRouter } from 'next/navigation'
+import { useEffect } from 'react'
+
+export default function Main() {
+ const router = useRouter()
+ const { setBackBtn } = useHeaderStore()
+
+ useEffect(() => {
+ setBackBtn(false)
+ }, [])
+
+ return (
+ <>
+
+
+
屋根材の照会
+
ご使用の屋根材の適合性をご確認いただけます
+
+
+ 照会まさに移動
+
+
+
+
+
+
+
+
+
+
router.push('/survey-sale')}>
+
+
+
+
+
+
+
+
+
router.push('/survey-sale/basic-info')}>
+
+
+
+
+
+
+
+
+
router.push('/inquiry/list')}>
+
+
+
1:1お問い合わせ リスト
+
作成問い合わせの確認
+
+
+
+
+
+
+
+
router.push('/inquiry/regist')}>
+
+
+
1:1問い合わせ登録
+
新規お問い合わせの 作成
+
+
+
+
+ >
+ )
+}
diff --git a/src/components/ui/PopupController.tsx b/src/components/ui/PopupController.tsx
new file mode 100644
index 0000000..e221d6a
--- /dev/null
+++ b/src/components/ui/PopupController.tsx
@@ -0,0 +1,16 @@
+'use client'
+
+import { usePopupController } from '@/store/popupController'
+import MemberInfomationPopup from '../popup/MemberInformationPopup'
+import ZipCodePopup from '../popup/ZipCodePopup'
+
+export default function PopupController() {
+ const popupController = usePopupController()
+
+ return (
+ <>
+ {popupController.memberInfomationPopup && }
+ {popupController.zipCodePopup && }
+ >
+ )
+}
diff --git a/src/components/ui/common/FloatBtn.tsx b/src/components/ui/common/FloatBtn.tsx
new file mode 100644
index 0000000..766f236
--- /dev/null
+++ b/src/components/ui/common/FloatBtn.tsx
@@ -0,0 +1,13 @@
+'use client'
+
+import { usePathname } from 'next/navigation'
+
+export default function FloatBtn() {
+ const pathname = usePathname()
+
+ if (pathname === '/login' || pathname === '/') {
+ return null
+ }
+
+ return
+}
diff --git a/src/components/ui/common/Footer.tsx b/src/components/ui/common/Footer.tsx
new file mode 100644
index 0000000..dedeb50
--- /dev/null
+++ b/src/components/ui/common/Footer.tsx
@@ -0,0 +1,9 @@
+export default function Footer() {
+ return (
+ <>
+
+ >
+ )
+}
diff --git a/src/components/ui/common/Header.tsx b/src/components/ui/common/Header.tsx
new file mode 100644
index 0000000..580545d
--- /dev/null
+++ b/src/components/ui/common/Header.tsx
@@ -0,0 +1,131 @@
+'use client'
+
+import { useEffect, useState } from 'react'
+
+import Link from 'next/link'
+import { usePathname, useRouter } from 'next/navigation'
+
+import { Swiper, SwiperSlide } from 'swiper/react'
+
+import type { HeaderProps } from '@/types/Header'
+
+import 'swiper/css'
+import { useSideNavState } from '@/store/sideNavState'
+
+// type HeaderProps = {
+// name: string //header 이름
+// backBtn: boolean // 뒤로가기 버튼 유무
+// }
+
+export default function Header({ name }: HeaderProps) {
+ const router = useRouter()
+ const pathname = usePathname()
+ const { sideNavIsOpen, setSideNavIsOpen, reset } = useSideNavState()
+ const [isShowBackBtn, setIsShowBackBtn] = useState(false)
+
+ if (pathname === '/login') {
+ return null
+ }
+
+ useEffect(() => {
+ if (pathname !== '/') {
+ setIsShowBackBtn(true)
+ }
+ //사이드바 초기화
+ reset()
+ }, [pathname])
+
+ return (
+ <>
+
+ >
+ )
+}
diff --git a/src/middleware.ts b/src/middleware.ts
index a839c62..5fe31f3 100644
--- a/src/middleware.ts
+++ b/src/middleware.ts
@@ -7,10 +7,11 @@ import { SessionData, sessionOptions } from './libs/session'
export async function middleware(request: NextRequest) {
const cookieStore = await cookies()
const session = await getIronSession(cookieStore, sessionOptions)
- console.log('🚀 ~ middleware ~ session:', session)
- if (!session.isLoggedIn) {
- return NextResponse.redirect(new URL('/login', request.url))
- }
+
+ // todo: 로그인 기능 추가 시 주석 해제
+ // if (!session.isLoggedIn) {
+ // return NextResponse.redirect(new URL('/login', request.url))
+ // }
return NextResponse.next()
}
diff --git a/src/store/header.ts b/src/store/header.ts
new file mode 100644
index 0000000..f385213
--- /dev/null
+++ b/src/store/header.ts
@@ -0,0 +1,19 @@
+import { create } from 'zustand'
+
+type HeaderState = {
+ backBtn: boolean
+ setBackBtn: (backBtn: boolean) => void
+}
+
+type InitialState = {
+ backBtn: boolean
+}
+
+const initialState: InitialState = {
+ backBtn: true,
+}
+
+export const useHeaderStore = create((set) => ({
+ ...initialState,
+ setBackBtn: (value: boolean) => set((state) => ({ ...state, backBtn: value })),
+}))
diff --git a/src/store/popupController.ts b/src/store/popupController.ts
new file mode 100644
index 0000000..2a83120
--- /dev/null
+++ b/src/store/popupController.ts
@@ -0,0 +1,25 @@
+import { create } from 'zustand'
+
+type PoupControllerState = {
+ memberInfomationPopup: boolean
+ zipCodePopup: boolean
+ setMemberInfomationPopup: (value: boolean) => void
+ setZipCodePopup: (value: boolean) => void
+}
+
+type InitialState = {
+ memberInfomationPopup: boolean
+ zipCodePopup: boolean
+}
+
+const initialState: InitialState = {
+ memberInfomationPopup: false,
+ zipCodePopup: false,
+}
+
+export const usePopupController = create((set) => ({
+ ...initialState,
+ setMemberInfomationPopup: (value: boolean) => set((state) => ({ ...state, memberInfomationPopup: value })),
+ setZipCodePopup: (value: boolean) => set((state) => ({ ...state, zipCodePopup: value })),
+ reset: () => set(initialState),
+}))
diff --git a/src/store/sideNavState.ts b/src/store/sideNavState.ts
new file mode 100644
index 0000000..b283aeb
--- /dev/null
+++ b/src/store/sideNavState.ts
@@ -0,0 +1,21 @@
+import { create } from 'zustand'
+
+type SideNavState = {
+ sideNavIsOpen: boolean
+ setSideNavIsOpen: (value: boolean) => void
+ reset: () => void
+}
+
+type InitialState = {
+ sideNavIsOpen: boolean
+}
+
+const initialState: InitialState = {
+ sideNavIsOpen: false,
+}
+
+export const useSideNavState = create((set) => ({
+ ...initialState,
+ setSideNavIsOpen: (value: boolean) => set((state) => ({ ...state, sideNavIsOpen: value })),
+ reset: () => set(initialState),
+}))
diff --git a/src/store/surveySaleTabState.ts b/src/store/surveySaleTabState.ts
new file mode 100644
index 0000000..f0ab766
--- /dev/null
+++ b/src/store/surveySaleTabState.ts
@@ -0,0 +1,26 @@
+import { create } from 'zustand'
+
+type SurveySaleTabState = {
+ basicInfoSelected: boolean
+ roofInfoSelected: boolean
+ setBasicInfoSelected: () => void
+ setRoofInfoSelected: () => void
+ reset: () => void
+}
+
+type InitialState = {
+ basicInfoSelected: boolean
+ roofInfoSelected: boolean
+}
+
+const initialState: InitialState = {
+ basicInfoSelected: true,
+ roofInfoSelected: false,
+}
+
+export const useSurveySaleTabState = create((set) => ({
+ ...initialState,
+ setBasicInfoSelected: () => set((state) => ({ ...state, basicInfoSelected: true, roofInfoSelected: false })),
+ setRoofInfoSelected: () => set((state) => ({ ...state, basicInfoSelected: false, roofInfoSelected: true })),
+ reset: () => set(initialState),
+}))
diff --git a/src/styles/abstracts/_index.scss b/src/styles/abstracts/_index.scss
new file mode 100644
index 0000000..4745c16
--- /dev/null
+++ b/src/styles/abstracts/_index.scss
@@ -0,0 +1,2 @@
+@forward 'variables';
+@forward 'mixins';
\ No newline at end of file
diff --git a/src/styles/abstracts/_mixins.scss b/src/styles/abstracts/_mixins.scss
new file mode 100644
index 0000000..f94b2dd
--- /dev/null
+++ b/src/styles/abstracts/_mixins.scss
@@ -0,0 +1,25 @@
+@mixin flex($gapSize){
+ display: flex;
+ gap: $gapSize;
+}
+
+@mixin ellipsis($col){
+ overflow: hidden;
+ text-overflow: ellipsis;
+ display: -webkit-box;
+ -webkit-line-clamp: $col;
+ -webkit-box-orient: vertical;
+}
+
+@mixin absoluteCenter{
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+}
+
+@mixin defaultFont($size, $weight, $color){
+ font-size: $size;
+ font-weight: $weight;
+ color: $color;
+}
\ No newline at end of file
diff --git a/src/styles/abstracts/_variables.scss b/src/styles/abstracts/_variables.scss
new file mode 100644
index 0000000..1b21ae9
--- /dev/null
+++ b/src/styles/abstracts/_variables.scss
@@ -0,0 +1,47 @@
+/* color */
+$black-000: #000;
+$black-1010: #101010;
+
+$white-fff: #fff;
+
+$grey-eee: #eee;
+$grey-999: #999;
+
+$font-c: #2E3A59;
+$font-pl-c: #A8B6C7;
+
+$btn-font-c: #4E637E;
+
+/* font weight */
+$font-w-100: 100;
+$font-w-200: 200;
+$font-w-300: 300;
+$font-w-400: 400;
+$font-w-500: 500;
+$font-w-600: 600;
+$font-w-700: 700;
+$font-w-800: 800;
+$font-w-900: 900;
+
+/* font size */
+$font-s-10: 10px;
+$font-s-11: 11px;
+$font-s-12: 12px;
+$font-s-13: 13px;
+$font-s-14: 14px;
+$font-s-15: 15px;
+$font-s-16: 16px;
+$font-s-17: 17px;
+$font-s-18: 18px;
+$font-s-19: 19px;
+$font-s-20: 20px;
+$font-s-21: 21px;
+$font-s-22: 22px;
+$font-s-23: 23px;
+$font-s-24: 24px;
+$font-s-25: 25px;
+$font-s-26: 26px;
+$font-s-27: 27px;
+$font-s-28: 28px;
+$font-s-29: 29px;
+$font-s-30: 30px;
\ No newline at end of file
diff --git a/src/styles/base/_button.scss b/src/styles/base/_button.scss
new file mode 100644
index 0000000..c6d11ad
--- /dev/null
+++ b/src/styles/base/_button.scss
@@ -0,0 +1,99 @@
+@use "../abstracts" as *;
+
+.btn-frame{
+ display:block;
+ width: 100%;
+ padding:0 10px;
+ height:40px;
+ line-height:40px;
+ border-radius:4px;
+ text-align:center;
+ font-weight:$font-w-500;
+ font-size:$font-s-13;
+ color: $btn-font-c;
+ border: 1px solid #A8B6C7;
+ transition: all .15s ease-in-out;
+ cursor:pointer;
+ &.icon{
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+ &.min{
+ height: 30px;
+ line-height: 30px;
+ font-weight: $font-w-500;
+ }
+ &.login{
+ height: 50px;
+ line-height: 50px;
+ font-size: $font-s-14;
+ font-weight: $font-w-600;
+ background-color: #0081B5;
+ border-color: #0081B5;
+ color: $white-fff;
+ &:hover{
+ background-color: #016c96;
+ }
+ }
+ &:disabled{
+ opacity: 0.5;
+ background-color: $grey-eee;
+ cursor: default;
+ }
+ .btn-arr{
+ display: block;
+ width: 7px;
+ height: 10px;
+ background: url(/assets/images/common/btn_arr.svg)no-repeat center;
+ background-size: cover;
+ margin-left: 12px;
+ }
+ .btn-edit{
+ display: block;
+ width: 10px;
+ height: 10px;
+ background: url(/assets/images/common/btn_edit.svg)no-repeat center;
+ background-size: cover;
+ margin-left: 12px;
+ }
+ .btn-clip{
+ display: block;
+ width: 18px;
+ height: 18px;
+ background: url(/assets/images/common/btn_clip.svg)no-repeat center;
+ background-size: cover;
+ margin-right: 5px;
+ transition: all .15s ease-in-out;
+ }
+ &.d-blue{
+ background-color: #5F738E;
+ border-color: #5F738E;
+ color: $white-fff;
+ &:hover{
+ background-color: #466388;
+ }
+ }
+ &.n-blue{
+ background-color: #7896BA;
+ border-color: #7896BA;
+ color: $white-fff;
+ &:hover{
+ background-color: #668cbb;
+ }
+ }
+ &.l-blue{
+ background-color: #A8B6C7;
+ border-color: #A8B6C7;
+ color: $white-fff;
+ }
+ &.red{
+ background-color: #FF5656;
+ border-color: #FF5656;
+ color: $white-fff;
+ &:hover{
+ background-color: #db4b4b;
+ }
+ }
+}
+
diff --git a/src/styles/base/_check-radio.scss b/src/styles/base/_check-radio.scss
new file mode 100644
index 0000000..bbecd6f
--- /dev/null
+++ b/src/styles/base/_check-radio.scss
@@ -0,0 +1,213 @@
+@use "../abstracts" as *;
+
+// check radio 공통
+.check-form-box input[type="checkbox"],
+.radio-form-box input[type="radio"]{
+ position: static;
+ margin-left:0;
+ opacity: 0;
+ z-index: 1;
+ flex: 0 0 auto;
+ cursor: pointer;
+}
+.check-form-box label,
+.radio-form-box label{
+ position: relative;
+ display: inline-block;
+ margin-bottom:0;
+ line-height:1.5;
+ font-size: $font-s-13;
+ color: $font-c;
+ vertical-align: top;
+ word-break:break-all;
+ cursor: pointer;
+ -webkit-user-select:none;
+ -moz-user-select:none;
+ -ms-user-select:none;
+ user-select:none;
+}
+
+// check box
+.check-form-box{
+ position: relative;
+ label{
+ padding-left: 30px;
+ &::before{
+ content: "";
+ display: inline-block;
+ position: absolute;
+ width: 22px;
+ height: 22px;
+ top: -1px;
+ left: 0;
+ margin-left: 0px;
+ border: 1px solid #A8B6C7;
+ border-radius: 4px;
+ background-color: #fff;
+ transition: border 0.15s ease-in-out, color 0.15s ease-in-out;
+ cursor: pointer;
+ }
+ &::after{
+ content: "";
+ display: inline-block;
+ position: absolute;
+ width: 22px;
+ height: 22px;
+ top: -1px;
+ left: 0;
+ margin-left: 0;
+ border-color: #fff;
+ cursor: pointer;
+ }
+ }
+ input[type="checkbox"]:checked + label::before{
+ background-color: #A8B6C7;
+ border-color: #A8B6C7;
+ }
+ input[type="checkbox"]:checked + label::after{
+ content: "";
+ display: inline-block;
+ position: absolute;
+ top: -1px;
+ left: 0%;
+ width: 7px;
+ height: 9px;
+ border: 2px solid #fff;
+ border-left: none;
+ border-top: none;
+ transform: translate(7.75px,4.5px) rotate(45deg);
+ -ms-transform: translate(7.75px,4.5px) rotate(45deg);
+ }
+ input[type="checkbox"]:disabled + label{
+ opacity: 0.7;
+ cursor: default;
+ }
+ input[type="checkbox"]:disabled + label::before{
+ background-color: #f5f6fa;
+ cursor: default;
+ }
+ input[type="checkbox"]:disabled + label::after{
+ cursor: default;
+ }
+}
+
+// radio box
+.radio-form-box{
+ position: relative;
+ label{
+ padding-left: 30px;
+ &::before{
+ content: "";
+ display: inline-block;
+ position: absolute;
+ width: 22px;
+ height: 22px;
+ top: -1px;
+ left: 0;
+ margin-left: 0;
+ border: 1px solid #A8B6C7;
+ border-radius: 100%;
+ background-color: #fff;
+ text-align:center;
+ font-size:17px;
+ line-height:12px;
+ transition: border 0.15s ease-in-out, color 0.15s ease-in-out;
+ cursor: pointer;
+ }
+ &::after{
+ content: "";
+ display: inline-block;
+ position: absolute;
+ top: 5px;
+ left: 6px;
+ width: 10px;
+ height: 10px;
+ background-color: transparent;
+ border-radius: 50%;
+ transition: background-color 0.1s ease-in-out;
+ }
+ }
+
+ input[type="radio"]:checked + label::after{
+ background-color: #A8B6C7;
+ }
+
+ input[type="radio"]:disabled + label{
+ opacity: 0.7;
+ cursor: default;
+ }
+ input[type="radio"]:disabled + label::before{
+ background-color: #f5f6fa;
+ cursor: default;
+ }
+ input[type="radio"]:disabled + label::after{
+ cursor: default;
+ }
+}
+
+
+//toggle
+.toggle-btn {
+ position: relative;
+ display: inline-block;
+ width: 38px;
+ height: 22px;
+ input {
+ display: none;
+ }
+ .slider {
+ position: absolute;
+ cursor: pointer;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: #E9F0F8;
+ border-radius: 25px;
+ text-align: center;
+ line-height: 20px;
+ color: $white-fff;
+ font-size: 14px;
+ font-weight: 400;
+ transition: .4s;
+ &:after {
+ content: '';
+ position: absolute;
+ top: 1px;
+ right: 8px;
+ color: white;
+ font-size: 14px;
+ font-weight: 400;
+ }
+ &:before {
+ position: absolute;
+ content: "";
+ height: 18px;
+ width: 18px;
+ left: 2px;
+ bottom: 2px;
+ background-color: $white-fff;
+ transition: .4s;
+ border-radius: 50%;
+ }
+ }
+ input:checked + .slider {
+ background-color: #A8B6C7;
+ &:after {
+ content: '';
+ left: 10px;
+ right: auto;
+ }
+ &:before {
+ transform: translateX(16px);
+ }
+ }
+}
+
+.toggle-form{
+ @include flex(8px);
+ align-items: center;
+ .toggle-name{
+ @include defaultFont($font-s-13, $font-w-400, $font-c)
+ }
+}
\ No newline at end of file
diff --git a/src/styles/base/_fonts.scss b/src/styles/base/_fonts.scss
new file mode 100644
index 0000000..1c41522
--- /dev/null
+++ b/src/styles/base/_fonts.scss
@@ -0,0 +1,199 @@
+@font-face {
+ font-family: 'Noto Sans JP';
+ src: url('/assets/fonts/NotoSansJP-ExtraBold.woff2') format('woff2'),
+ url('/assets/fonts/NotoSansJP-ExtraBold.woff') format('woff');
+ font-weight: bold;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Noto Sans JP';
+ src: url('/assets/fonts/NotoSansJP-Bold.woff2') format('woff2'),
+ url('/assets/fonts/NotoSansJP-Bold.woff') format('woff');
+ font-weight: bold;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Noto Sans JP';
+ src: url('/assets/fonts/NotoSansJP-Black.woff2') format('woff2'),
+ url('/assets/fonts/NotoSansJP-Black.woff') format('woff');
+ font-weight: 900;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Noto Sans JP';
+ src: url('/assets/fonts/NotoSansJP-ExtraLight.woff2') format('woff2'),
+ url('/assets/fonts/NotoSansJP-ExtraLight.woff') format('woff');
+ font-weight: 200;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Noto Sans JP';
+ src: url('/assets/fonts/NotoSansJP-Light.woff2') format('woff2'),
+ url('/assets/fonts/NotoSansJP-Light.woff') format('woff');
+ font-weight: 300;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Noto Sans JP';
+ src: url('/assets/fonts/NotoSansJP-Medium.woff2') format('woff2'),
+ url('/assets/fonts/NotoSansJP-Medium.woff') format('woff');
+ font-weight: 500;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Noto Sans JP';
+ src: url('/assets/fonts/NotoSansJP-Regular.woff2') format('woff2'),
+ url('/assets/fonts/NotoSansJP-Regular.woff') format('woff');
+ font-weight: normal;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Noto Sans JP';
+ src: url('/assets/fonts/NotoSansJP-SemiBold.woff2') format('woff2'),
+ url('/assets/fonts/NotoSansJP-SemiBold.woff') format('woff');
+ font-weight: 600;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Noto Sans JP';
+ src: url('/assets/fonts/NotoSansJP-Thin.woff2') format('woff2'),
+ url('/assets/fonts/NotoSansJP-Thin.woff') format('woff');
+ font-weight: 100;
+ font-style: normal;
+ font-display: swap;
+}
+
+// pretendard
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/assets/fonts/Pretendard-Bold.woff2') format('woff2'),
+ url('/assets/fonts/Pretendard-Bold.woff') format('woff');
+ font-weight: bold;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/assets/fonts/Pretendard-ExtraBold.woff2') format('woff2'),
+ url('/assets/fonts/Pretendard-ExtraBold.woff') format('woff');
+ font-weight: bold;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/assets/fonts/Pretendard-ExtraBold.woff2') format('woff2'),
+ url('/assets/fonts/Pretendard-ExtraBold.woff') format('woff');
+ font-weight: bold;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/assets/fonts/Pretendard-ExtraLight.woff2') format('woff2'),
+ url('/assets/fonts/Pretendard-ExtraLight.woff') format('woff');
+ font-weight: 200;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/assets/fonts/Pretendard-ExtraLight.woff2') format('woff2'),
+ url('/assets/fonts/Pretendard-ExtraLight.woff') format('woff');
+ font-weight: 200;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/assets/fonts/Pretendard-Light.woff2') format('woff2'),
+ url('/assets/fonts/Pretendard-Light.woff') format('woff');
+ font-weight: 300;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/assets/fonts/Pretendard-Light.woff2') format('woff2'),
+ url('/assets/fonts/Pretendard-Light.woff') format('woff');
+ font-weight: 300;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/assets/fonts/Pretendard-Medium.woff2') format('woff2'),
+ url('/assets/fonts/Pretendard-Medium.woff') format('woff');
+ font-weight: 500;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/assets/fonts/Pretendard-Medium.woff2') format('woff2'),
+ url('/assets/fonts/Pretendard-Medium.woff') format('woff');
+ font-weight: 500;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/assets/fonts/Pretendard-Regular.woff2') format('woff2'),
+ url('/assets/fonts/Pretendard-Regular.woff') format('woff');
+ font-weight: normal;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/assets/fonts/Pretendard-Black.woff2') format('woff2'),
+ url('/assets/fonts/Pretendard-Black.woff') format('woff');
+ font-weight: 900;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/assets/fonts/Pretendard-Black.woff2') format('woff2'),
+ url('/assets/fonts/Pretendard-Black.woff') format('woff');
+ font-weight: 900;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: 'Pretendard';
+ src: url('/assets/fonts/Pretendard-Bold.woff2') format('woff2'),
+ url('/assets/fonts/Pretendard-Bold.woff') format('woff');
+ font-weight: bold;
+ font-style: normal;
+ font-display: swap;
+}
+
diff --git a/src/styles/base/_index.scss b/src/styles/base/_index.scss
new file mode 100644
index 0000000..f01a11e
--- /dev/null
+++ b/src/styles/base/_index.scss
@@ -0,0 +1,7 @@
+@forward 'fonts';
+@forward 'reset';
+@forward 'utilities';
+@forward 'button';
+@forward 'check-radio';
+@forward 'select-textarea';
+@forward 'inputs';
\ No newline at end of file
diff --git a/src/styles/base/_inputs.scss b/src/styles/base/_inputs.scss
new file mode 100644
index 0000000..7bc0784
--- /dev/null
+++ b/src/styles/base/_inputs.scss
@@ -0,0 +1,197 @@
+@use "../abstracts" as *;
+
+input[type='number']{
+ -moz-appearance: textfield;
+}
+input::-webkit-outer-spin-button,
+input::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ margin: 0;
+}
+
+// input default
+.input-frame {
+ display: block;
+ width: 100%;
+ height: 40px;
+ padding: 0 10px;
+ background-color: #fff;
+ background-clip: padding-box;
+ border: 1px solid #D5DEE8;
+ border-radius: 4px;
+ font-size: $font-s-13;
+ font-weight: $font-w-400;
+ color: $font-c;
+ box-shadow: inset 0 0 0 transparent;
+ transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out;
+ &::placeholder{
+ color: $font-pl-c;
+ }
+ &:read-only,
+ &:disabled{
+ background-color: #F5F6FA;
+ }
+ &:focus{
+ border-color: #4e93dd;
+ }
+}
+
+//file input
+.filebox{
+ display: flex;
+ align-items: center;
+ width: 100%;
+ .input-frame{
+ flex: 1 1 auto;
+ margin-right: 5px;
+ color: #999;
+ cursor: default;
+ &:read-only{
+ background-color: #fff;
+ }
+ &:focus{
+ border-color: #e5e6e7;
+ }
+ }
+ .file-upload{
+ flex: none;
+ display: inline-block;
+ height: 30px;
+ background-color: #fff;
+ padding: 0 10px;
+ border-radius: 2px;
+ font-size: 13px;
+ line-height: 30px;
+ color: #000;
+ border: 1px solid #000;
+ font-weight: 500;
+ cursor: pointer;
+ transition: background .15s ease-in-out;
+ }
+ input[type='file']{
+ display: none;
+ }
+}
+
+// search input
+.login-input,
+.date-input,
+.search-input{
+ display: flex;
+ align-items: center;
+ width: 100%;
+ padding: 0 10px;
+ height: 40px;
+ font-size: $font-s-13;
+ color: $font-c;
+ font-weight: $font-w-400;
+ background-color: $white-fff;
+ border: 1px solid #D5DEE8;
+ border-radius: 4px;
+ input{
+ width: 100%;
+ height: 100%;
+ background-color: transparent;
+ &::placeholder{
+ color: $font-pl-c;
+ }
+ }
+}
+.search-input{
+ .search-icon{
+ flex: none;
+ width: 24px;
+ height: 24px;
+ background: url(/assets/images/common/search_icon.svg)no-repeat center;
+ background-size: cover;
+ margin-left: 5px;
+ }
+ .del-icon{
+ flex: none;
+ width: 24px;
+ height: 24px;
+ background: url(/assets/images/common/search_del_icon.svg)no-repeat center;
+ background-size: cover;
+ margin-left: 5px;
+ }
+}
+.date-input{
+ padding-left: 0;
+ input{
+ padding-left: 10px;
+ }
+ .date-btn{
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-right: 1px solid #D5DEE8;
+ flex: none;
+ width: 34px;
+ height: 100%;
+ i{
+ display: block;
+ width: 24px;
+ height: 24px;
+ background: url(/assets/images/common/date_icon.svg)no-repeat center;
+ background-size: cover;
+ }
+ }
+}
+
+.login-input{
+ position: relative;
+ padding-left: 34px;
+ padding-right: 0;
+ height: 50px;
+ line-height: 50px;
+ &:before{
+ content: '';
+ position: absolute;
+ top: 50%;
+ left: 14px;
+ transform: translateY(-50%);
+ background-size: cover;
+ background-repeat: no-repeat;
+ background-position: center;
+ }
+ &.id{
+ &::before{
+ width: 10px;
+ height: 12px;
+ background-image: url(/assets/images/common/id_input_icon.svg);
+ }
+ }
+ &.pw{
+ &::before{
+ width: 9px;
+ height: 12px;
+ background-image: url(/assets/images/common/pw_input_icon.svg);
+ }
+ }
+ .login-icon{
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 40px;
+ height: 100%;
+ .del-icon{
+ display: block;
+ width: 16px;
+ height: 16px;
+ background: url(/assets/images/common/id_delete_icon.svg)no-repeat center;
+ background-size: cover;
+ }
+ .show-icon{
+ display: block;
+ width: 19px;
+ height: 14px;
+ background: url(/assets/images/common/pw_show_icon.svg)no-repeat center;
+ background-size: cover;
+ }
+ &.act{
+ .show-icon{
+ background: url(/assets/images/common/pw_hide_icon.svg)no-repeat center;
+ }
+ }
+ }
+}
diff --git a/src/styles/base/_reset.scss b/src/styles/base/_reset.scss
new file mode 100644
index 0000000..dc2f12e
--- /dev/null
+++ b/src/styles/base/_reset.scss
@@ -0,0 +1,47 @@
+@use "../abstracts" as *;
+
+* {
+ -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:$font-s-16;}/*font-size:1rem*/
+html, body,
+div,dl, dt, dd, ul, ol, li,
+h1, h2, h3, h4, h5, h6,
+blockquote, p, address, pre, cite,
+form, fieldset, input, textarea, select,
+table, th, td {margin:0;padding:0;line-height: 1.4; font-family: 'Noto Sans JP', sans-serif;}
+
+h1, h2, h3, h4, h5, h6 {font-size:100%;font-weight:normal;}
+
+fieldset, img, abbr,acronym, input, select, button { border:0 none; background:none;}
+
+ol, ul { list-style:none; }
+
+table {border-collapse: collapse;border-spacing:0;border:0 none;}
+caption, th, td {text-align:left;font-weight: normal;border:0;}
+
+address, caption, i, em, cite {font-weight:normal;font-style:normal;}
+ins { text-decoration:none; }
+del { text-decoration:line-through; }
+
+blockquote:before, blockquote:after, q:before, q:after { content:""; }
+blockquote,q { quotes:"" ""; }
+
+body:first-of-type caption { display:none;}
+
+a { cursor:pointer;color: $black-000;}
+a, a:hover, a:active {text-decoration:none;-webkit-tap-highlight-color: transparent;}
+
+button { font-family:inherit; outline:none; margin:0; padding: 0; cursor: pointer;}
+textarea { -webkit-appearance: none;appearance: none;border-radius:0;-webkit-border-radius: 0; font-family:inherit; resize: none;border:none;outline:0;}
+input { font-family:inherit; -webkit-appearance: none;appearance: none;border-radius:0;-webkit-border-radius: 0; border:none;outline:0;}
+img { max-width:100%; }
+
+select {-webkit-appearance:none;-moz-appearance:none; appearance:none}
diff --git a/src/styles/base/_select-textarea.scss b/src/styles/base/_select-textarea.scss
new file mode 100644
index 0000000..0e78248
--- /dev/null
+++ b/src/styles/base/_select-textarea.scss
@@ -0,0 +1,62 @@
+@use "../abstracts" as *;
+
+// select
+.select-form{
+ display: block;
+ width: 100%;
+ height: 40px;
+ line-height: 39px;
+ padding: 0px 36px 0px 10px;
+ border: 1px solid #D5DEE8;
+ border-radius: 4px;
+ font-size: $font-s-13;
+ font-weight: $font-w-400;
+ color: $font-c;
+ background:$white-fff url(/assets/images/common/select_arr.svg) calc(100% - 16px) center no-repeat;
+ background-size:14px 8px;
+ box-shadow: inset 0 0 0 transparent;
+ transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out;
+ cursor: pointer;
+ &:focus{
+ outline: none;
+ border-color: #4e93dd;
+ }
+ &:disabled{
+ opacity: 1;
+ background-color: #F5F6FA;
+ cursor: default;
+ }
+}
+.select-flex-form{
+ display: flex;
+ align-items: center;
+ width: 100%;
+ gap: 5px;
+ .select-form{
+ flex: 1 1 auto;
+ }
+}
+
+// textarea
+.textarea-form{
+ display: block;
+ width: 100%;
+ border: 1px solid #D5DEE8;
+ border-radius: 4px;
+ min-height: 100px;
+ padding: 14px;
+ font-size: $font-s-13;
+ font-weight: $font-w-400;
+ color: $font-c;
+ transition: border-color .15s ease-in-out;
+ &:focus{
+ border-color: #4e93dd;
+ }
+ &:disabled{
+ border-color: #D5DEE8;
+ background-color: #F5F6FA;
+ }
+ &::placeholder{
+ color: $font-pl-c;
+ }
+}
\ No newline at end of file
diff --git a/src/styles/base/_utilities.scss b/src/styles/base/_utilities.scss
new file mode 100644
index 0000000..256d7c8
--- /dev/null
+++ b/src/styles/base/_utilities.scss
@@ -0,0 +1,39 @@
+/* align */
+.al-c{text-align: center !important;}
+.al-r{text-align: right !important;}
+.al-l{text-align: left !important;}
+
+/* text-transform */
+.text-uppercase { text-transform: uppercase; }
+.text-lowercase { text-transform: lowercase; }
+.text-capitalize { text-transform: capitalize; }
+
+/* margin */
+.m0{margin: 0 !important;}
+.mt5{margin-top: 5px !important;}
+.mt10{margin-top: 10px !important;}
+.mt15{margin-top: 15px !important;}
+.mt20{margin-top: 20px !important;}
+.mt25{margin-top: 25px !important;}
+.mt30{margin-top: 30px !important;}
+.mb5{margin-bottom: 5px !important;}
+.mb10{margin-bottom: 10px !important;}
+.mb15{margin-bottom: 15px !important;}
+.mb20{margin-bottom: 20px !important;}
+.mb25{margin-bottom: 25px !important;}
+.mb30{margin-bottom: 30px !important;}
+.mr5{margin-right: 5px !important;}
+.mr10{margin-right: 10px !important;}
+.mr15{margin-right: 15px !important;}
+.mr20{margin-right: 20px !important;}
+.mr25{margin-right: 25px !important;}
+.mr30{margin-right: 30px !important;}
+.ml5{margin-left: 5px !important;}
+.ml10{margin-left: 10px !important;}
+.ml15{margin-left: 15px !important;}
+.ml20{margin-left: 20px !important;}
+.ml25{margin-left: 25px !important;}
+.ml30{margin-left: 30px !important;}
+
+// color
+.red-f{color: #FF5656 !important;}
\ No newline at end of file
diff --git a/src/styles/components/_index.scss b/src/styles/components/_index.scss
new file mode 100644
index 0000000..4ebdd02
--- /dev/null
+++ b/src/styles/components/_index.scss
@@ -0,0 +1,4 @@
+@forward 'main';
+@forward 'login';
+@forward 'pop-contents';
+@forward 'sub';
\ No newline at end of file
diff --git a/src/styles/components/_login.scss b/src/styles/components/_login.scss
new file mode 100644
index 0000000..7aae640
--- /dev/null
+++ b/src/styles/components/_login.scss
@@ -0,0 +1,19 @@
+@use "../abstracts" as *;
+
+.login-contents{
+ padding: 94px 34px 0;
+ .login-logo{
+ @include defaultFont($font-s-24, $font-w-600, $black-1010);
+ text-align: center;
+ }
+ .login-form-wrap{
+ margin-top: 42px;
+ .login-check-warp{
+ margin-top: 24px;
+ @include flex(14px);
+ }
+ .login-btn-wrap{
+ margin-top: 24px;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/styles/components/_main.scss b/src/styles/components/_main.scss
new file mode 100644
index 0000000..0c1f3b5
--- /dev/null
+++ b/src/styles/components/_main.scss
@@ -0,0 +1,91 @@
+@use "../abstracts" as *;
+
+.main-contens{
+ width: 100%;
+ height: auto;
+ padding: 0 20px;
+ background-color: $white-fff;
+}
+.main-head-block{
+ padding: 33px 30px;
+ background: linear-gradient(102deg, #F8F9EC 2.93%, rgba(249, 239, 236, 0.80) 98.22%);
+ border-radius: 16px;
+ .head-block-tit{
+ @include defaultFont($font-s-18, $font-w-600, #F86A56)
+ }
+ .head-block-text{
+ @include defaultFont($font-s-13, $font-w-500, #F86A56)
+ }
+ .head-block-link-wrap{
+ margin-top: 18px;
+ .head-block-link{
+ @include flex(10px);
+ align-items: center;
+ padding: 8px 13px;
+ background-color: #CD8888;
+ border-radius: 100px;
+ @include defaultFont($font-s-12, $font-w-600, $white-fff);
+ .block-arr{
+ display: block;
+ width: 6px;
+ height: 11px;
+ background: url(/assets/images/main/block_arr.svg)no-repeat center;
+ background-size: cover;
+ }
+ }
+ }
+}
+
+.main-grid-wrap{
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 15px;
+ margin-top: 15px;
+ .main-grid-bx{
+ min-height: 160px;
+ padding: 40px 20px 10px;
+ border-radius: 16px;
+ &.bx01{
+ background: linear-gradient(134deg, #F0EDFF 5.92%, #F0FFF6 96.24%);
+ }
+ &.bx02{
+ background: linear-gradient(134deg, #FFF4F4 3.38%, #F2FFF5 98.09%);
+ }
+ &.bx03{
+ background: linear-gradient(136deg, #F7FAF1 3.75%, #E6FCF7 98.46%);
+ }
+ &.bx04{
+ background: linear-gradient(133deg, #FFFBEF 3.32%, rgba(243, 236, 255, 0.33) 100%);
+ }
+ .grid-bx-head{
+ @include flex(0px);
+ align-items: center;
+ .main-bx-icon{
+ @include flex(0px);
+ }
+ .main-bx-arr{
+ display: block;
+ margin-left: auto;
+ width: 24px;
+ height: 24px;
+ border-radius: 50%;
+ background-color: #fff;
+ background-image: url(/assets/images/main/main_contens_arr.svg);
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: 12px 12px;
+ }
+ }
+ .grid-bx-body{
+ margin-top: 16px;
+ .grid-bx-body-tit{
+ @include defaultFont($font-s-14, $font-w-600, #7896BA);
+ }
+ .grid-bx-body-txt{
+ @include defaultFont($font-s-12, $font-w-500, #7896BA);
+ opacity: 0.6;
+ margin-top: 3px;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/styles/components/_pop-contents.scss b/src/styles/components/_pop-contents.scss
new file mode 100644
index 0000000..88180a2
--- /dev/null
+++ b/src/styles/components/_pop-contents.scss
@@ -0,0 +1,36 @@
+@use "../abstracts" as *;
+
+// 회원정보 팝업
+.member-infor-form-wrap{
+ margin-bottom: 20px;
+}
+
+// 우편번호 찾기 팝업
+.zip-code-search-input{
+ margin-bottom: 18px;
+}
+.zip-code-table-wrap{
+ .zip-code-table-tit{
+ @include defaultFont($font-s-13, $font-w-500, $font-c);
+ margin-bottom: 10px;
+ }
+ .zip-code-table{
+ width: 100%;
+ table-layout: fixed;
+ border-top: 2px solid #2E3A59;
+ th{
+ @include defaultFont($font-s-13, $font-w-500, $font-c);
+ padding: 10px;
+ border-bottom: 1px solid #2E3A59;
+ text-align: center;
+ }
+ td{
+ @include defaultFont($font-s-13, $font-w-400, $font-c);
+ padding: 10px;
+ border-bottom: 1px solid #ECECEC;
+ }
+ }
+ .btn-flex-wrap{
+ margin-top: 20px;
+ }
+}
\ No newline at end of file
diff --git a/src/styles/components/_sub.scss b/src/styles/components/_sub.scss
new file mode 100644
index 0000000..c1f05f8
--- /dev/null
+++ b/src/styles/components/_sub.scss
@@ -0,0 +1,419 @@
+@use "../abstracts" as *;
+
+// input form 공통
+.data-input-form-bx{
+ margin-bottom: 18px;
+ &:last-child{
+ margin-bottom: 0;
+ }
+ .data-input-form-tit{
+ @include defaultFont($font-s-13, $font-w-500, $font-c);
+ margin-bottom: 10px;
+ .import{
+ color: #F00;
+ }
+ span{
+ display: block;
+ @include defaultFont($font-s-13, $font-w-400, #A8B6C7);
+ }
+ }
+}
+
+.btn-flex-wrap{
+ @include flex(5px);
+ margin-top: 24px;
+ .btn-bx{
+ flex: 1;
+ }
+}
+
+// 매물 common
+.top-btn{
+ position: fixed;
+ bottom: 96px;
+ right: 15px;
+ width: 38px;
+ height: 38px;
+ background-color: rgba(0, 0, 0, 0.50);
+ background-image: url(/assets/images/sub/top_btn_icon.svg);
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: 18px 18px;
+ border-radius: 50%;
+ z-index: 90000;
+}
+
+.sale-contents{
+ width: 100%;
+ background-color: #F5F5F5;
+ .sale-frame{
+ padding: 0 20px;
+ border-top: 1px solid #ECECEC;
+ border-bottom: 1px solid #ECECEC;
+ margin-bottom: 10px;
+ padding-bottom: 24px;
+ padding-top: 24px;
+ background-color: $white-fff;
+ &:first-child{
+ padding-top: 0;
+ border-top: none;
+ }
+ &:last-child{
+ padding-bottom: 0;
+ border-bottom: none;
+ margin-bottom: 0;
+ }
+ }
+}
+.sale-detail-tab-relative{
+ height: 40px;
+ margin-bottom: 10px;
+}
+.sale-detail-tab-wrap{
+ position: fixed;
+ top: 66px;
+ left: 0;
+ width: 100%;
+ height: 40px;
+ background-color: $white-fff;
+ z-index: 98000;
+ .sale-detail-tab-inner{
+ position: relative;
+ @include flex(0px);
+ align-items: center;
+ height: 100%;
+ .sale-detail-tab{
+ flex: 1;
+ height: 100%;
+ background-color: #fff;
+ border-top: 1px solid #DDDFE2;
+ border-bottom: 1px solid #DDDFE2;
+ @include defaultFont($font-s-13, $font-w-500, $font-c);
+ &.act{
+ color: $white-fff;
+ background-color: #5F738E;
+ border-color: #5F738E;
+ }
+ }
+ }
+}
+
+// 매물 목록
+.sale-form-bx{
+ margin-bottom: 14px;
+ &:last-child{
+ margin-bottom: 0;
+ }
+}
+.sale-list-wrap{
+ .sale-list-item{
+ padding-top: 14px;
+ padding-bottom: 14px;
+ border-bottom: 1px solid #ECECEC;
+ cursor: pointer;
+ &:first-child{
+ padding-top: 0;
+ }
+ &:last-child{
+ border-bottom: none;
+ padding-bottom: 0;
+ }
+ }
+}
+.sale-item-bx{
+ .sale-item-date-bx{
+ @include flex(0px);
+ align-items: center;
+ margin-bottom: 9px;
+ .sale-item-num{
+ position: relative;
+ @include defaultFont($font-s-13, $font-w-400, $font-c);
+ padding-right: 6px;
+ &::after{
+ content: '';
+ position: absolute;
+ top: 50%;
+ right: 0;
+ transform: translateY(-50%);
+ width: 1px;
+ height: 10px;
+ background-color: #A2ABB8;
+ }
+ }
+ .sale-item-date{
+ @include defaultFont($font-s-13, $font-w-400, #A2ABB8);
+ padding-left: 6px;
+ }
+ }
+ .sale-item-tit{
+ @include defaultFont($font-s-15, $font-w-500, $font-c);
+ @include ellipsis(1);
+ margin-bottom: 9px;
+ }
+ .sale-item-customer{
+ @include defaultFont($font-s-13, $font-w-400, $font-c);
+ margin-bottom: 9px;
+ }
+ .sale-item-update-bx{
+ @include flex(0px);
+ align-items: center;
+ .sale-item-name{
+ position: relative;
+ @include defaultFont($font-s-13, $font-w-400, #A2ABB8);
+ padding-right: 6px;
+ &::after{
+ content: '';
+ position: absolute;
+ top: 50%;
+ right: 0;
+ transform: translateY(-50%);
+ width: 1px;
+ height: 10px;
+ background-color: #A2ABB8;
+ }
+ }
+ .sale-item-update{
+ @include defaultFont($font-s-13, $font-w-400, #A2ABB8);
+ padding-left: 6px;
+ }
+ }
+}
+.sale-edit-btn{
+ margin-top: 24px;
+}
+
+// 매물 상세
+.sale-data-table{
+ width: 100%;
+ table-layout: fixed;
+ tbody{
+ tr{
+ th{
+ @include defaultFont($font-s-13, $font-w-500, $font-c);
+ vertical-align: top;
+ padding: 5px 0;
+ }
+ td{
+ @include defaultFont($font-s-13, $font-w-400, $font-c);
+ padding: 5px 0 8px 14px;
+ .data-down{
+ @include flex(8px);
+ align-items: center;
+ color: #1259CB;
+ i{
+ display: block;
+ width: 8px;
+ height: 12px;
+ background: url(/assets/images/sub/down_icon.svg)no-repeat center;
+ background-size: cover;
+ }
+ }
+ }
+ &:first-child{
+ th,td{
+ padding-top: 0;
+ }
+ }
+ &:last-child{
+ th,td{
+ padding-bottom: 0;
+ }
+ }
+ }
+ }
+}
+
+// 매물 기본정보
+.form-flex{
+ @include flex(5px);
+ .form-bx{
+ flex: 1;
+ }
+}
+.form-btn{
+ margin-top: 12px;
+}
+
+// 매물 전기 지붕정보
+.sale-roof-title{
+ @include defaultFont($font-s-15, $font-w-500, $font-c);
+ padding-bottom: 10px;
+ margin-bottom: 20px;
+ border-bottom: 1px solid #2E3A59;
+}
+.data-check-wrap{
+ @include flex(10px);
+ flex-wrap: wrap;
+ margin-bottom: 12px;
+ .radio-form-box,
+ .check-form-box{
+ width: calc(50% - 5px);
+ }
+ &.mb0{
+ margin-bottom: 0;
+ }
+}
+.data-input{
+ &.flex{
+ @include flex(8px);
+ align-items: center;
+ span{
+ flex: none;
+ @include defaultFont($font-s-13, $font-w-400, $font-c);
+ }
+ }
+}
+
+
+// 1:1 문의 common
+.inquiry-frame{
+ padding: 0 20px;
+}
+.badge{
+ min-width: 60px;
+ height: 30px;
+ line-height: 30px;
+ padding: 0 8px;
+ border-radius: 60px;
+ text-align: center;
+ font-size: $font-s-12;
+ font-weight: $font-w-500;
+ &.blue{
+ color: #5497E9;
+ background-color: #ECF5FF;
+ }
+ &.orange{
+ color: #F86A56;
+ background-color: #FFEFED;
+ }
+ &.block{
+ width: 100%;
+
+ }
+}
+// 1:1 문의 목록
+.inquiry-table-filter{
+ margin-bottom: 24px;
+ .filter-check{
+ margin-bottom: 12px;
+ }
+}
+.inquiry-list-tit{
+ padding-bottom: 10px;
+ border-bottom: 1px solid #2E3A59;
+ @include defaultFont($font-s-13, $font-w-400, $font-c);
+ span{
+ font-weight: $font-w-500;
+ }
+}
+.inquiry-list{
+ .inquiry-item{
+ padding: 10px 0;
+ cursor: pointer;
+ border-bottom: 1px solid #ECECEC;
+ &:last-child{
+ border-bottom: none;
+ padding-bottom: 0;
+ }
+ .inquiry-item-bx{
+ position: relative;
+ padding-right: 70px;
+ .inquiry-item-category{
+ @include defaultFont($font-s-13, $font-w-400, $font-c);
+ margin-bottom: 5px;
+ }
+ .inquiry-item-tit{
+ @include defaultFont($font-s-15, $font-w-500, $font-c);
+ @include ellipsis(1);
+ margin-bottom: 5px;
+ }
+ .inquiry-item-date{
+ @include defaultFont($font-s-13, $font-w-400, #A2ABB8);
+ }
+ .inquiry-badge{
+ position: absolute;
+ top: 0;
+ right: 0;
+ }
+ }
+ }
+}
+
+// 1:1문의 작성
+.inquiry-file-wrap{
+ margin-top: 20px;
+ .file-list-wrap{
+ margin-top: 14px;
+ }
+}
+.file-list-tit{
+ @include defaultFont($font-s-13, $font-w-500, $font-c);
+}
+.file-list{
+ margin-top: 14px;
+ .file-item{
+ border-top: 1px solid #EDEDED;
+ cursor: default;
+ .file-item-bx{
+ width: 100%;
+ padding: 14px 0;
+ @include flex(0px);
+ align-items: center;
+ .file-item-name{
+ @include defaultFont($font-s-13, $font-w-400, $font-c);
+ }
+ .file-del{
+ display: block;
+ margin-left: auto;
+ width: 16px;
+ height: 16px;
+ background: url(/assets/images/common/id_delete_icon.svg)no-repeat center;
+ background-size: cover;
+ }
+ }
+ &:last-child{
+ .file-item-bx{
+ padding-bottom: 0;
+ }
+ }
+ }
+}
+
+// 1:1 문의 상세
+.inquiry-detail-data-table{
+ padding: 20px 0;
+ border-bottom: 1px solid #ECECEC;
+}
+.inquiry-detail-data{
+ padding: 20px 0;
+ border-bottom: 1px solid #2E3A59;
+ margin-bottom: 24px;
+ .inquiry-detail-category{
+ @include defaultFont($font-s-13, $font-w-400, $font-c);
+ margin-bottom: 3px;
+ }
+ .inquiry-detail-tit{
+ @include defaultFont($font-s-15, $font-w-500, $font-c);
+ margin-bottom: 10px;
+ }
+ .inquiry-detail-txt{
+ @include defaultFont($font-s-13, $font-w-400, $font-c);
+ }
+}
+
+// 1:1 문의 답변
+.inquiry-answer-wrap{
+ margin-top: 24px;
+}
+.inquiry-answer-header{
+ padding: 20px 0;
+ border-top: 1px solid #F86A56;
+ border-bottom: 1px solid #ECECEC;
+ .inquiry-answer-tit{
+ @include defaultFont($font-s-14, $font-w-500, #F86A56);
+ margin-bottom: 5px;
+ }
+ .inquiry-answer-date{
+ @include defaultFont($font-s-13, $font-w-400, #F86A56);
+ }
+}
\ No newline at end of file
diff --git a/src/styles/layout/_index.scss b/src/styles/layout/_index.scss
new file mode 100644
index 0000000..c1e1dee
--- /dev/null
+++ b/src/styles/layout/_index.scss
@@ -0,0 +1,2 @@
+@forward 'pop-common';
+@forward 'layout';
\ No newline at end of file
diff --git a/src/styles/layout/_layout.scss b/src/styles/layout/_layout.scss
new file mode 100644
index 0000000..6d1e7c4
--- /dev/null
+++ b/src/styles/layout/_layout.scss
@@ -0,0 +1,254 @@
+@use "../abstracts" as *;
+
+// 기본 Frame
+.wrap{
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ min-height: 100vh;
+ overflow-x: hidden;
+ .container{
+ flex: 1 1 auto;
+ }
+}
+
+// header
+.header-warp{
+ height: 66px;
+ z-index: 100000;
+}
+header{
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 66px;
+ background-color: $white-fff;
+ z-index: 100000;
+ .header-inner{
+ position: relative;
+ @include flex(0px);
+ align-items: center;
+ justify-content: center;
+ height: 100%;
+ .back-button-wrap{
+ position: absolute;
+ top: 50%;
+ left: 20px;
+ transform: translateY(-50%);
+ width: 24px;
+ height: 24px;
+ .back-button {
+ display: block;
+ width: 100%;
+ height: 100%;
+ background:url(/assets/images/layout/side_back_btn.svg) no-repeat center;
+ background-size: cover;
+ }
+ }
+ .logo{
+ a{
+ @include defaultFont($font-s-18, $font-w-600, $black-1010);
+ }
+ }
+ .side-button-wrap{
+ position: absolute;
+ top: 50%;
+ right: 20px;
+ transform: translateY(-50%);
+ width: 24px;
+ height: 24px;
+ .side-button{
+ display: block;
+ width: 100%;
+ height: 100%;
+ background:url(/assets/images/common/side_nav_btn.svg) no-repeat center;
+ background-size: cover;
+ }
+ }
+ }
+}
+
+.side-nav{
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0, 0, 0, 0.70);
+ opacity: 0;
+ visibility: hidden;
+ z-index: 990000;
+ transition: all .2s ease-in-out;
+ .side-nav-inner{
+ position: absolute;
+ top: 0;
+ right: -310px;
+ width: 310px;
+ height: 100%;
+ @include flex(0px);
+ flex-direction: column;
+ border-top-left-radius: 16px;
+ border-bottom-left-radius: 16px;
+ background-color: #fff;
+ z-index: 999000;
+ transition: all .2s ease-in-out;
+ }
+ &.active{
+ opacity: 1;
+ visibility: visible;
+ .side-nav-inner{
+ right: 0;
+ }
+ }
+}
+
+.side-nav-header{
+ @include flex(0px);
+ align-items: center;
+ padding: 20px 20px 0 20px;
+ .side-header-profile{
+
+ @include flex(12px);
+ align-items: center;
+ .profile-img{
+ @include flex(0px);
+ }
+ .profile-name{
+ font-family: 'Pretendard', sans-serif;
+ @include defaultFont($font-s-15, $font-w-600, $black-1010);
+ cursor: pointer;
+ }
+ .profile-company{
+ font-family: 'Pretendard', sans-serif;
+ @include defaultFont($font-s-12, $font-w-500, #535763);
+ }
+ }
+ .side-close-wrap{
+ margin-left: auto;
+ .side-close-btn{
+ width: 24px;
+ height: 24px;
+ background: url(/assets/images/layout/side_nav_close.svg)no-repeat center;
+ background-size: cover;
+ }
+ }
+}
+
+.side-swiper-wrap{
+ margin-top: 30px;
+ padding: 0 20px;
+ .swiper-slide{
+ height: auto;
+ }
+ .side-swiper-card{
+ width: 100%;
+ height: 100%;
+ padding: 16px 20px;
+ background-color: #F4F9FF;
+ border-radius: 8px;
+ cursor: pointer;
+ .side-swiper-icon{
+ width: 20px;
+ height: 20px;
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+ margin-bottom: 8px;
+ &.icon01{
+ background-image: url(/assets/images/layout/side_swiper_icon01.svg)
+ }
+ &.icon02{
+ background-image: url(/assets/images/layout/side_swiper_icon02.svg)
+ }
+ }
+ .side-swiper-infor{
+ @include defaultFont($font-s-12, $font-w-500, #7896BA);
+ word-break: keep-all;
+ }
+ }
+}
+
+.side-nav-wrap{
+ margin-top: 30px;
+ padding: 0 20px;
+ height: calc(100% - 247px);
+ overflow-y: auto;
+ .side-nav-list{
+ .side-nav-item{
+ padding: 12px;
+ margin-bottom: 8px;
+ button{
+ position: relative;
+ width: 100%;
+ text-align: left;
+ padding-right: 10px;
+ @include defaultFont($font-s-15, $font-w-500, #4B6586);
+ &:before{
+ content: '';
+ position: absolute;
+ top: 50%;
+ right: 0;
+ transform: translateY(-50%);
+ width: 6px;
+ height: 11px;
+ background: url(/assets/images/layout/side_nav_item_arr.svg)no-repeat center;
+ background-size: cover;
+ }
+ }
+ &:last-child{
+ margin-bottom: 0;
+ }
+ }
+ }
+}
+
+.side-nav-footer{
+ margin-top: 20px;
+ padding: 0 20px 34px 20px;
+ .side-footer-list{
+ @include flex(0px);
+ justify-content: center;
+ align-items: center;
+ padding-top: 24px;
+ border-top: 2px solid #EDEDED;
+ .side-footer-item{
+ position: relative;
+ display: flex;
+ padding: 0 12px;
+ button{
+ font-family: 'Pretendard', sans-serif;
+ text-transform: uppercase;
+ @include defaultFont($font-s-13, $font-w-500, $font-c);
+ &.bold{
+ font-weight: $font-w-600;
+ }
+ }
+ &::before{
+ content: '';
+ position: absolute;
+ top: 50%;
+ right: 0;
+ transform: translateY(-50%);
+ width: 1px;
+ height: 10px;
+ background-color: #EDEDED;
+ }
+ &:last-child{
+ &::before{
+ display: none;
+ }
+ }
+ }
+ }
+}
+
+// footer
+footer{
+ padding: 24px 20px;
+ .footer-inner{
+ font-family: 'Pretendard', sans-serif;
+ text-align: center;
+ @include defaultFont($font-s-11, $font-w-400, #9F9F9F);
+ }
+}
\ No newline at end of file
diff --git a/src/styles/layout/_pop-common.scss b/src/styles/layout/_pop-common.scss
new file mode 100644
index 0000000..365d2b3
--- /dev/null
+++ b/src/styles/layout/_pop-common.scss
@@ -0,0 +1,109 @@
+@use '../abstracts' as *;
+
+.modal-popup{
+ position: fixed;
+ top: 0;
+ left: 0;
+ width:100%;
+ height:100%;
+ overflow-x: hidden;
+ overflow-y: auto;
+ background:rgba(0,0,0,.75);
+ z-index:110000;
+ .modal-dialog {
+ position: relative;
+ display: flex;
+ min-height: calc(100% - (14px * 2));
+ max-width: 860px;
+ z-index:111000;
+ margin: 14px auto;
+ pointer-events: none;
+ font-size: $font-s-14;
+ .modal-content{
+ flex:1;
+ position: relative;
+ margin: 0 16px;
+ background-clip: padding-box;
+ background-color: $white-fff;
+ border-radius: 16px;
+ outline: 0 none;
+ pointer-events: auto;
+ .modal-header {
+ display: block;
+ position:relative;
+ padding:20px 20px 0;
+ }
+ .modal-body {
+ position: relative;
+ -ms-flex: 1 1 auto;
+ flex: 1 1 auto;
+ padding: 32px 20px;
+ }
+ .modal-footer {
+ display: -ms-flexbox;
+ display: flex;
+ -ms-flex-align: center;
+ align-items: center;
+ -ms-flex-pack: end;
+ justify-content: flex-end;
+ padding: 10px;
+ }
+ }
+ }
+}
+
+// modal-header
+.modal-header-inner{
+ @include flex(0px);
+ align-items: center;
+ .modal-name-wrap{
+ @include flex(12px);
+ align-items: center;
+ .modal-img{
+ @include flex(0px);
+ align-items: center;
+ justify-content: center;
+ width: 38px;
+ height: 38px;
+ border-radius: 50%;
+ background-color: $black-1010;
+ }
+ .modal-name{
+ @include defaultFont($font-s-15, $font-w-600, $black-1010)
+ }
+ }
+ .modal-close{
+ display: block;
+ margin-left: auto;
+ width: 24px;
+ height: 24px;
+ background: url(/assets/images/layout/modal_close.svg)no-repeat center;
+ background-size: cover;
+ }
+}
+
+// alert
+.modal-popup{
+ &.alert{
+ .modal-dialog{
+ max-width: 237px;
+ align-items: center;
+ .modal-content{
+ padding: 20px;
+ .alert-tit{
+ padding-bottom: 15px;
+ border-bottom: 1px solid #ECECEC;
+ text-align: center;
+ @include defaultFont($font-s-13, $font-w-400, $font-c);
+ }
+ .alert-btn-wrap{
+ @include flex(5px);
+ margin-top: 20px;
+ .alert-btn-bx{
+ flex: 1;
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/styles/publishpage.scss b/src/styles/publishpage.scss
new file mode 100644
index 0000000..64e89e0
--- /dev/null
+++ b/src/styles/publishpage.scss
@@ -0,0 +1,124 @@
+@import url('https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,100..900;1,100..900&display=swap');
+
+$default-color: #2C2C2C;
+
+.l{text-align: left !important;}
+.c{text-align: center !important;}
+.r{text-align: right !important;}
+
+.red{color: #F00;}
+
+.publish-list {
+ font-family: "Noto Sans", sans-serif;
+ font-optical-sizing: auto;
+ font-style: normal;
+ font-variation-settings:"wdth" 100;
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ min-height: 100vh;
+}
+.p-header{
+ padding: 20px;
+ background-color: $default-color;
+ text-align: center;
+ h1{
+ font-size: 34px;
+ color: #fff;
+ font-weight: 600;
+ }
+}
+
+.p-body{
+ margin-top: 30px;
+ flex: 1 1 auto;
+ .p-contents{
+ max-width: 1480px;
+ margin: 0 auto;
+ }
+}
+
+.p-guide{
+ border: 1px solid $default-color;
+ border-radius: 4px;
+ .p-guide-header{
+ font-size: 16px;
+ color: #fff;
+ background-color: $default-color;
+ padding: 10px 20px;
+ border-radius: 4px 4px 0 0;
+ }
+ .p-guide-content{
+ padding: 10px 20px;
+ p{
+ font-size: 14px;
+ margin-bottom: 5px;
+ span{
+ color: red;
+ }
+ &:last-child{
+ margin-bottom: 0;
+ }
+ }
+ }
+ .p-guide-inputcommon{
+ h3{
+ font-size: 16px;
+ margin: 15px 0 5px;
+ font-weight: 600;
+ }
+ a{
+ display: block;
+ border: 1px solid $default-color;
+ border-radius: 3px;
+ background-color: $default-color;
+ color: #fff;
+ height: 44px;
+ line-height: 40px;
+ padding: 0 10px;
+ text-align: center;
+ transition: all .15s ease-in-out;
+ &:hover{
+ background-color: #fff;
+ color: $default-color;
+ }
+ }
+ }
+}
+
+.p-list-wrap{
+ margin-top: 25px;
+ h2{
+ font-size: 22px;
+ font-weight: 500;
+ }
+ .p-list-table{
+ margin-top: 10px;
+ table{
+ width: 100%;
+ border-collapse: collapse;
+ table-layout: fixed;
+ th{
+ background-color: #eee;
+ color: #2C2C2C;
+ text-align: center;
+ font-size: 14px;
+ font-weight: 600;
+ padding: 10px;
+ border: 1px solid #999;
+ }
+ td{
+ border: 1px solid #999;
+ padding: 10px;
+ font-size: 12px;
+ a{
+ text-decoration: underline;
+ color: blue;
+ &:visited{
+ color: purple;
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/styles/style.scss b/src/styles/style.scss
new file mode 100644
index 0000000..091e269
--- /dev/null
+++ b/src/styles/style.scss
@@ -0,0 +1,5 @@
+@use 'abstracts';
+@use 'base';
+@use 'layout';
+@use 'components';
+
diff --git a/src/types/Header.ts b/src/types/Header.ts
new file mode 100644
index 0000000..2631a88
--- /dev/null
+++ b/src/types/Header.ts
@@ -0,0 +1,4 @@
+export type HeaderProps = {
+ name: string //header 이름
+ // backBtn: boolean // 뒤로가기 버튼 유무
+}