Merge branch 'dev' of https://git.hanasys.jp/qcast3/onsitesurvey into feature/suitable

This commit is contained in:
Daseul Kim 2025-05-16 17:59:29 +09:00
commit f53c7410e2
16 changed files with 2307 additions and 158 deletions

804
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -207,3 +207,13 @@ model MS_SUITABLE_MAIN {
UPT_DT DateTime?
MS_SUITABLE_DETAIL MS_SUITABLE_DETAIL[]
}
/// The underlying table does not contain a valid unique identifier and can therefore currently not be handled by Prisma Client.
model MS_USR_TRK {
ID Int @id @default(autoincrement())
OWNER String @db.VarChar(100)
TYPE String @db.VarChar(50)
URL String? @db.VarChar(200)
data String? @db.VarChar(200)
REG_DT DateTime @default(now())
}

View File

@ -0,0 +1,33 @@
import type { SessionData } from '@/types/Auth'
import { NextResponse } from 'next/server'
import { cookies } from 'next/headers'
import { Prisma } from '@prisma/client'
import { getIronSession } from 'iron-session'
import { sessionOptions } from '@/libs/session'
export const POST = async (request: Request) => {
const { url, data } = await request.json()
const cookieStore = await cookies()
const session = await getIronSession<SessionData>(cookieStore, sessionOptions)
let owner = session.userId
let type = ''
if (url.includes('api')) {
type = 'api'
} else {
type = 'page'
}
// @ts-ignore
const result = await Prisma.MS_USR_TRK.create({
data: {
owner,
type,
url,
data: JSON.stringify(data),
},
})
return NextResponse.json({ message: 'Tracking data received', result })
}

9
src/app/pdf/page.tsx Normal file
View File

@ -0,0 +1,9 @@
import DownloadPdf from '@/components/DownloadPDF'
export default function page() {
return (
<>
<DownloadPdf />
</>
)
}

View File

@ -1,11 +1,29 @@
import DataTable from '@/components/survey-sale/detail/DataTable'
import DetailForm from '@/components/survey-sale/detail/DetailForm'
import { SurveyBasicInfo } from '@/types/Survey'
export default function page() {
const surveyInfo: SurveyBasicInfo = {
ID: 1,
REPRESENTATIVE: 'HG',
STORE: 'HWJ(T01)',
CONSTRUCTION_POINT: '施工点名表示',
INVESTIGATION_DATE: '2021-01-01',
BUILDING_NAME: 'ビル名表示',
CUSTOMER_NAME: '顧客名表示',
POST_CODE: '1234567890',
ADDRESS: '東京都千代田区永田町1-7-1',
ADDRESS_DETAIL: '永田町ビル101号室',
SUBMISSION_STATUS: true,
SUBMISSION_DATE: '2021-01-01',
DETAIL_INFO: null,
REG_DT: new Date(),
UPT_DT: new Date(),
}
return (
<>
<DataTable />
<DetailForm />
<DetailForm surveyInfo={surveyInfo} mode="READ" />
</>
)
}

View File

@ -9,10 +9,7 @@ export default function layout({ children, navTab }: SurveySaleLayoutProps) {
return (
<>
<div className="container">
<div className="sale-contents">
{navTab}
{children}
</div>
<div className="sale-contents">{children}</div>
</div>
</>
)

View File

@ -0,0 +1,748 @@
'use client'
import { useRef } from 'react'
import generatePDF, { Margin, Resolution } from 'react-to-pdf'
export default function DownloadPdf() {
const targetRef = useRef<HTMLDivElement>(null)
const handleDownPdf = () => {
const options = {
method: 'open' as const,
resolution: Resolution.HIGH,
page: {
margin: Margin.SMALL,
format: 'A4',
orientation: 'portrait' as const,
},
canvas: {
mimeType: 'image/png' as const,
qualityRatio: 1,
},
overrides: {
pdf: {
compress: true,
},
canvas: {
useCORS: true,
},
},
}
generatePDF(targetRef, options)
// generatePDF(targetRef, { filename: 'page.pdf' })
}
return (
<>
<button onClick={handleDownPdf}>down</button>
<div ref={targetRef} style={{ boxSizing: 'border-box' }}>
<div style={{ margin: '0 auto', padding: 0, maxWidth: '800px' }}>
<div style={{ padding: '20px 20px 50px', borderBottom: '2px solid #2E3A59' }}>
<div style={{ float: 'left', verticalAlign: 'middle', fontSize: '18px', color: '#101010', fontWeight: 600, fontFamily: 'M-Gothic' }}>
HWJ 調1/2
</div>
<div style={{ float: 'right', overflow: 'hidden' }}>
<div style={{ float: 'left', marginRight: '20px' }}>
<p style={{ margin: 0, padding: 0, fontSize: '13px', color: '#101010', fontWeight: 500, fontFamily: 'M-Gothic', textAlign: 'right' }}>
</p>
<p style={{ margin: 0, padding: 0, fontSize: '13px', color: '#FF5656', fontWeight: 400, fontFamily: 'M-Gothic' }}>
Sheet2 No.4Sheet2
</p>
</div>
<div style={{ float: 'right' }}>
<p style={{ margin: 0, padding: 0, fontSize: '13px', color: '#101010', fontWeight: 500, fontFamily: 'M-Gothic' }}></p>
<p style={{ margin: 0, padding: 0, fontSize: '13px', color: '#FF5656', fontWeight: 400, fontFamily: 'M-Gothic' }}>2025.05.09</p>
</div>
</div>
</div>
<div style={{ padding: '24px 20px 12px' }}>
<table
style={{ width: '100%', tableLayout: 'fixed', borderCollapse: 'collapse', fontFamily: 'M-Gothic', WebkitPrintColorAdjust: 'exact' }}
>
<tbody>
<tr>
<th
style={{
padding: '10px',
width: '73px',
border: '1px solid #2E3A59',
backgroundColor: '#F5F6FA',
fontSize: '13px',
fontWeight: 500,
color: '#101010',
textAlign: 'left',
boxSizing: 'border-box',
}}
>
</th>
<td
style={{
padding: '10px',
border: '1px solid #2E3A59',
fontSize: '13px',
fontWeight: 500,
color: '#FF5656',
boxSizing: 'border-box',
}}
>
Sheet2No.1
</td>
</tr>
<tr>
<th
style={{
padding: '10px',
width: '73px',
border: '1px solid #2E3A59',
backgroundColor: '#F5F6FA',
fontSize: '13px',
fontWeight: 500,
color: '#101010',
textAlign: 'left',
boxSizing: 'border-box',
}}
>
</th>
<td
style={{
padding: '10px',
border: '1px solid #2E3A59',
fontSize: '13px',
fontWeight: 500,
color: '#FF5656',
boxSizing: 'border-box',
}}
>
Sheet2No.2
</td>
</tr>
</tbody>
</table>
</div>
<div style={{ padding: '12px 20px 12px' }}>
<div style={{ fontSize: '14px', fontFamily: 'M-Gothic', color: '#101010', fontWeight: 500, marginBottom: '10px' }}></div>
<table
style={{ width: '100%', tableLayout: 'fixed', borderCollapse: 'collapse', fontFamily: 'M-Gothic', WebkitPrintColorAdjust: 'exact' }}
>
<tbody>
<tr>
<th
style={{
padding: '10px',
width: '126px',
border: '1px solid #2E3A59',
backgroundColor: '#F5F6FA',
fontSize: '13px',
fontWeight: 500,
color: '#101010',
textAlign: 'left',
boxSizing: 'border-box',
}}
>
</th>
<td
style={{
padding: '10px',
border: '1px solid #2E3A59',
fontSize: '13px',
fontWeight: 500,
color: '#FF5656',
boxSizing: 'border-box',
}}
>
Sheet2No.1
</td>
<th
style={{
padding: '10px',
width: '126px',
border: '1px solid #2E3A59',
backgroundColor: '#F5F6FA',
fontSize: '13px',
fontWeight: 500,
color: '#101010',
textAlign: 'left',
boxSizing: 'border-box',
}}
>
</th>
<td
style={{
padding: '10px',
border: '1px solid #2E3A59',
fontSize: '13px',
fontWeight: 500,
color: '#FF5656',
boxSizing: 'border-box',
}}
>
Sheet2No.1
</td>
</tr>
<tr>
<th
style={{
padding: '10px',
width: '126px',
border: '1px solid #2E3A59',
backgroundColor: '#F5F6FA',
fontSize: '13px',
fontWeight: 500,
color: '#101010',
textAlign: 'left',
boxSizing: 'border-box',
}}
>
</th>
<td
colSpan={3}
style={{
padding: '10px',
border: '1px solid #2E3A59',
fontSize: '13px',
fontWeight: 500,
color: '#FF5656',
boxSizing: 'border-box',
}}
>
Sheet2No.7 /
</td>
</tr>
<tr>
<th
style={{
padding: '10px',
width: '126px',
border: '1px solid #2E3A59',
backgroundColor: '#F5F6FA',
fontSize: '13px',
fontWeight: 500,
color: '#101010',
textAlign: 'left',
boxSizing: 'border-box',
}}
>
</th>
<td
colSpan={3}
style={{
padding: '10px',
border: '1px solid #2E3A59',
fontSize: '13px',
fontWeight: 500,
color: '#FF5656',
boxSizing: 'border-box',
}}
>
Sheet2No.8 /
</td>
</tr>
</tbody>
</table>
</div>
<div style={{ padding: '12px 20px 12px' }}>
<div style={{ fontSize: '14px', fontFamily: 'M-Gothic', color: '#101010', fontWeight: 500, marginBottom: '10px' }}></div>
<table
style={{ width: '100%', tableLayout: 'fixed', borderCollapse: 'collapse', fontFamily: 'M-Gothic', WebkitPrintColorAdjust: 'exact' }}
>
<tbody>
<tr>
<th
style={{
padding: '10px',
width: '126px',
border: '1px solid #2E3A59',
backgroundColor: '#F5F6FA',
fontSize: '13px',
fontWeight: 500,
color: '#101010',
textAlign: 'left',
boxSizing: 'border-box',
}}
>
</th>
<td
style={{
padding: '10px',
border: '1px solid #2E3A59',
fontSize: '13px',
fontWeight: 500,
color: '#FF5656',
boxSizing: 'border-box',
}}
>
No.9
</td>
<th
style={{
padding: '10px',
width: '126px',
border: '1px solid #2E3A59',
backgroundColor: '#F5F6FA',
fontSize: '13px',
fontWeight: 500,
color: '#101010',
textAlign: 'left',
boxSizing: 'border-box',
}}
>
</th>
<td
style={{
padding: '10px',
border: '1px solid #2E3A59',
fontSize: '13px',
fontWeight: 500,
color: '#FF5656',
boxSizing: 'border-box',
}}
>
No.10
</td>
<th
style={{
padding: '10px',
width: '126px',
border: '1px solid #2E3A59',
backgroundColor: '#F5F6FA',
fontSize: '13px',
fontWeight: 500,
color: '#101010',
textAlign: 'left',
boxSizing: 'border-box',
}}
>
</th>
<td
style={{
padding: '10px',
border: '1px solid #2E3A59',
fontSize: '13px',
fontWeight: 500,
color: '#FF5656',
boxSizing: 'border-box',
}}
>
No.11
</td>
</tr>
<tr>
<th
style={{
padding: '10px',
width: '126px',
border: '1px solid #2E3A59',
backgroundColor: '#F5F6FA',
fontSize: '13px',
fontWeight: 500,
color: '#101010',
textAlign: 'left',
boxSizing: 'border-box',
}}
>
</th>
<td
style={{
padding: '10px',
border: '1px solid #2E3A59',
fontSize: '13px',
fontWeight: 500,
color: '#FF5656',
boxSizing: 'border-box',
}}
>
No.12
</td>
<th
style={{
padding: '10px',
width: '126px',
border: '1px solid #2E3A59',
backgroundColor: '#F5F6FA',
fontSize: '13px',
fontWeight: 500,
color: '#101010',
textAlign: 'left',
boxSizing: 'border-box',
}}
>
</th>
<td
colSpan={3}
style={{
padding: '10px',
border: '1px solid #2E3A59',
fontSize: '13px',
fontWeight: 500,
color: '#FF5656',
boxSizing: 'border-box',
}}
>
No.13
</td>
</tr>
<tr>
<th
style={{
padding: '10px',
width: '126px',
border: '1px solid #2E3A59',
backgroundColor: '#F5F6FA',
fontSize: '13px',
fontWeight: 500,
color: '#101010',
textAlign: 'left',
boxSizing: 'border-box',
}}
>
</th>
<td
style={{
padding: '10px',
border: '1px solid #2E3A59',
fontSize: '13px',
fontWeight: 500,
color: '#FF5656',
boxSizing: 'border-box',
}}
>
No.14
</td>
<th
style={{
padding: '10px',
width: '126px',
border: '1px solid #2E3A59',
backgroundColor: '#F5F6FA',
fontSize: '13px',
fontWeight: 500,
color: '#101010',
textAlign: 'left',
boxSizing: 'border-box',
}}
>
</th>
<td
colSpan={3}
style={{
padding: '10px',
border: '1px solid #2E3A59',
fontSize: '13px',
fontWeight: 500,
color: '#FF5656',
boxSizing: 'border-box',
}}
>
No.15
</td>
</tr>
<tr>
<th
style={{
padding: '10px',
width: '126px',
border: '1px solid #2E3A59',
backgroundColor: '#F5F6FA',
fontSize: '13px',
fontWeight: 500,
color: '#101010',
textAlign: 'left',
boxSizing: 'border-box',
}}
>
</th>
<td
style={{
padding: '10px',
border: '1px solid #2E3A59',
fontSize: '13px',
fontWeight: 500,
color: '#FF5656',
boxSizing: 'border-box',
}}
>
No.16
</td>
<th
style={{
padding: '10px',
width: '126px',
border: '1px solid #2E3A59',
backgroundColor: '#F5F6FA',
fontSize: '13px',
fontWeight: 500,
color: '#101010',
textAlign: 'left',
boxSizing: 'border-box',
}}
>
</th>
<td
colSpan={3}
style={{
padding: '10px',
border: '1px solid #2E3A59',
fontSize: '13px',
fontWeight: 500,
color: '#FF5656',
boxSizing: 'border-box',
}}
>
No.17
</td>
</tr>
<tr>
<th
style={{
padding: '10px',
width: '126px',
border: '1px solid #2E3A59',
backgroundColor: '#F5F6FA',
fontSize: '13px',
fontWeight: 500,
color: '#101010',
textAlign: 'left',
boxSizing: 'border-box',
}}
>
</th>
<td
style={{
padding: '10px',
border: '1px solid #2E3A59',
fontSize: '13px',
fontWeight: 500,
color: '#FF5656',
boxSizing: 'border-box',
}}
>
No.18
</td>
<th
style={{
padding: '10px',
width: '126px',
border: '1px solid #2E3A59',
backgroundColor: '#F5F6FA',
fontSize: '13px',
fontWeight: 500,
color: '#101010',
textAlign: 'left',
boxSizing: 'border-box',
}}
>
</th>
<td
colSpan={3}
style={{
padding: '10px',
border: '1px solid #2E3A59',
fontSize: '13px',
fontWeight: 500,
color: '#FF5656',
boxSizing: 'border-box',
}}
>
No.19
</td>
</tr>
<tr>
<th
style={{
padding: '10px',
width: '126px',
border: '1px solid #2E3A59',
backgroundColor: '#F5F6FA',
fontSize: '13px',
fontWeight: 500,
color: '#101010',
textAlign: 'left',
boxSizing: 'border-box',
}}
>
</th>
<td
colSpan={5}
style={{
padding: '10px',
border: '1px solid #2E3A59',
fontSize: '13px',
fontWeight: 500,
color: '#FF5656',
boxSizing: 'border-box',
}}
>
No.20
</td>
</tr>
<tr>
<th
style={{
padding: '10px',
width: '126px',
border: '1px solid #2E3A59',
backgroundColor: '#F5F6FA',
fontSize: '13px',
fontWeight: 500,
color: '#101010',
textAlign: 'left',
boxSizing: 'border-box',
}}
>
</th>
<td
colSpan={5}
style={{
padding: '10px',
border: '1px solid #2E3A59',
fontSize: '13px',
fontWeight: 500,
color: '#FF5656',
boxSizing: 'border-box',
}}
>
No.21
</td>
</tr>
<tr>
<th
style={{
padding: '10px',
width: '126px',
border: '1px solid #2E3A59',
backgroundColor: '#F5F6FA',
fontSize: '13px',
fontWeight: 500,
color: '#101010',
textAlign: 'left',
boxSizing: 'border-box',
}}
>
</th>
<td
colSpan={5}
style={{
padding: '10px',
border: '1px solid #2E3A59',
fontSize: '13px',
fontWeight: 500,
color: '#FF5656',
boxSizing: 'border-box',
}}
>
No.22
</td>
</tr>
<tr>
<th
style={{
padding: '10px',
width: '126px',
border: '1px solid #2E3A59',
backgroundColor: '#F5F6FA',
fontSize: '13px',
fontWeight: 500,
color: '#101010',
textAlign: 'left',
boxSizing: 'border-box',
}}
>
</th>
<td
colSpan={5}
style={{
padding: '10px',
border: '1px solid #2E3A59',
fontSize: '13px',
fontWeight: 500,
color: '#FF5656',
boxSizing: 'border-box',
}}
>
No.23
</td>
</tr>
</tbody>
</table>
</div>
<div style={{ padding: '12px 20px' }}>
<table
style={{ width: '100%', tableLayout: 'fixed', borderCollapse: 'collapse', fontFamily: 'M-Gothic', WebkitPrintColorAdjust: 'exact' }}
>
<tbody>
<tr>
<th
style={{
padding: '10px',
width: '160px',
border: '1px solid #2E3A59',
backgroundColor: '#F5F6FA',
fontSize: '13px',
fontWeight: 500,
color: '#101010',
textAlign: 'left',
boxSizing: 'border-box',
}}
>
</th>
<td
colSpan={5}
style={{
padding: '10px',
border: '1px solid #2E3A59',
fontSize: '13px',
fontWeight: 500,
color: '#FF5656',
boxSizing: 'border-box',
}}
>
No.23
</td>
</tr>
</tbody>
</table>
</div>
<div style={{ padding: '12px 20px 12px' }}>
<div style={{ fontSize: '14px', fontFamily: 'M-Gothic', color: '#101010', fontWeight: 500, marginBottom: '10px' }}></div>
<div
style={{
boxSizing: 'border-box',
padding: '10px',
fontSize: '13px',
fontWeight: 400,
fontFamily: 'M-Gothic',
color: '#FF5656',
border: '1px solid #2E3A59',
height: '150px',
}}
>
No.25
</div>
</div>
</div>
</div>
</>
)
}

View File

@ -1,10 +1,18 @@
'use client'
import { useEffect } from 'react'
import { useEffect, useState } from 'react'
import { useSurveySaleTabState } from '@/store/surveySaleTabState'
import { SurveyBasicInfo } from '@/types/Survey'
import { Mode } from 'fs'
export default function BasicForm() {
export default function BasicForm(props: {
surveyInfo: Partial<SurveyBasicInfo>
setSurveyInfo: (surveyInfo: Partial<SurveyBasicInfo>) => void
mode: Mode
}) {
const { surveyInfo, setSurveyInfo, mode } = props
const { setBasicInfoSelected } = useSurveySaleTabState()
const [isFlip, setIsFlip] = useState<boolean>(true)
useEffect(() => {
setBasicInfoSelected()
@ -12,84 +20,101 @@ export default function BasicForm() {
return (
<>
<div className="sale-frame">
<div className="data-form-wrap">
<div className="data-input-form-bx">
<div className="data-input-form-tit"></div>
<input type="text" className="input-frame" defaultValue={'HG'} />
</div>
<div className="data-input-form-bx">
<div className="data-input-form-tit"></div>
<input type="text" className="input-frame" defaultValue={'HWJ(T01)'} />
</div>
<div className="data-input-form-bx">
<div className="data-input-form-tit"></div>
<input type="text" className="input-frame" defaultValue={'施工点名表示'} />
<div className={`sale-detail-toggle-bx ${isFlip ? 'act' : ''}`}>
<div className="sale-detail-toggle-head" onClick={() => setIsFlip(!isFlip)}>
<div className="sale-detail-toggle-name"></div>
<div className="sale-detail-toggle-btn-wrap">
<button className="sale-detail-toggle-btn"></button>
</div>
</div>
</div>
<div className="sale-detail-toggle-cont">
<div className="sale-frame">
<div className="data-form-wrap">
<div className="data-input-form-bx">
<div className="data-input-form-tit"></div>
<input
type="text"
className="input-frame"
readOnly={mode === 'READ'}
value={surveyInfo?.REPRESENTATIVE}
onChange={(e) => setSurveyInfo({ ...surveyInfo, REPRESENTATIVE: e.target.value })}
/>
</div>
<div className="data-input-form-bx">
<div className="data-input-form-tit"></div>
<input
type="text"
className="input-frame"
readOnly={mode === 'READ'}
value={surveyInfo?.BUILDING_NAME ?? ''}
onChange={(e) => setSurveyInfo({ ...surveyInfo, BUILDING_NAME: e.target.value })}
/>
</div>
<div className="data-input-form-bx">
<div className="data-input-form-tit"></div>
<input
type="text"
className="input-frame"
readOnly={mode === 'READ'}
value={surveyInfo?.CONSTRUCTION_POINT ?? ''}
onChange={(e) => setSurveyInfo({ ...surveyInfo, CONSTRUCTION_POINT: e.target.value })}
/>
</div>
</div>
</div>
<div className="sale-frame">
<div className="data-form-wrap">
<div className="data-input-form-bx">
<div className="data-input-form-tit">調</div>
{['CREATE', 'EDIT'].includes(mode as 'CREATE' | 'EDIT') ? (
<div className="date-input">
<button className="date-btn">
<i className="date-icon"></i>
</button>
<input type="text" className="date-frame" readOnly defaultValue={surveyInfo?.INVESTIGATION_DATE?.toString()} />
</div>
) : (
<input type="text" className="input-frame" disabled defaultValue={surveyInfo?.INVESTIGATION_DATE?.toString()} />
)}
</div>
<div className="data-input-form-bx">
{/* 건물명 */}
<div className="data-input-form-tit"></div>
<input type="text" className="input-frame" readOnly={mode === 'READ'} defaultValue={surveyInfo?.BUILDING_NAME ?? ''} />
</div>
<div className="data-input-form-bx">
{/* 고객명 */}
<div className="data-input-form-tit"></div>
<input type="text" className="input-frame" readOnly={mode === 'READ'} defaultValue={surveyInfo?.CUSTOMER_NAME ?? ''} />
</div>
<div className="data-input-form-bx">
<div className="data-input-form-tit">便/</div>
<div className="form-flex">
{/* 우편번호 */}
<div className="form-bx">
<input type="text" className="input-frame" readOnly={mode === 'READ'} defaultValue={surveyInfo?.POST_CODE ?? ''} disabled />
</div>
{/* 도도부현 */}
<div className="form-bx">
<input type="text" className="input-frame" readOnly={mode === 'READ'} defaultValue={surveyInfo?.ADDRESS ?? ''} disabled />
</div>
</div>
{/* 주소 */}
<div className="data-input mt5">
<input type="text" className="input-frame" readOnly={mode === 'READ'} defaultValue={'浜松浜松町'} disabled />
</div>
<div className="form-btn">
<button className="btn-frame n-blue icon">
便<i className="btn-arr"></i>
</button>
</div>
</div>
<div className="sale-frame">
<div className="data-form-wrap">
<div className="data-input-form-bx">
<div className="data-input-form-tit">調</div>
<div className="date-input">
<button className="date-btn">
<i className="date-icon"></i>
</button>
<input type="text" className="date-frame" defaultValue={'2025.04.16'} />
</div>
</div>
<div className="data-input-form-bx">
<div className="data-input-form-tit"></div>
<input type="text" className="input-frame" defaultValue={'ギルドン'} />
</div>
<div className="data-input-form-bx">
<div className="data-input-form-tit"></div>
<input type="text" className="input-frame" defaultValue={'HWJ Building'} />
</div>
<div className="data-input-form-bx">
<div className="data-input-form-tit"></div>
<div className="form-flex">
<div className="form-bx">
<input type="text" className="input-frame" defaultValue={'1050013'} disabled />
</div>
<div className="form-bx">
<select className="select-form" name="" id="">
<option value=""></option>
<option value=""></option>
<option value=""></option>
<option value=""></option>
<option value=""></option>
</select>
<div className="data-input-form-bx">
<div className="data-input-form-tit">, </div>
<input type="text" className="input-frame" defaultValue={'浜松 浜松町'} />
</div>
</div>
<div className="form-btn">
<button className="btn-frame n-blue icon">
便<i className="btn-arr"></i>
</button>
</div>
</div>
<div className="data-input-form-bx">
<div className="data-input-form-tit">, </div>
<input type="text" className="input-frame" defaultValue={'浜松 浜松町'} />
</div>
</div>
<div className="btn-flex-wrap">
<div className="btn-bx">
<button className="btn-frame n-blue icon">
<i className="btn-arr"></i>
</button>
</div>
<div className="btn-bx">
<button className="btn-frame red icon">
<i className="btn-arr"></i>
</button>
</div>
<div className="btn-bx">
<button className="btn-frame n-blue icon">
<i className="btn-arr"></i>
</button>
</div>
</div>
</div>

View File

@ -0,0 +1,81 @@
import { Mode } from '@/types/Survey'
export default function ButtonForm(props: { mode: Mode; setMode: (mode: Mode) => void }) {
const { mode, setMode } = props
return (
<>
{mode === 'CREATE' && (
<div className="sale-form-btn-wrap">
<div className="btn-flex-wrap">
<div className="btn-bx">
{/* 임시저장 */}
<button className="btn-frame n-blue icon" onClick={() => setMode('TEMP')}>
<i className="btn-arr"></i>
</button>
</div>
<div className="btn-bx">
{/* 저장 */}
<button className="btn-frame red icon">
<i className="btn-arr"></i>
</button>
</div>
<div className="btn-bx">
{/* 목록 */}
<button className="btn-frame n-blue icon">
<i className="btn-arr"></i>
</button>
</div>
</div>
</div>
)}
{mode === 'TEMP' && (
<div className="sale-form-btn-wrap">
<div className="btn-flex-wrap">
<div className="btn-bx">
{/* 수정 */}
<button className="btn-frame n-blue icon" onClick={() => setMode('EDIT')}>
<i className="btn-arr"></i>
</button>
</div>
<div className="btn-bx">
{/* 삭제 */}
<button className="btn-frame n-blue icon">
<i className="btn-arr"></i>
</button>
</div>
</div>
</div>
)}
{mode === 'EDIT' && (
<div className="sale-form-btn-wrap">
<div className="btn-flex-wrap">
<div className="btn-bx">
{/* 목록 */}
<button className="btn-frame n-blue icon">
<i className="btn-arr"></i>
</button>
</div>
<div className="btn-bx">
{/* 제출 */}
<button className="btn-frame red icon">
<i className="btn-arr"></i>
</button>
</div>
<div className="btn-bx">
{/* 수정 */}
<button className="btn-frame n-blue icon" onClick={() => setMode('EDIT')}>
<i className="btn-arr"></i>
</button>
</div>
<div className="btn-bx">
{/* 삭제 */}
<button className="btn-frame n-blue icon">
<i className="btn-arr"></i>
</button>
</div>
</div>
</div>
)}
</>
)
}

View File

@ -3,7 +3,7 @@
export default function DataTable() {
return (
<>
<div className="sale-frame">
<div className="sale-data-table-wrap">
<table className="sale-data-table">
<colgroup>
<col style={{ width: '80px' }} />

View File

@ -1,62 +1,53 @@
'use client'
export default function DetailForm() {
import { Mode, SurveyBasicInfo } from '@/types/Survey'
import { useEffect, useState } from 'react'
import ButtonForm from './ButtonForm'
import BasicForm from './BasicForm'
import RoofForm from './RoofForm'
export default function DetailForm(props: { surveyInfo?: SurveyBasicInfo; mode?: Mode }) {
const [surveyInfo, setSurveyInfo] = useState<Partial<SurveyBasicInfo>>(
props.surveyInfo ?? {
REPRESENTATIVE: '',
CONSTRUCTION_POINT: '',
STORE: '',
INVESTIGATION_DATE: '',
BUILDING_NAME: '',
CUSTOMER_NAME: '',
POST_CODE: '',
ADDRESS: '',
ADDRESS_DETAIL: '',
SUBMISSION_STATUS: true,
SUBMISSION_DATE: '2021-01-01',
DETAIL_INFO: null,
REG_DT: new Date(),
UPT_DT: new Date(),
},
)
const [roofValue, setRoofValue] = useState<Boolean>(false)
const [mode, setMode] = useState<Mode>(props.mode ?? 'CREATE')
const basicInfoProps = { surveyInfo, setSurveyInfo, mode }
const roofInfoProps = { surveyInfo, mode }
const buttonFormProps = { mode, setMode }
useEffect(() => {
// setMode(props.surveyInfo ? 'EDIT' : 'CREATE')
}, [props.surveyInfo])
useEffect(() => {
console.log(surveyInfo)
}, [surveyInfo])
return (
<>
<div className="sale-frame">
<div className="data-form-wrap">
<div className="data-input-form-bx">
<div className="data-input-form-tit"></div>
<input type="text" className="input-frame" disabled defaultValue={'HG'} />
</div>
<div className="data-input-form-bx">
<div className="data-input-form-tit"></div>
<input type="text" className="input-frame" disabled defaultValue={'HWJ(T01)'} />
</div>
<div className="data-input-form-bx">
<div className="data-input-form-tit"></div>
<input type="text" className="input-frame" disabled defaultValue={'施工点名表示'} />
</div>
</div>
</div>
<div className="sale-frame">
<div className="data-form-wrap">
<div className="data-input-form-bx">
<div className="data-input-form-tit">調</div>
<input type="text" className="input-frame" disabled defaultValue={'2025/04/05'} />
</div>
<div className="data-input-form-bx">
<div className="data-input-form-tit"></div>
<input type="text" className="input-frame" disabled defaultValue={'ハンファジャパンビル'} />
</div>
<div className="data-input-form-bx">
<div className="data-input-form-tit"></div>
<input type="text" className="input-frame" disabled defaultValue={'Hong gi'} />
</div>
</div>
<div className="btn-flex-wrap">
<div className="btn-bx">
<button className="btn-frame n-blue icon">
<i className="btn-arr"></i>
</button>
</div>
<div className="btn-bx">
<button className="btn-frame red icon">
<i className="btn-arr"></i>
</button>
</div>
<div className="btn-bx">
<button className="btn-frame n-blue icon">
<i className="btn-arr"></i>
</button>
</div>
<div className="btn-bx">
<button className="btn-frame n-blue icon">
<i className="btn-arr"></i>
</button>
</div>
</div>
<div className="sale-detail-toggle-wrap">
{mode}
{/* 기본정보 */}
<BasicForm {...basicInfoProps} />
{/* 전기/지붕정보 */}
<RoofForm {...roofInfoProps} />
<ButtonForm {...buttonFormProps} />
</div>
</>
)

View File

@ -0,0 +1,396 @@
import { useState } from 'react'
import { Mode, SurveyBasicInfo } from '@/types/Survey'
export default function RoofForm(props: { surveyInfo: Partial<SurveyBasicInfo>; mode: Mode }) {
const { surveyInfo, mode } = props
const [isFlip, setIsFlip] = useState<boolean>(true)
return (
<div className={`sale-detail-toggle-bx ${isFlip ? 'act' : ''}`}>
<div className="sale-detail-toggle-head" onClick={() => setIsFlip(!isFlip)}>
<div className="sale-detail-toggle-name"> / </div>
<div className="sale-detail-toggle-btn-wrap">
<button className="sale-detail-toggle-btn"></button>
</div>
</div>
<div className="sale-detail-toggle-cont">
<div className="sale-frame">
{/* 전기 관계 */}
<div className="sale-roof-title"></div>
<div className="data-form-wrap">
<div className="data-input-form-bx">
{/* 전기 계약 용량 */}
<div className="data-input-form-tit"></div>
<div className="data-input mb5">
<input type="text" className="input-frame" defaultValue={'10'} readOnly={mode === 'READ'} />
</div>
{mode === 'READ' && <input type="text" className="input-frame" defaultValue={'10'} readOnly={mode === 'READ'} />}
{mode !== 'READ' && (
<div className="data-input">
<select className="select-form" name="" id="">
<option value="">kVA</option>
<option value="">kVA</option>
<option value="">kVA</option>
<option value="">kVA</option>
<option value="">kVA</option>
</select>
</div>
)}
</div>
<div className="data-input-form-bx">
{/* 전기 소매 회사사 */}
<div className="data-input-form-tit"></div>
<input type="text" className="input-frame" defaultValue={'HWJ Electric'} readOnly={mode === 'READ'} />
</div>
<div className="data-input-form-bx">
{/* 전기 부대 설비 */}
<div className="data-input-form-tit">
<span></span>
</div>
<div className="data-check-wrap">
<div className="check-form-box">
<input type="checkbox" id="ch01" readOnly={mode === 'READ'} />
<label htmlFor="ch01"></label>
</div>
<div className="check-form-box">
<input type="checkbox" id="ch02" readOnly={mode === 'READ'} />
<label htmlFor="ch02"></label>
</div>
<div className="check-form-box">
<input type="checkbox" id="ch03" readOnly={mode === 'READ'} />
<label htmlFor="ch03"></label>
</div>
<div className="check-form-box">
<input type="checkbox" id="ch04" readOnly={mode === 'READ'} />
<label htmlFor="ch04"></label>
</div>
<div className="check-form-box">
<input type="checkbox" id="ch05" readOnly={mode === 'READ'} />
<label htmlFor="ch05"> ()</label>
</div>
</div>
<div className="data-input">
<input type="text" className="input-frame" disabled defaultValue={''} />
</div>
</div>
<div className="data-input-form-bx">
{/* 설치 희망 시스템 */}
<div className="data-input-form-tit red-f"></div>
{mode === 'READ' && (
<div className="data-input">
<input type="text" className="input-frame" defaultValue={''} disabled />
</div>
)}
{mode !== 'READ' && (
<div className="data-input mb5">
<select className="select-form" name="" id="">
<option value=""></option>
<option value=""></option>
<option value=""></option>
<option value=""></option>
<option value=""></option>
</select>
</div>
)}
</div>
</div>
</div>
<div className="sale-frame">
{/* 지붕 관계 */}
<div className="sale-roof-title"></div>
<div className="data-form-wrap">
<div className="data-input-form-bx">
{/* 건축 연수 */}
<div className="data-input-form-tit red-f"></div>
<div className="data-input mb5">
{mode === 'READ' && <input type="text" className="input-frame" defaultValue={''} disabled />}
{mode !== 'READ' && (
<select className="select-form" name="" id="">
<option value=""></option>
<option value=""></option>
<option value=""></option>
<option value=""></option>
<option value=""></option>
</select>
)}
</div>
<div className="data-input flex">
<input type="text" className="input-frame" defaultValue={''} disabled />
<span></span>
</div>
</div>
<div className="data-input-form-bx">
{/* 지붕재 */}
<div className="data-input-form-tit">
<span>2</span>
</div>
<div className="data-check-wrap">
<div className="check-form-box">
<input type="checkbox" id="ch01" readOnly={mode === 'READ'} />
<label htmlFor="ch01"></label>
</div>
<div className="check-form-box">
<input type="checkbox" id="ch02" readOnly={mode === 'READ'} />
<label htmlFor="ch02"></label>
</div>
<div className="check-form-box">
<input type="checkbox" id="ch03" readOnly={mode === 'READ'} />
<label htmlFor="ch03"></label>
</div>
<div className="check-form-box">
<input type="checkbox" id="ch04" readOnly={mode === 'READ'} />
<label htmlFor="ch04"></label>
</div>
<div className="check-form-box">
<input type="checkbox" id="ch05" readOnly={mode === 'READ'} />
<label htmlFor="ch05"> ()</label>
</div>
</div>
<div className="data-input">
<input type="text" className="input-frame" disabled defaultValue={''} />
</div>
</div>
<div className="data-input-form-bx">
{/* 지붕 모양 */}
<div className="data-input-form-tit"></div>
<div className="data-input mb5">
{mode === 'READ' && <input type="text" className="input-frame" defaultValue={''} disabled />}
{mode !== 'READ' && (
<select className="select-form" name="" id="">
<option value=""></option>
<option value=""></option>
<option value=""></option>
<option value=""></option>
<option value=""></option>
</select>
)}
</div>
<div className="data-input">
<input type="text" className="input-frame" defaultValue={''} disabled />
</div>
</div>
<div className="data-input-form-bx">
{/* 지붕 경사도도 */}
<div className="data-input-form-tit"></div>
<div className="data-input flex">
<input type="text" className="input-frame" defaultValue={'4'} readOnly={mode === 'READ'} />
<span></span>
</div>
</div>
<div className="data-input-form-bx">
{/* 주택구조조 */}
<div className="data-input-form-tit"></div>
<div className="radio-form-box mb10">
<input type="radio" name="radio01" id="ra01" readOnly={mode === 'READ'} />
<label htmlFor="ra01"></label>
</div>
<div className="radio-form-box mb10">
<input type="radio" name="radio01" id="ra02" readOnly={mode === 'READ'} />
<label htmlFor="ra02"> ()</label>
</div>
<div className="data-input">
<input type="text" className="input-frame" disabled defaultValue={''} />
</div>
</div>
<div className="data-input-form-bx">
{/* 서까래 재질 */}
<div className="data-input-form-tit"></div>
<div className="data-check-wrap">
<div className="radio-form-box">
<input type="radio" name="radio02" id="ra03" readOnly={mode === 'READ'} />
<label htmlFor="ra03"></label>
</div>
<div className="radio-form-box">
<input type="radio" name="radio02" id="ra04" readOnly={mode === 'READ'} />
<label htmlFor="ra04"></label>
</div>
<div className="radio-form-box">
<input type="radio" name="radio02" id="ra05" readOnly={mode === 'READ'} />
<label htmlFor="ra05"> ()</label>
</div>
</div>
<div className="data-input">
<input type="text" className="input-frame" disabled defaultValue={''} />
</div>
</div>
<div className="data-input-form-bx">
{/* 서까래 크기 */}
<div className="data-input-form-tit red-f"></div>
<div className="data-input mb5">
{mode === 'READ' && <input type="text" className="input-frame" defaultValue={''} disabled />}
{mode !== 'READ' && (
<select className="select-form" name="" id="">
<option value="">35mm以上×48mm以上</option>
<option value="">35mm以上×48mm以上</option>
<option value="">35mm以上×48mm以上</option>
<option value="">35mm以上×48mm以上</option>
<option value="">35mm以上×48mm以上</option>
</select>
)}
</div>
<div className="data-input">
<input type="text" className="input-frame" defaultValue={''} disabled />
</div>
</div>
<div className="data-input-form-bx">
{/* 서까래 피치 */}
<div className="data-input-form-tit red-f"></div>
<div className="data-input mb5">
{mode === 'READ' && <input type="text" className="input-frame" defaultValue={''} disabled />}
{mode !== 'READ' && (
<select className="select-form" name="" id="">
<option value="">455mm以下</option>
<option value="">455mm以下</option>
<option value="">455mm以下</option>
<option value="">455mm以下</option>
<option value="">455mm以下</option>
</select>
)}
</div>
<div className="data-input">
<input type="text" className="input-frame" defaultValue={''} disabled />
</div>
</div>
<div className="data-input-form-bx">
{/* 서까래 방향 */}
<div className="data-input-form-tit red-f"></div>
<div className="data-check-wrap mb0">
<div className="radio-form-box">
<input type="radio" name="radio03" id="ra06" readOnly={mode === 'READ'} />
<label htmlFor="ra06"></label>
</div>
<div className="radio-form-box">
<input type="radio" name="radio03" id="ra07" readOnly={mode === 'READ'} />
<label htmlFor="ra07"></label>
</div>
</div>
</div>
<div className="data-input-form-bx">
{/* 노지판 종류류 */}
<div className="data-input-form-tit"></div>
<div className="data-input mb5">
{mode === 'READ' && <input type="text" className="input-frame" defaultValue={''} disabled />}
{mode !== 'READ' && (
<select className="select-form" name="" id="">
<option value=""></option>
<option value=""></option>
<option value=""></option>
<option value=""></option>
<option value=""></option>
</select>
)}
</div>
<div className="data-input">
<input type="text" className="input-frame" defaultValue={''} disabled />
</div>
</div>
<div className="data-input-form-bx">
<div className="data-input-form-tit">
<span>, . </span>
</div>
<div className="data-input flex">
<input type="text" className="input-frame" defaultValue={'150'} readOnly={mode === 'READ'} />
<span>mm</span>
</div>
</div>
<div className="data-input-form-bx">
{/* 서까래 방향 */}
<div className="data-input-form-tit "></div>
<div className="data-check-wrap mb0">
<div className="radio-form-box">
<input type="radio" name="radio04" id="ra08" readOnly={mode === 'READ'} />
<label htmlFor="ra08"></label>
</div>
<div className="radio-form-box">
<input type="radio" name="radio04" id="ra09" readOnly={mode === 'READ'} />
<label htmlFor="ra09"></label>
</div>
</div>
</div>
<div className="data-input-form-bx">
{/* 주택 구조 */}
<div className="data-input-form-tit red-f"></div>
<div className="radio-form-box mb10">
<input type="radio" name="radio05" id="ra10" readOnly={mode === 'READ'} />
<label htmlFor="ra10">94022kg以上</label>
</div>
<div className="radio-form-box mb10">
<input type="radio" name="radio05" id="ra11" readOnly={mode === 'READ'} />
<label htmlFor="ra11"> ()</label>
</div>
<div className="data-input">
<input type="text" className="input-frame" disabled defaultValue={''} />
</div>
</div>
<div className="data-input-form-bx">
{/* 단열재 유무 */}
<div className="data-input-form-tit red-f"></div>
<div className="radio-form-box mb10">
<input type="radio" name="radio06" id="ra12" readOnly={mode === 'READ'} />
<label htmlFor="ra12"></label>
</div>
<div className="data-input mb10">
<input type="text" className="input-frame" defaultValue={''} readOnly={mode === 'READ'} />
</div>
<div className="radio-form-box">
<input type="radio" name="radio06" id="ra13" readOnly={mode === 'READ'} />
<label htmlFor="ra13"></label>
</div>
</div>
<div className="data-input-form-bx">
{/* 지붕 구조의 순서 */}
<div className="data-input-form-tit red-f"></div>
<div className="data-input mb5">
{mode === 'READ' && <input type="text" className="input-frame" defaultValue={''} disabled />}
{mode !== 'READ' && (
<select className="select-form" name="" id="">
<option value="">///</option>
<option value="">///</option>
<option value="">///</option>
<option value="">///</option>
<option value="">///</option>
</select>
)}
</div>
<div className="data-input">
<input type="text" className="input-frame" defaultValue={''} readOnly={mode === 'READ'} />
</div>
</div>
<div className="data-input-form-bx">
{/* 지붕 제품명 설치 가능 여부 확인 */}
<div className="data-input-form-tit"> </div>
<div className="data-input mb5">
{mode === 'READ' && <input type="text" className="input-frame" defaultValue={''} disabled />}
{mode !== 'READ' && (
<select className="select-form" name="" id="">
<option value=""></option>
<option value=""></option>
<option value=""></option>
<option value=""></option>
<option value=""></option>
</select>
)}
</div>
<div className="data-input">
<input type="text" className="input-frame" defaultValue={''} readOnly={mode === 'READ'} />
</div>
</div>
<div className="data-input-form-bx">
{/* 메모 */}
<div className="data-input-form-tit"></div>
<div className="data-input">
<textarea
className="textarea-form"
name=""
id=""
defaultValue={'漏れの兆候があるため、正確な点検が必要です.'}
placeholder="TextArea Filed"
readOnly={mode === 'READ'}
></textarea>
</div>
</div>
</div>
</div>
</div>
</div>
)
}

View File

@ -1,8 +1,17 @@
'use client'
import Link from 'next/link'
export default function Footer() {
return (
<>
<footer>
<div className="footer-inner">COPYRIGHT©2025 Hanwha Japan All Rights Reserved</div>
<div className="footer-inner">
COPYRIGHT©2025 Hanwha Japan All Rights Reserved{' '}
<span>
<Link href="/pdf">PDF</Link>
</span>
</div>
</footer>
</>
)

View File

@ -1,35 +1,55 @@
import axios from 'axios'
import { tracking } from './tracking'
export const axiosInstance = (url: string | null | undefined) => {
const baseURL = url || process.env.NEXT_PUBLIC_API_URL
return axios.create({
const instance = axios.create({
baseURL,
headers: {
Accept: 'application/json',
},
})
instance.interceptors.request.use(
(config) => {
console.log('🚀 ~ config:', config)
return config
},
(error) => {
return Promise.reject(error)
},
)
axios.interceptors.response.use(
(response) => transferResponse(response),
(error) => {
// 에러 처리 로직
return Promise.reject(error)
},
)
return instance
}
// Request interceptor
axios.interceptors.request.use(
(config) => {
// 여기에 토큰 추가 등의 공통 로직을 넣을 수 있습니다
return config
},
(error) => {
return Promise.reject(error)
},
)
// axios.interceptors.request.use(
// (config) => {
// // 여기에 토큰 추가 등의 공통 로직을 넣을 수 있습니다
// return config
// },
// (error) => {
// return Promise.reject(error)
// },
// )
// Response interceptor
axios.interceptors.response.use(
(response) => transferResponse(response),
(error) => {
// 에러 처리 로직
return Promise.reject(error)
},
)
// axios.interceptors.response.use(
// (response) => transferResponse(response),
// (error) => {
// // 에러 처리 로직
// return Promise.reject(error)
// },
// )
// response데이터가 array, object에 따라 분기하여 키 변환
const transferResponse = (response: any) => {

10
src/libs/tracking.ts Normal file
View File

@ -0,0 +1,10 @@
import { axiosInstance } from './axios'
export const tracking = async (params: { url: string; data: string }) => {
const { url, data } = params
const result = await axiosInstance(null).post('/api/tracking', {
url,
data,
})
console.log('🚀 ~ result ~ result:', result)
}

View File

@ -1,5 +1,3 @@
import { SEARCH_OPTIONS_ENUM, SEARCH_OPTIONS_PARTNERS_ENUM, SORT_OPTIONS_ENUM } from '@/store/surveyFilterStore'
export type SurveyBasicInfo = {
ID: number
REPRESENTATIVE: string
@ -130,3 +128,5 @@ export type SurveyRegistRequest = {
SUBMISSION_DATE: string | null
DETAIL_INFO: SurveyDetailRequest | null
}
export type Mode = 'CREATE' | 'EDIT' | 'READ' | 'TEMP' // 등록 | 수정 | 상세 | 임시저장