Compare commits
27 Commits
5893cd6491
...
19a11783d6
| Author | SHA1 | Date | |
|---|---|---|---|
| 19a11783d6 | |||
| 5d5ba2e82a | |||
| a2e6c2343a | |||
| b783ca92d7 | |||
| c212ed0ad6 | |||
| 70c5af70f5 | |||
| ed8c6187d3 | |||
| 7597700e7b | |||
| 8fc88f526d | |||
|
|
855dedce44 | ||
| 77895c220d | |||
| 042096c682 | |||
| 298b563977 | |||
| 36a06c226b | |||
|
|
96b5e39a58 | ||
|
|
1af57d0965 | ||
| 3eb5974414 | |||
| a573d7ffb1 | |||
|
|
420c481b84 | ||
| 44d7a52790 | |||
| 99b37e3ac3 | |||
| f8d1cb54b6 | |||
| 7c724f2430 | |||
| 38ff8ce65f | |||
| 74865df3ba | |||
| 15114d8da0 | |||
| 907c92a546 |
16
.env
16
.env
@ -1,16 +0,0 @@
|
|||||||
# Environment variables declared in this file are automatically made available to Prisma.
|
|
||||||
# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema
|
|
||||||
|
|
||||||
# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
|
|
||||||
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
|
|
||||||
|
|
||||||
# DATABASE_URL="sqlserver://3team.devgrr.kr:1433;database=onsitesurvey;user=sa;password=1q2w3e4r!;encrypt=true;trustServerCertificate=true;"
|
|
||||||
DATABASE_URL="sqlserver://3team.devgrr.kr:1433;database=onsitesurvey;user=sa;password=1q2w3e4r!;encrypt=true;trustServerCertificate=true;connectionTimeout=30000;applicationName=OnSiteSurvey"
|
|
||||||
# DATABASE_URL="sqlserver://172.16.56.60:14331;database=hanwha_qcells_jp;user=qcells_jp;password=zbtpf2022!;encrypt=true;trustServerCertificate=true;applicationName=OnSiteSurvey"
|
|
||||||
# DATABASE_URL="mysql://root:root@localhost:3306/onsitesurvey"
|
|
||||||
DATABASE_CONNECTION_LIMIT=10
|
|
||||||
DATABASE_POOL_MIN=2
|
|
||||||
DATABASE_POOL_MAX=10
|
|
||||||
|
|
||||||
# SESSION_PASSWORD="QWERASDFZXCV1234567890REWQFDSAVCXZ"
|
|
||||||
SESSION_PASSWORD="This application is for mobile field research"
|
|
||||||
@ -1,8 +1,17 @@
|
|||||||
NEXT_PUBLIC_RUN_MODE=development
|
NEXT_PUBLIC_RUN_MODE=development
|
||||||
|
|
||||||
|
DATABASE_URL="sqlserver://172.16.56.60:14331;database=hanwha_qcells_jp;user=qcells_jp;password=zbtpf2022!;encrypt=true;trustServerCertificate=true;applicationName=OnSiteSurvey"
|
||||||
|
DATABASE_CONNECTION_LIMIT=10
|
||||||
|
DATABASE_POOL_MIN=2
|
||||||
|
DATABASE_POOL_MAX=10
|
||||||
|
|
||||||
|
SESSION_PASSWORD="This application is for mobile field research"
|
||||||
|
|
||||||
# 모바일 디바이스로 로컬 서버 확인하려면 자신 IP 주소로 변경
|
# 모바일 디바이스로 로컬 서버 확인하려면 자신 IP 주소로 변경
|
||||||
# 다시 로컬에서 개발할때는 localhost로 변경
|
# 다시 로컬에서 개발할때는 localhost로 변경
|
||||||
#route handler
|
#route handler
|
||||||
NEXT_PUBLIC_API_URL=http://localhost:3000
|
# NEXT_PUBLIC_API_URL=http://172.16.56.60:3000
|
||||||
|
NEXT_PUBLIC_API_URL=https://dev.hanasysfield.jp
|
||||||
|
|
||||||
#qsp 로그인 api
|
#qsp 로그인 api
|
||||||
NEXT_PUBLIC_QSP_API_URL=http://121.168.9.37:8080
|
NEXT_PUBLIC_QSP_API_URL=http://121.168.9.37:8080
|
||||||
|
|||||||
@ -1,4 +1,12 @@
|
|||||||
NEXT_PUBLIC_RUN_MODE=local
|
NEXT_PUBLIC_RUN_MODE=local
|
||||||
|
|
||||||
|
DATABASE_URL="sqlserver://172.16.56.60:14331;database=hanwha_qcells_jp;user=qcells_jp;password=zbtpf2022!;encrypt=true;trustServerCertificate=true;applicationName=OnSiteSurvey"
|
||||||
|
DATABASE_CONNECTION_LIMIT=10
|
||||||
|
DATABASE_POOL_MIN=2
|
||||||
|
DATABASE_POOL_MAX=10
|
||||||
|
|
||||||
|
SESSION_PASSWORD="This application is for mobile field research"
|
||||||
|
|
||||||
# 모바일 디바이스로 로컬 서버 확인하려면 자신 IP 주소로 변경
|
# 모바일 디바이스로 로컬 서버 확인하려면 자신 IP 주소로 변경
|
||||||
# 다시 로컬에서 개발할때는 localhost로 변경
|
# 다시 로컬에서 개발할때는 localhost로 변경
|
||||||
#route handler
|
#route handler
|
||||||
|
|||||||
@ -1,6 +1,15 @@
|
|||||||
NEXT_PUBLIC_RUN_MODE=production
|
NEXT_PUBLIC_RUN_MODE=production
|
||||||
|
|
||||||
|
DATABASE_URL="sqlserver://172.16.56.57:14331;database=hanwha_qcells_jp;user=qcells_jp;password=zbtpf2022!;encrypt=true;trustServerCertificate=true;applicationName=OnSiteSurvey"
|
||||||
|
DATABASE_CONNECTION_LIMIT=10
|
||||||
|
DATABASE_POOL_MIN=2
|
||||||
|
DATABASE_POOL_MAX=10
|
||||||
|
|
||||||
|
SESSION_PASSWORD="This application is for mobile field research"
|
||||||
|
|
||||||
#route handler
|
#route handler
|
||||||
NEXT_PUBLIC_API_URL=http://localhost:3000
|
# NEXT_PUBLIC_API_URL=http://localhost:3000
|
||||||
|
NEXT_PUBLIC_API_URL=https://hanasysfield.jp
|
||||||
|
|
||||||
#qsp 로그인 api
|
#qsp 로그인 api
|
||||||
# NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120
|
# NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120
|
||||||
|
|||||||
4
.gitignore
vendored
4
.gitignore
vendored
@ -46,3 +46,7 @@ next-env.d.ts
|
|||||||
bun.lockb
|
bun.lockb
|
||||||
pnpm-lock.yaml
|
pnpm-lock.yaml
|
||||||
pnpm-workspace.yaml
|
pnpm-workspace.yaml
|
||||||
|
|
||||||
|
# logs
|
||||||
|
logs/
|
||||||
|
*.log
|
||||||
|
|||||||
2
dev.startscript.js
Normal file
2
dev.startscript.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
var exec = require('child_process').exec
|
||||||
|
exec('pnpm run start:dev', { windowsHide: true })
|
||||||
@ -6,7 +6,12 @@ const nextConfig: NextConfig = {
|
|||||||
sassOptions: {
|
sassOptions: {
|
||||||
includePaths: [path.join(__dirname, './src/styles')],
|
includePaths: [path.join(__dirname, './src/styles')],
|
||||||
},
|
},
|
||||||
serverExternalPackages: ['@react-pdf/renderer'],
|
serverExternalPackages: ['@react-pdf/renderer', 'pino'],
|
||||||
|
logging: {
|
||||||
|
fetches: {
|
||||||
|
fullUrl: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
async rewrites() {
|
async rewrites() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@ -19,6 +24,22 @@ const nextConfig: NextConfig = {
|
|||||||
// },
|
// },
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
webpack: (config, { dev, isServer }) => {
|
||||||
|
if (!dev && !isServer) {
|
||||||
|
config.optimization.minimizer = config.optimization.minimizer || []
|
||||||
|
config.optimization.minimizer.push(
|
||||||
|
new (require('terser-webpack-plugin'))({
|
||||||
|
terserOptions: {
|
||||||
|
format: {
|
||||||
|
comments: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
extractComments: false,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export default nextConfig
|
export default nextConfig
|
||||||
|
|||||||
@ -29,6 +29,7 @@
|
|||||||
"next": "15.2.4",
|
"next": "15.2.4",
|
||||||
"nodemailer": "^7.0.3",
|
"nodemailer": "^7.0.3",
|
||||||
"pdf-lib": "^1.17.1",
|
"pdf-lib": "^1.17.1",
|
||||||
|
"pino": "^9.7.0",
|
||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-to-pdf": "^2.0.0",
|
"react-to-pdf": "^2.0.0",
|
||||||
@ -45,6 +46,7 @@
|
|||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
"prisma": "^6.7.0",
|
"prisma": "^6.7.0",
|
||||||
"tailwindcss": "^4",
|
"tailwindcss": "^4",
|
||||||
|
"terser-webpack-plugin": "^5.3.14",
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
prod.startscript.js
Normal file
2
prod.startscript.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
var exec = require('child_process').exec
|
||||||
|
exec('pnpm run start:prod', { windowsHide: true })
|
||||||
@ -1,7 +1,8 @@
|
|||||||
import { NextResponse } from 'next/server'
|
import { NextResponse } from 'next/server'
|
||||||
|
import { loggerWrapper } from '@/libs/api-wrapper'
|
||||||
import { axiosInstance } from '@/libs/axios'
|
import { axiosInstance } from '@/libs/axios'
|
||||||
|
|
||||||
export async function POST(req: Request) {
|
async function setChgPwd(req: Request): Promise<NextResponse> {
|
||||||
const { loginId, email, pwd, chgPwd } = await req.json()
|
const { loginId, email, pwd, chgPwd } = await req.json()
|
||||||
console.log('🚀 ~ POST ~ loginId:', loginId)
|
console.log('🚀 ~ POST ~ loginId:', loginId)
|
||||||
console.log('🚀 ~ POST ~ email:', email)
|
console.log('🚀 ~ POST ~ email:', email)
|
||||||
@ -19,3 +20,5 @@ export async function POST(req: Request) {
|
|||||||
|
|
||||||
return NextResponse.json({ code: 200, data: result.data })
|
return NextResponse.json({ code: 200, data: result.data })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const POST = loggerWrapper(setChgPwd)
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import { NextRequest, NextResponse } from 'next/server'
|
import { NextRequest, NextResponse } from 'next/server'
|
||||||
|
import { loggerWrapper } from '@/libs/api-wrapper'
|
||||||
import { prisma } from '@/libs/prisma'
|
import { prisma } from '@/libs/prisma'
|
||||||
import type { CommCode } from '@/types/CommCode'
|
import type { CommCode } from '@/types/CommCode'
|
||||||
|
|
||||||
export async function GET(request: NextRequest) {
|
async function getCommCode(request: NextRequest): Promise<NextResponse> {
|
||||||
try {
|
try {
|
||||||
const searchParams = request.nextUrl.searchParams
|
const searchParams = request.nextUrl.searchParams
|
||||||
const headCode = searchParams.get('headCode')
|
const headCode = searchParams.get('headCode')
|
||||||
@ -20,6 +21,10 @@ export async function GET(request: NextRequest) {
|
|||||||
if (!headCd) {
|
if (!headCd) {
|
||||||
return NextResponse.json({ error: `${headCode}를 찾을 수 없습니다` }, { status: 404 })
|
return NextResponse.json({ error: `${headCode}를 찾을 수 없습니다` }, { status: 404 })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (headCode === 'SALES_OFFICE_CD') {
|
||||||
|
return getSaleOffice(headCd.HEAD_CD)
|
||||||
|
} else {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const roofMaterials: CommCode[] = await prisma.BC_COMM_L.findMany({
|
const roofMaterials: CommCode[] = await prisma.BC_COMM_L.findMany({
|
||||||
where: {
|
where: {
|
||||||
@ -34,10 +39,8 @@ export async function GET(request: NextRequest) {
|
|||||||
CODE: 'asc',
|
CODE: 'asc',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
if (headCode === 'SALES_OFFICE_CD') {
|
|
||||||
return getSaleOffice(headCd.HEAD_CD)
|
|
||||||
}
|
|
||||||
return NextResponse.json(roofMaterials)
|
return NextResponse.json(roofMaterials)
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ 데이터 조회 중 오류가 발생했습니다:', error)
|
console.error('❌ 데이터 조회 중 오류가 발생했습니다:', error)
|
||||||
return NextResponse.json({ error: '데이터 조회 중 오류가 발생했습니다' }, { status: 500 })
|
return NextResponse.json({ error: '데이터 조회 중 오류가 발생했습니다' }, { status: 500 })
|
||||||
@ -60,3 +63,5 @@ const getSaleOffice = async (headCode: string) => {
|
|||||||
})
|
})
|
||||||
return NextResponse.json(commCodeSaleOffice)
|
return NextResponse.json(commCodeSaleOffice)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const GET = loggerWrapper(getCommCode)
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import { queryStringFormatter } from '@/utils/common-utils'
|
import { queryStringFormatter } from '@/utils/common-utils'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { NextResponse } from 'next/server'
|
import { NextResponse } from 'next/server'
|
||||||
|
import { loggerWrapper } from '@/libs/api-wrapper'
|
||||||
|
|
||||||
export async function GET(request: Request) {
|
async function getQnaDetail(request: Request): Promise<NextResponse> {
|
||||||
const { searchParams } = new URL(request.url)
|
const { searchParams } = new URL(request.url)
|
||||||
const params = {
|
const params = {
|
||||||
compCd: searchParams.get('compCd'),
|
compCd: searchParams.get('compCd'),
|
||||||
@ -22,3 +23,5 @@ export async function GET(request: Request) {
|
|||||||
return NextResponse.json({ error: 'route error' }, { status: 500 })
|
return NextResponse.json({ error: 'route error' }, { status: 500 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const GET = loggerWrapper(getQnaDetail)
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { NextResponse } from 'next/server'
|
import { NextResponse } from 'next/server'
|
||||||
|
import { loggerWrapper } from '@/libs/api-wrapper'
|
||||||
|
|
||||||
// export async function GET(request: Request) {
|
// export async function GET(request: Request) {
|
||||||
// const { searchParams } = new URL(request.url)
|
// const { searchParams } = new URL(request.url)
|
||||||
@ -38,7 +39,7 @@ import { NextResponse } from 'next/server'
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
export async function GET(request: Request) {
|
async function downloadFile(request: Request): Promise<NextResponse> {
|
||||||
const { searchParams } = new URL(request.url)
|
const { searchParams } = new URL(request.url)
|
||||||
const encodeFileNo = searchParams.get('encodeFileNo')
|
const encodeFileNo = searchParams.get('encodeFileNo')
|
||||||
const srcFileNm = searchParams.get('srcFileNm') || 'downloaded-file'
|
const srcFileNm = searchParams.get('srcFileNm') || 'downloaded-file'
|
||||||
@ -71,3 +72,5 @@ export async function GET(request: Request) {
|
|||||||
return NextResponse.json({ error: error.response?.data || 'Failed to download file' }, { status: 500 })
|
return NextResponse.json({ error: error.response?.data || 'Failed to download file' }, { status: 500 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const GET = loggerWrapper(downloadFile)
|
||||||
|
|||||||
@ -3,10 +3,11 @@ import { NextResponse } from 'next/server'
|
|||||||
import { queryStringFormatter } from '@/utils/common-utils'
|
import { queryStringFormatter } from '@/utils/common-utils'
|
||||||
import { getIronSession } from 'iron-session'
|
import { getIronSession } from 'iron-session'
|
||||||
import { cookies } from 'next/headers'
|
import { cookies } from 'next/headers'
|
||||||
|
import { loggerWrapper } from '@/libs/api-wrapper'
|
||||||
import { sessionOptions } from '@/libs/session'
|
import { sessionOptions } from '@/libs/session'
|
||||||
import { SessionData } from '@/types/Auth'
|
import { SessionData } from '@/types/Auth'
|
||||||
|
|
||||||
export async function GET(request: Request) {
|
async function getQnaList(request: Request): Promise<NextResponse> {
|
||||||
const cookieStore = await cookies()
|
const cookieStore = await cookies()
|
||||||
const session = await getIronSession<SessionData>(cookieStore, sessionOptions)
|
const session = await getIronSession<SessionData>(cookieStore, sessionOptions)
|
||||||
|
|
||||||
@ -37,3 +38,5 @@ export async function GET(request: Request) {
|
|||||||
return NextResponse.json({ error: 'route error' }, { status: 500 })
|
return NextResponse.json({ error: 'route error' }, { status: 500 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const GET = loggerWrapper(getQnaList)
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
import { NextResponse } from 'next/server'
|
import { NextResponse } from 'next/server'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { CommonCode } from '@/types/Inquiry'
|
import { CommonCode } from '@/types/Inquiry'
|
||||||
|
import { loggerWrapper } from '@/libs/api-wrapper'
|
||||||
|
|
||||||
export async function GET() {
|
async function getCommonCodeListData(request: Request): Promise<NextResponse> {
|
||||||
const response = await axios.get(`${process.env.NEXT_PUBLIC_INQUIRY_API_URL}/api/system/commonCodeListData`)
|
const response = await axios.get(`${process.env.NEXT_PUBLIC_INQUIRY_API_URL}/api/system/commonCodeListData`)
|
||||||
const codeList: CommonCode[] = []
|
const codeList: CommonCode[] = []
|
||||||
response.data.data.apiCommCdList.forEach((item: any) => {
|
response.data.data.apiCommCdList.forEach((item: any) => {
|
||||||
@ -17,3 +18,5 @@ export async function GET() {
|
|||||||
})
|
})
|
||||||
return NextResponse.json({ data: codeList })
|
return NextResponse.json({ data: codeList })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const GET = loggerWrapper(getCommonCodeListData)
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { NextResponse } from 'next/server'
|
import { NextResponse } from 'next/server'
|
||||||
|
import { loggerWrapper } from '@/libs/api-wrapper'
|
||||||
|
|
||||||
export async function POST(request: Request) {
|
async function setQna(request: Request): Promise<NextResponse> {
|
||||||
const formData = await request.formData()
|
const formData = await request.formData()
|
||||||
console.log(formData)
|
console.log(formData)
|
||||||
try {
|
try {
|
||||||
@ -19,3 +20,5 @@ export async function POST(request: Request) {
|
|||||||
return NextResponse.json({ error: 'Failed to save qna' }, { status: 500 })
|
return NextResponse.json({ error: 'Failed to save qna' }, { status: 500 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const POST = loggerWrapper(setQna)
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { prisma } from '@/libs/prisma'
|
import { prisma } from '@/libs/prisma'
|
||||||
import { NextRequest, NextResponse } from 'next/server'
|
import { NextRequest, NextResponse } from 'next/server'
|
||||||
|
import { loggerWrapper } from '@/libs/api-wrapper'
|
||||||
|
|
||||||
type AdminSubPerson = {
|
type AdminSubPerson = {
|
||||||
storeId: string
|
storeId: string
|
||||||
@ -8,7 +9,7 @@ type AdminSubPerson = {
|
|||||||
authority: string
|
authority: string
|
||||||
}
|
}
|
||||||
// 2차점이 자신에게 매핑 된 1차 판매점과 관리자 정보 조회
|
// 2차점이 자신에게 매핑 된 1차 판매점과 관리자 정보 조회
|
||||||
export async function GET(request: NextRequest) {
|
async function getSubMissionAdminSub(request: NextRequest): Promise<NextResponse> {
|
||||||
try {
|
try {
|
||||||
const { searchParams } = new URL(request.url)
|
const { searchParams } = new URL(request.url)
|
||||||
const id = searchParams.get('id')
|
const id = searchParams.get('id')
|
||||||
@ -40,3 +41,5 @@ export async function GET(request: NextRequest) {
|
|||||||
return NextResponse.json({ error: '데이터 조회 중 오류가 발생했습니다' }, { status: 500 })
|
return NextResponse.json({ error: '데이터 조회 중 오류가 발생했습니다' }, { status: 500 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const GET = loggerWrapper(getSubMissionAdminSub)
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { prisma } from '@/libs/prisma'
|
import { prisma } from '@/libs/prisma'
|
||||||
import { NextRequest, NextResponse } from 'next/server'
|
import { NextRequest, NextResponse } from 'next/server'
|
||||||
|
import { loggerWrapper } from '@/libs/api-wrapper'
|
||||||
|
|
||||||
type SuperPerson = {
|
type SuperPerson = {
|
||||||
storeId: string
|
storeId: string
|
||||||
@ -8,7 +9,7 @@ type SuperPerson = {
|
|||||||
toEmail: string
|
toEmail: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function GET(request: NextRequest) {
|
async function getSubmissionAdmin(request: NextRequest): Promise<NextResponse> {
|
||||||
try {
|
try {
|
||||||
const { searchParams } = new URL(request.url)
|
const { searchParams } = new URL(request.url)
|
||||||
const id = searchParams.get('id')
|
const id = searchParams.get('id')
|
||||||
@ -44,3 +45,5 @@ export async function GET(request: NextRequest) {
|
|||||||
return NextResponse.json({ error: '데이터 조회 중 오류가 발생했습니다' }, { status: 500 })
|
return NextResponse.json({ error: '데이터 조회 중 오류가 발생했습니다' }, { status: 500 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const GET = loggerWrapper(getSubmissionAdmin)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { prisma } from '@/libs/prisma'
|
import { prisma } from '@/libs/prisma'
|
||||||
import { SubmitTargetResponse } from '@/types/Survey'
|
import { SubmitTargetResponse } from '@/types/Survey'
|
||||||
import { NextRequest, NextResponse } from 'next/server'
|
import { NextRequest, NextResponse } from 'next/server'
|
||||||
|
import { loggerWrapper } from '@/libs/api-wrapper'
|
||||||
|
|
||||||
type BuilderPerson = {
|
type BuilderPerson = {
|
||||||
agencyStoreId: string
|
agencyStoreId: string
|
||||||
@ -11,7 +12,7 @@ type BuilderPerson = {
|
|||||||
|
|
||||||
// 2차점의 시공권한 user가 해당 판매점의 관리자 정보 조회
|
// 2차점의 시공권한 user가 해당 판매점의 관리자 정보 조회
|
||||||
// N == 일반유저, S == 수퍼유저, B == 시공권한유저
|
// N == 일반유저, S == 수퍼유저, B == 시공권한유저
|
||||||
export async function GET(request: NextRequest) {
|
async function getSubmissionBuilder(request: NextRequest): Promise<NextResponse> {
|
||||||
try {
|
try {
|
||||||
const { searchParams } = new URL(request.url)
|
const { searchParams } = new URL(request.url)
|
||||||
const id = searchParams.get('id')
|
const id = searchParams.get('id')
|
||||||
@ -46,3 +47,5 @@ export async function GET(request: NextRequest) {
|
|||||||
return NextResponse.json({ error: '데이터 조회 중 오류가 발생했습니다' }, { status: 500 })
|
return NextResponse.json({ error: '데이터 조회 중 오류가 발생했습니다' }, { status: 500 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const GET = loggerWrapper(getSubmissionBuilder)
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { prisma } from '@/libs/prisma'
|
import { prisma } from '@/libs/prisma'
|
||||||
import { NextRequest, NextResponse } from 'next/server'
|
import { NextRequest, NextResponse } from 'next/server'
|
||||||
|
import { loggerWrapper } from '@/libs/api-wrapper'
|
||||||
|
|
||||||
type SuperPerson = {
|
type SuperPerson = {
|
||||||
storeId: string
|
storeId: string
|
||||||
@ -7,7 +8,7 @@ type SuperPerson = {
|
|||||||
eMail: string
|
eMail: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function GET(request: NextRequest) {
|
async function getSubmissionSuper(request: NextRequest): Promise<NextResponse> {
|
||||||
try {
|
try {
|
||||||
const { searchParams } = new URL(request.url)
|
const { searchParams } = new URL(request.url)
|
||||||
const id = searchParams.get('id')
|
const id = searchParams.get('id')
|
||||||
@ -37,3 +38,5 @@ export async function GET(request: NextRequest) {
|
|||||||
return NextResponse.json({ error: '데이터 조회 중 오류가 발생했습니다' }, { status: 500 })
|
return NextResponse.json({ error: '데이터 조회 중 오류가 발생했습니다' }, { status: 500 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const GET = loggerWrapper(getSubmissionSuper)
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
import { NextRequest, NextResponse } from 'next/server'
|
import { NextRequest, NextResponse } from 'next/server'
|
||||||
|
import { HttpStatusCode } from 'axios'
|
||||||
|
import { loggerWrapper } from '@/libs/api-wrapper'
|
||||||
import { prisma } from '@/libs/prisma'
|
import { prisma } from '@/libs/prisma'
|
||||||
import { type Suitable } from '@/types/Suitable'
|
import { type Suitable } from '@/types/Suitable'
|
||||||
|
|
||||||
@ -41,7 +43,7 @@ import { type Suitable } from '@/types/Suitable'
|
|||||||
* }
|
* }
|
||||||
* ]
|
* ]
|
||||||
*/
|
*/
|
||||||
export async function GET(request: NextRequest) {
|
async function getSuitableList(request: NextRequest): Promise<NextResponse> {
|
||||||
try {
|
try {
|
||||||
const searchParams = request.nextUrl.searchParams
|
const searchParams = request.nextUrl.searchParams
|
||||||
const pageNumber = parseInt(searchParams.get('pageNumber') || '0')
|
const pageNumber = parseInt(searchParams.get('pageNumber') || '0')
|
||||||
@ -51,7 +53,7 @@ export async function GET(request: NextRequest) {
|
|||||||
|
|
||||||
/* 파라미터 체크 */
|
/* 파라미터 체크 */
|
||||||
if (pageNumber === 0 || itemPerPage === 0) {
|
if (pageNumber === 0 || itemPerPage === 0) {
|
||||||
return NextResponse.json({ error: '페이지 번호와 페이지당 아이템 수가 필요합니다' }, { status: 400 })
|
return NextResponse.json({ error: '페이지 번호와 페이지당 아이템 수가 필요합니다' }, { status: HttpStatusCode.BadRequest })
|
||||||
}
|
}
|
||||||
|
|
||||||
let query = `
|
let query = `
|
||||||
@ -108,9 +110,12 @@ export async function GET(request: NextRequest) {
|
|||||||
headers: {
|
headers: {
|
||||||
'spinner-state': 'true',
|
'spinner-state': 'true',
|
||||||
},
|
},
|
||||||
|
status: HttpStatusCode.Ok,
|
||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`데이터 조회 중 오류가 발생했습니다: ${error}`)
|
console.error(`데이터 조회 중 오류가 발생했습니다: ${error}`)
|
||||||
return NextResponse.json({ error: `데이터 조회 중 오류가 발생했습니다: ${error}` }, { status: 500 })
|
return NextResponse.json({ error: `데이터 조회 중 오류가 발생했습니다: ${error}` }, { status: HttpStatusCode.InternalServerError })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const GET = loggerWrapper(getSuitableList)
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { NextRequest, NextResponse } from 'next/server'
|
import { NextRequest, NextResponse } from 'next/server'
|
||||||
|
import { HttpStatusCode } from 'axios'
|
||||||
import { pdf, Document } from '@react-pdf/renderer'
|
import { pdf, Document } from '@react-pdf/renderer'
|
||||||
import { PDFDocument } from 'pdf-lib'
|
import { PDFDocument } from 'pdf-lib'
|
||||||
|
import { loggerWrapper } from '@/libs/api-wrapper'
|
||||||
import { prisma } from '@/libs/prisma'
|
import { prisma } from '@/libs/prisma'
|
||||||
import { type Suitable } from '@/types/Suitable'
|
import { type Suitable } from '@/types/Suitable'
|
||||||
import SuitablePdf from '@/components/pdf/SuitablePdf'
|
import SuitablePdf from '@/components/pdf/SuitablePdf'
|
||||||
@ -28,7 +30,7 @@ import SuitablePdf from '@/components/pdf/SuitablePdf'
|
|||||||
*
|
*
|
||||||
* @apiSuccess {File} 지붕재 적합성 PDF 파일
|
* @apiSuccess {File} 지붕재 적합성 PDF 파일
|
||||||
*/
|
*/
|
||||||
export async function POST(request: NextRequest) {
|
async function createSuitablePdf(request: NextRequest): Promise<NextResponse> {
|
||||||
const formData = await request.formData()
|
const formData = await request.formData()
|
||||||
const ids = formData.get('ids') as string
|
const ids = formData.get('ids') as string
|
||||||
const detailIds = formData.get('detailIds') as string
|
const detailIds = formData.get('detailIds') as string
|
||||||
@ -36,7 +38,7 @@ export async function POST(request: NextRequest) {
|
|||||||
|
|
||||||
/* 파라미터 체크 */
|
/* 파라미터 체크 */
|
||||||
if (ids === '' || detailIds === '' || fileTitle === '') {
|
if (ids === '' || detailIds === '' || fileTitle === '') {
|
||||||
return NextResponse.json({ error: '필수 파라미터가 누락되었습니다' }, { status: 400 })
|
return NextResponse.json({ error: '필수 파라미터가 누락되었습니다' }, { status: HttpStatusCode.BadRequest })
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -121,7 +123,7 @@ export async function POST(request: NextRequest) {
|
|||||||
})
|
})
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`데이터 조회 중 오류가 발생했습니다: ${error}`)
|
console.error(`데이터 조회 중 오류가 발생했습니다: ${error}`)
|
||||||
return NextResponse.json({ error: `데이터 조회 중 오류가 발생했습니다: ${error}` }, { status: 500 })
|
return NextResponse.json({ error: `데이터 조회 중 오류가 발생했습니다: ${error}` }, { status: HttpStatusCode.InternalServerError })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,3 +144,5 @@ async function mergePdfBuffers(buffers: Uint8Array[]) {
|
|||||||
const mergedPdfBytes = await mergedPdf.save()
|
const mergedPdfBytes = await mergedPdf.save()
|
||||||
return mergedPdfBytes
|
return mergedPdfBytes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const POST = loggerWrapper(createSuitablePdf)
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
import { NextRequest, NextResponse } from 'next/server'
|
import { NextRequest, NextResponse } from 'next/server'
|
||||||
|
import { HttpStatusCode } from 'axios'
|
||||||
|
import { loggerWrapper } from '@/libs/api-wrapper'
|
||||||
import { prisma } from '@/libs/prisma'
|
import { prisma } from '@/libs/prisma'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -27,7 +29,7 @@ import { prisma } from '@/libs/prisma'
|
|||||||
* }
|
* }
|
||||||
* ]
|
* ]
|
||||||
*/
|
*/
|
||||||
export async function GET(request: NextRequest) {
|
async function getSuitablePick(request: NextRequest): Promise<NextResponse> {
|
||||||
try {
|
try {
|
||||||
const searchParams = request.nextUrl.searchParams
|
const searchParams = request.nextUrl.searchParams
|
||||||
const category = searchParams.get('category')
|
const category = searchParams.get('category')
|
||||||
@ -72,6 +74,8 @@ export async function GET(request: NextRequest) {
|
|||||||
return NextResponse.json(suitableIdSet)
|
return NextResponse.json(suitableIdSet)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`데이터 조회 중 오류가 발생했습니다: ${error}`)
|
console.error(`데이터 조회 중 오류가 발생했습니다: ${error}`)
|
||||||
return NextResponse.json({ error: `데이터 조회 중 오류가 발생했습니다: ${error}` }, { status: 500 })
|
return NextResponse.json({ error: `데이터 조회 중 오류가 발생했습니다: ${error}` }, { status: HttpStatusCode.InternalServerError })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const GET = loggerWrapper(getSuitablePick)
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
import { NextRequest, NextResponse } from 'next/server'
|
import { NextRequest, NextResponse } from 'next/server'
|
||||||
|
import { HttpStatusCode } from 'axios'
|
||||||
|
import { loggerWrapper } from '@/libs/api-wrapper'
|
||||||
import { prisma } from '@/libs/prisma'
|
import { prisma } from '@/libs/prisma'
|
||||||
import { Suitable } from '@/types/Suitable'
|
import { Suitable } from '@/types/Suitable'
|
||||||
|
|
||||||
@ -40,7 +42,7 @@ import { Suitable } from '@/types/Suitable'
|
|||||||
* }
|
* }
|
||||||
* ]
|
* ]
|
||||||
*/
|
*/
|
||||||
export async function POST(request: NextRequest) {
|
async function getSuitable(request: NextRequest): Promise<NextResponse> {
|
||||||
try {
|
try {
|
||||||
const body: Record<string, string> = await request.json()
|
const body: Record<string, string> = await request.json()
|
||||||
const ids = body.ids
|
const ids = body.ids
|
||||||
@ -48,7 +50,7 @@ export async function POST(request: NextRequest) {
|
|||||||
|
|
||||||
/* 파라미터 체크 */
|
/* 파라미터 체크 */
|
||||||
if (ids === '') {
|
if (ids === '') {
|
||||||
return NextResponse.json({ error: '필수 파라미터가 누락되었습니다' }, { status: 400 })
|
return NextResponse.json({ error: '필수 파라미터가 누락되었습니다' }, { status: HttpStatusCode.BadRequest })
|
||||||
}
|
}
|
||||||
|
|
||||||
let query = `
|
let query = `
|
||||||
@ -96,6 +98,8 @@ export async function POST(request: NextRequest) {
|
|||||||
return NextResponse.json(suitable)
|
return NextResponse.json(suitable)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`데이터 조회 중 오류가 발생했습니다: ${error}`)
|
console.error(`데이터 조회 중 오류가 발생했습니다: ${error}`)
|
||||||
return NextResponse.json({ error: `데이터 조회 중 오류가 발생했습니다: ${error}` }, { status: 500 })
|
return NextResponse.json({ error: `데이터 조회 중 오류가 발생했습니다: ${error}` }, { status: HttpStatusCode.InternalServerError })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const POST = loggerWrapper(getSuitable)
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import { sessionOptions } from '@/libs/session'
|
|||||||
import { cookies } from 'next/headers'
|
import { cookies } from 'next/headers'
|
||||||
import type { SessionData } from '@/types/Auth'
|
import type { SessionData } from '@/types/Auth'
|
||||||
import { Prisma } from '@prisma/client'
|
import { Prisma } from '@prisma/client'
|
||||||
|
import { loggerWrapper } from '@/libs/api-wrapper'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @description 조사 매물 조회 에러 메시지
|
* @description 조사 매물 조회 에러 메시지
|
||||||
@ -128,11 +129,11 @@ const fetchSurvey = async (id: number) => {
|
|||||||
* ...
|
* ...
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
async function getSurveySaleDetail(request: NextRequest): Promise<NextResponse> {
|
||||||
try {
|
try {
|
||||||
const cookieStore = await cookies()
|
const cookieStore = await cookies()
|
||||||
const session = await getIronSession<SessionData>(cookieStore, sessionOptions)
|
const session = await getIronSession<SessionData>(cookieStore, sessionOptions)
|
||||||
const { id } = await params
|
const id = request.nextUrl.pathname.split('/').pop() ?? ''
|
||||||
const { searchParams } = new URL(request.url)
|
const { searchParams } = new URL(request.url)
|
||||||
const isPdf = searchParams.get('isPdf') === 'true'
|
const isPdf = searchParams.get('isPdf') === 'true'
|
||||||
|
|
||||||
@ -228,9 +229,9 @@ const getNewSrlNo = async (srlNo: string, storeId: string, role: string) => {
|
|||||||
* ...
|
* ...
|
||||||
* }
|
* }
|
||||||
* */
|
* */
|
||||||
export async function PUT(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
async function updateSurveySaleDetail(request: NextRequest): Promise<NextResponse> {
|
||||||
try {
|
try {
|
||||||
const { id } = await params
|
const id = request.nextUrl.pathname.split('/').pop() ?? ''
|
||||||
const body = await request.json()
|
const body = await request.json()
|
||||||
const { detailInfo, ...basicInfo } = body.survey
|
const { detailInfo, ...basicInfo } = body.survey
|
||||||
|
|
||||||
@ -257,6 +258,7 @@ export async function PUT(request: NextRequest, { params }: { params: Promise<{
|
|||||||
return NextResponse.json({ error: 'データ保存に失敗しました。' }, { status: 500 })
|
return NextResponse.json({ error: 'データ保存に失敗しました。' }, { status: 500 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @api {DELETE} /api/survey-sales/:id 조사 매물 삭제 API
|
* @api {DELETE} /api/survey-sales/:id 조사 매물 삭제 API
|
||||||
* @apiName DELETE /api/survey-sales/:id
|
* @apiName DELETE /api/survey-sales/:id
|
||||||
@ -275,9 +277,9 @@ export async function PUT(request: NextRequest, { params }: { params: Promise<{
|
|||||||
* {
|
* {
|
||||||
* "message": "success"
|
* "message": "success"
|
||||||
*/
|
*/
|
||||||
export async function DELETE(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
async function deleteSurveySaleDetail(request: NextRequest): Promise<NextResponse> {
|
||||||
try {
|
try {
|
||||||
const { id } = await params
|
const id = request.nextUrl.pathname.split('/').pop() ?? ''
|
||||||
|
|
||||||
await prisma.$transaction(async (tx: Prisma.TransactionClient) => {
|
await prisma.$transaction(async (tx: Prisma.TransactionClient) => {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@ -343,9 +345,9 @@ export async function DELETE(request: NextRequest, { params }: { params: Promise
|
|||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
export async function PATCH(request: NextRequest, { params }: { params: Promise<{ id: string }> }) {
|
async function submitSurveySaleDetail(request: NextRequest): Promise<NextResponse> {
|
||||||
try {
|
try {
|
||||||
const { id } = await params
|
const id = request.nextUrl.pathname.split('/').pop() ?? ''
|
||||||
const body = await request.json()
|
const body = await request.json()
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const survey = await prisma.SD_SURVEY_SALES_BASIC_INFO.update({
|
const survey = await prisma.SD_SURVEY_SALES_BASIC_INFO.update({
|
||||||
@ -364,3 +366,8 @@ export async function PATCH(request: NextRequest, { params }: { params: Promise<
|
|||||||
return NextResponse.json({ error: 'データ保存に失敗しました。' }, { status: 500 })
|
return NextResponse.json({ error: 'データ保存に失敗しました。' }, { status: 500 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const GET = loggerWrapper(getSurveySaleDetail)
|
||||||
|
export const PUT = loggerWrapper(updateSurveySaleDetail)
|
||||||
|
export const DELETE = loggerWrapper(deleteSurveySaleDetail)
|
||||||
|
export const PATCH = loggerWrapper(submitSurveySaleDetail)
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { NextResponse } from 'next/server'
|
import { NextResponse } from 'next/server'
|
||||||
import { prisma } from '@/libs/prisma'
|
import { prisma } from '@/libs/prisma'
|
||||||
import { convertToSnakeCase } from '@/utils/common-utils'
|
import { convertToSnakeCase } from '@/utils/common-utils'
|
||||||
|
import { loggerWrapper } from '@/libs/api-wrapper'
|
||||||
/**
|
/**
|
||||||
* @description 검색 파라미터 타입
|
* @description 검색 파라미터 타입
|
||||||
*/
|
*/
|
||||||
@ -192,7 +193,7 @@ const checkSession = (params: SearchParams) => {
|
|||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
export async function GET(request: Request) {
|
async function getSurveySales(request: Request) {
|
||||||
try {
|
try {
|
||||||
/** URL 파라미터 파싱 */
|
/** URL 파라미터 파싱 */
|
||||||
const { searchParams } = new URL(request.url)
|
const { searchParams } = new URL(request.url)
|
||||||
@ -273,7 +274,7 @@ export async function GET(request: Request) {
|
|||||||
*
|
*
|
||||||
* @apiError {Number} 500 서버 오류
|
* @apiError {Number} 500 서버 오류
|
||||||
*/
|
*/
|
||||||
export async function PUT(request: Request) {
|
async function updateSurveySales(request: Request) {
|
||||||
try {
|
try {
|
||||||
/** 요청 바디 파싱 */
|
/** 요청 바디 파싱 */
|
||||||
const body = await request.json()
|
const body = await request.json()
|
||||||
@ -335,7 +336,7 @@ export async function PUT(request: Request) {
|
|||||||
*
|
*
|
||||||
* @apiError {Number} 500 서버 오류
|
* @apiError {Number} 500 서버 오류
|
||||||
*/
|
*/
|
||||||
export async function POST(request: Request) {
|
async function createSurveySales(request: Request) {
|
||||||
try {
|
try {
|
||||||
const body = await request.json()
|
const body = await request.json()
|
||||||
|
|
||||||
@ -393,3 +394,7 @@ export async function POST(request: Request) {
|
|||||||
return NextResponse.json({ error: 'データ保存に失敗しました。' }, { status: 500 })
|
return NextResponse.json({ error: 'データ保存に失敗しました。' }, { status: 500 })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const GET = loggerWrapper(getSurveySales)
|
||||||
|
export const PUT = loggerWrapper(updateSurveySales)
|
||||||
|
export const POST = loggerWrapper(createSurveySales)
|
||||||
@ -1,5 +1,11 @@
|
|||||||
|
import { Metadata } from 'next'
|
||||||
import type { ReactNode } from 'react'
|
import type { ReactNode } from 'react'
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'HANASYS現地調査:お問い合わせ',
|
||||||
|
description: 'HANASYS現地調査:お問い合わせ',
|
||||||
|
}
|
||||||
|
|
||||||
export default function layout({ children }: { children: ReactNode }) {
|
export default function layout({ children }: { children: ReactNode }) {
|
||||||
return <div className="container">{children}</div>
|
return <div className="container">{children}</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,8 +13,8 @@ import { sessionOptions } from '@/libs/session'
|
|||||||
import '@/styles/style.scss'
|
import '@/styles/style.scss'
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: 'Create Next App',
|
title: 'HANASYS現地調査',
|
||||||
description: 'Generated by create next app',
|
description: 'HANASYS現地調査',
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RootLayoutProps {
|
interface RootLayoutProps {
|
||||||
|
|||||||
@ -1,9 +1,15 @@
|
|||||||
|
import { Metadata } from 'next'
|
||||||
import type { ReactNode } from 'react'
|
import type { ReactNode } from 'react'
|
||||||
|
|
||||||
interface SuitableLayoutProps {
|
interface SuitableLayoutProps {
|
||||||
children: ReactNode
|
children: ReactNode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'HANASYS現地調査:屋根材積合成',
|
||||||
|
description: 'HANASYS現地調査:屋根材積合成',
|
||||||
|
}
|
||||||
|
|
||||||
export default function layout({ children }: SuitableLayoutProps) {
|
export default function layout({ children }: SuitableLayoutProps) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@ -1,9 +1,15 @@
|
|||||||
|
import { Metadata } from 'next'
|
||||||
import type { ReactNode } from 'react'
|
import type { ReactNode } from 'react'
|
||||||
|
|
||||||
interface SurveySaleLayoutProps {
|
interface SurveySaleLayoutProps {
|
||||||
children: ReactNode
|
children: ReactNode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'HANASYS現地調査:調査物件',
|
||||||
|
description: 'HANASYS現地調査:調査物件',
|
||||||
|
}
|
||||||
|
|
||||||
export default function layout({ children }: SurveySaleLayoutProps) {
|
export default function layout({ children }: SurveySaleLayoutProps) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
import getConfigs from '@/config/config.common'
|
import getConfigs from '@/config/config.common'
|
||||||
|
|
||||||
// 환경마다 달라져야 할 변수, 값들을 정의합니다. (여기는 development 환경에 맞는 값을 지정합니다.)
|
// 환경마다 달라져야 할 변수, 값들을 정의합니다. (여기는 development 환경에 맞는 값을 지정합니다.)
|
||||||
const baseUrl = 'http://1.248.227.176:3000'
|
// const baseUrl = 'http://172.16.56.60:3000'
|
||||||
|
const baseUrl = 'https://dev.hanasysfield.jp'
|
||||||
const mode = 'development'
|
const mode = 'development'
|
||||||
|
|
||||||
// 환경마다 달라져야 할 값들을 getConfig 함수에 전달합니다.
|
// 환경마다 달라져야 할 값들을 getConfig 함수에 전달합니다.
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
import getConfigs from '@/config/config.common'
|
import getConfigs from '@/config/config.common'
|
||||||
|
|
||||||
// 환경마다 달라져야 할 변수, 값들을 정의합니다. (여기는 production 환경에 맞는 값을 지정합니다.)
|
// 환경마다 달라져야 할 변수, 값들을 정의합니다. (여기는 production 환경에 맞는 값을 지정합니다.)
|
||||||
const baseUrl = 'http://localhost.prod:3000'
|
const baseUrl = 'https://hanasysfield.jp'
|
||||||
|
// const baseUrl = 'http://172.16.56.55:3000'
|
||||||
const mode = 'production'
|
const mode = 'production'
|
||||||
|
|
||||||
// 환경마다 달라져야 할 값들을 getConfig 함수에 전달합니다.
|
// 환경마다 달라져야 할 값들을 getConfig 함수에 전달합니다.
|
||||||
|
|||||||
@ -48,7 +48,9 @@ export function useInquiry(
|
|||||||
*/
|
*/
|
||||||
const errorRouter = (error: any) => {
|
const errorRouter = (error: any) => {
|
||||||
const status = error.response?.status
|
const status = error.response?.status
|
||||||
|
if (error.response?.data.error) {
|
||||||
alert(error.response?.data.error)
|
alert(error.response?.data.error)
|
||||||
|
}
|
||||||
switch (status) {
|
switch (status) {
|
||||||
// session 없는 경우
|
// session 없는 경우
|
||||||
case 401:
|
case 401:
|
||||||
|
|||||||
@ -108,7 +108,9 @@ export function useSurvey(
|
|||||||
*/
|
*/
|
||||||
const errorRouter = (error: any) => {
|
const errorRouter = (error: any) => {
|
||||||
const status = error.response?.status
|
const status = error.response?.status
|
||||||
|
if (error.response?.data.error) {
|
||||||
alert(error.response?.data.error)
|
alert(error.response?.data.error)
|
||||||
|
}
|
||||||
switch (status) {
|
switch (status) {
|
||||||
/** session 없는 경우 */
|
/** session 없는 경우 */
|
||||||
case 401:
|
case 401:
|
||||||
@ -259,6 +261,9 @@ export function useSurvey(
|
|||||||
queryClient.invalidateQueries({ queryKey: ['survey', id] })
|
queryClient.invalidateQueries({ queryKey: ['survey', id] })
|
||||||
queryClient.invalidateQueries({ queryKey: ['survey', 'list'] })
|
queryClient.invalidateQueries({ queryKey: ['survey', 'list'] })
|
||||||
},
|
},
|
||||||
|
onError: (error: any) => {
|
||||||
|
alert(error.response?.data.error)
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -370,8 +375,9 @@ export function useSurvey(
|
|||||||
`https://zipcloud.ibsnet.co.jp/api/search?${queryStringFormatter({ zipcode: zipCode.trim() })}`,
|
`https://zipcloud.ibsnet.co.jp/api/search?${queryStringFormatter({ zipcode: zipCode.trim() })}`,
|
||||||
)
|
)
|
||||||
return data.results
|
return data.results
|
||||||
} catch (e) {
|
} catch (error: any) {
|
||||||
console.error('Failed to fetch zipcode data:', e)
|
console.error('Failed to fetch zipcode data:', error)
|
||||||
|
alert(error.response?.data.error)
|
||||||
throw new Error('Failed to fetch zipcode data')
|
throw new Error('Failed to fetch zipcode data')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
21
src/libs/api-wrapper.ts
Normal file
21
src/libs/api-wrapper.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { NextRequest, NextResponse } from 'next/server'
|
||||||
|
import { writeApiLog } from './logger'
|
||||||
|
|
||||||
|
export function loggerWrapper(handler: (req: NextRequest) => Promise<NextResponse>): (req: NextRequest) => Promise<NextResponse> {
|
||||||
|
return async function (req: NextRequest) {
|
||||||
|
const reqClone = req.clone()
|
||||||
|
|
||||||
|
const response = await handler(req)
|
||||||
|
|
||||||
|
await writeApiLog(
|
||||||
|
new NextRequest(req.url, {
|
||||||
|
method: req.method,
|
||||||
|
headers: req.headers,
|
||||||
|
body: reqClone.body ? await reqClone.text() : undefined,
|
||||||
|
}),
|
||||||
|
response.status,
|
||||||
|
)
|
||||||
|
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
}
|
||||||
92
src/libs/logger.ts
Normal file
92
src/libs/logger.ts
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
import { NextRequest } from 'next/server'
|
||||||
|
import { join } from 'path'
|
||||||
|
import pino from 'pino'
|
||||||
|
|
||||||
|
/* 로그 데이터 인터페이스 */
|
||||||
|
interface ApiLogData {
|
||||||
|
responseStatus: number
|
||||||
|
method: string
|
||||||
|
url: string
|
||||||
|
// headers: { [k: string]: string }
|
||||||
|
query: { [k: string]: string }
|
||||||
|
body: string | undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 날짜별 로그 파일 경로 생성 함수 */
|
||||||
|
const getLogFilePath = (): string => {
|
||||||
|
const today = new Date().toISOString().split('T')[0] // YYYY-MM-DD 형식
|
||||||
|
return join(process.cwd(), 'logs', `onsite-survey-${today}.log`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 날짜별 로거 생성 클래스 */
|
||||||
|
class DailyLogger {
|
||||||
|
private currentDate: string
|
||||||
|
private logger: pino.Logger
|
||||||
|
private destination: ReturnType<typeof pino.destination>
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.currentDate = new Date().toISOString().split('T')[0]
|
||||||
|
this.destination = pino.destination({
|
||||||
|
dest: getLogFilePath(),
|
||||||
|
mkdir: true,
|
||||||
|
sync: false,
|
||||||
|
})
|
||||||
|
this.logger = this.createLogger()
|
||||||
|
|
||||||
|
/* kill signal 핸들러 등록 */
|
||||||
|
process.on('SIGTERM', this.handleShutdown.bind(this))
|
||||||
|
process.on('SIGINT', this.handleShutdown.bind(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
private async handleShutdown(): Promise<void> {
|
||||||
|
this.destination.flushSync()
|
||||||
|
this.destination.end()
|
||||||
|
}
|
||||||
|
|
||||||
|
private createLogger(): pino.Logger {
|
||||||
|
return pino(
|
||||||
|
{
|
||||||
|
level: 'info',
|
||||||
|
timestamp: pino.stdTimeFunctions.isoTime,
|
||||||
|
},
|
||||||
|
this.destination,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
public info(obj: any, msg?: string): void {
|
||||||
|
const today = new Date().toISOString().split('T')[0]
|
||||||
|
|
||||||
|
if (today !== this.currentDate) {
|
||||||
|
/* 기존 destination 종료 */
|
||||||
|
this.destination.flushSync()
|
||||||
|
this.destination.end()
|
||||||
|
|
||||||
|
/* 새로운 destination 생성 */
|
||||||
|
this.destination = pino.destination({
|
||||||
|
dest: getLogFilePath(),
|
||||||
|
mkdir: true,
|
||||||
|
sync: false,
|
||||||
|
})
|
||||||
|
this.currentDate = today
|
||||||
|
this.logger = this.createLogger()
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.info(obj, msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 로거 인스턴스 */
|
||||||
|
const dailyLogger = new DailyLogger()
|
||||||
|
|
||||||
|
/* API 로그 기록 함수 */
|
||||||
|
export const writeApiLog = async (request: NextRequest, responseStatus: number): Promise<void> => {
|
||||||
|
const logData: ApiLogData = {
|
||||||
|
responseStatus: responseStatus,
|
||||||
|
method: request.method,
|
||||||
|
url: request.url,
|
||||||
|
// headers: Object.fromEntries(request.headers),
|
||||||
|
query: Object.fromEntries(new URL(request.url).searchParams),
|
||||||
|
body: request.body ? await request.text() : undefined,
|
||||||
|
}
|
||||||
|
dailyLogger.info(logData, 'API Request')
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user