From c027a3977be56b983fab50ebb091dab406e5de7a Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Wed, 28 May 2025 14:21:24 +0900 Subject: [PATCH 01/12] chore: update QSP API URL in development and production environment files --- .env.development | 3 ++- .env.production | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.env.development b/.env.development index 8e6fead..2ad3a20 100644 --- a/.env.development +++ b/.env.development @@ -5,7 +5,8 @@ NEXT_PUBLIC_RUN_MODE=development NEXT_PUBLIC_API_URL=http://172.30.1.65:3000 #qsp 로그인 api -NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120 +# NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120 +NEXT_PUBLIC_QSP_API_URL=http://121.168.9.37:8080 #1:1문의 api NEXT_PUBLIC_INQUIRY_API_URL=http://172.23.4.129:8110 diff --git a/.env.production b/.env.production index ce308e8..1738ee7 100644 --- a/.env.production +++ b/.env.production @@ -3,7 +3,8 @@ NEXT_PUBLIC_RUN_MODE=production NEXT_PUBLIC_API_URL=http://1.248.227.176:3000 #qsp 로그인 api -NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120 +# NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120 +NEXT_PUBLIC_QSP_API_URL=https://jp.qsalesplatform.com #1:1문의 api NEXT_PUBLIC_INQUIRY_API_URL=http://172.23.4.129:8110 From 67ba964eec7f7c5edc6c36c5398498d63e08ae72 Mon Sep 17 00:00:00 2001 From: keyy1315 Date: Wed, 28 May 2025 14:22:22 +0900 Subject: [PATCH 02/12] feat: add data for download survey-sale pdf --- src/components/pdf/SurveySaleDownloadPdf.tsx | 45 ++++++++++++++----- .../survey-sale/detail/DataTable.tsx | 5 ++- src/config/config.local.ts | 2 +- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/src/components/pdf/SurveySaleDownloadPdf.tsx b/src/components/pdf/SurveySaleDownloadPdf.tsx index 0802308..5abf49e 100644 --- a/src/components/pdf/SurveySaleDownloadPdf.tsx +++ b/src/components/pdf/SurveySaleDownloadPdf.tsx @@ -1,8 +1,8 @@ 'use client' -import { useEffect, useRef } from 'react' +import { useEffect, useRef, useState } from 'react' import generatePDF, { Margin, Resolution } from 'react-to-pdf' -import { useParams } from 'next/navigation' +import { useParams, useRouter } from 'next/navigation' import { useSurvey } from '@/hooks/useSurvey' import { radioEtcData, roofMaterial, selectBoxOptions, supplementaryFacilities } from '../survey-sale/detail/RoofForm' @@ -11,13 +11,18 @@ export default function SurveySaleDownloadPdf() { const id = params.id const { surveyDetail, isLoadingSurveyDetail } = useSurvey(Number(id)) - - useEffect(() => { - if (isLoadingSurveyDetail) return - handleDownPdf() - }, [surveyDetail, isLoadingSurveyDetail]) + const [isLoading, setIsLoading] = useState(false) + const router = useRouter() const targetRef = useRef(null) + const isGeneratedRef = useRef(false) + + // useEffect(() => { + // if (isLoadingSurveyDetail || !surveyDetail || isGeneratedRef.current) return + // isGeneratedRef.current = true + // handleDownPdf() + // }, [surveyDetail?.id, isLoadingSurveyDetail]) + const handleDownPdf = () => { const options = { method: 'open' as const, @@ -41,14 +46,30 @@ export default function SurveySaleDownloadPdf() { }, } - generatePDF(targetRef, options) - // generatePDF(targetRef, { filename: 'page.pdf' }) + generatePDF(targetRef, options).then(() => { + router.push(`/survey-sale/${id}`) + }) } return ( <> - {/* */} -
-
+ +
+
HWJ 現地調査シート1/2 diff --git a/src/components/survey-sale/detail/DataTable.tsx b/src/components/survey-sale/detail/DataTable.tsx index d0ca7bf..93d314e 100644 --- a/src/components/survey-sale/detail/DataTable.tsx +++ b/src/components/survey-sale/detail/DataTable.tsx @@ -1,13 +1,14 @@ 'use client' import { useSurvey } from '@/hooks/useSurvey' -import { useParams } from 'next/navigation' +import { useParams, useRouter } from 'next/navigation' import { useEffect } from 'react' import DetailForm from './DetailForm' export default function DataTable() { const params = useParams() const id = params.id + const router = useRouter() useEffect(() => { if (Number.isNaN(Number(id))) { @@ -67,7 +68,7 @@ export default function DataTable() { ダウンロード - diff --git a/src/config/config.local.ts b/src/config/config.local.ts index ac02c97..8fbf68b 100644 --- a/src/config/config.local.ts +++ b/src/config/config.local.ts @@ -1,7 +1,7 @@ import getConfigs from '@/config/config.common' // 환경마다 달라져야 할 변수, 값들을 정의합니다. (여기는 local 환경에 맞는 값을 지정합니다.) -const baseUrl = 'http://localhost:3000' +const baseUrl = 'http://172.30.1.23:3000' const mode = 'local' // 환경마다 달라져야 할 값들을 getConfig 함수에 전달합니다. From 3a8c431f418c239526c86deee5e03e2a1aa98a80 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Wed, 28 May 2025 14:26:43 +0900 Subject: [PATCH 03/12] chore: update QSP API URL in local environment configuration --- .env.localhost | 3 ++- src/components/Login.tsx | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.env.localhost b/.env.localhost index 29cb5c2..c88c5a0 100644 --- a/.env.localhost +++ b/.env.localhost @@ -5,7 +5,8 @@ NEXT_PUBLIC_RUN_MODE=local NEXT_PUBLIC_API_URL=http://172.30.1.65:3000 #qsp 로그인 api -NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120 +# NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120 +NEXT_PUBLIC_QSP_API_URL=http://121.168.9.37:8080 #1:1문의 api NEXT_PUBLIC_INQUIRY_API_URL=http://172.23.4.129:8110 diff --git a/src/components/Login.tsx b/src/components/Login.tsx index 4a77ad6..6c60b99 100644 --- a/src/components/Login.tsx +++ b/src/components/Login.tsx @@ -79,7 +79,11 @@ export default function Login() { url = '/api/partner' } - const { data } = await axiosInstance('').post(`${url}`, { + // const { data } = await axiosInstance('').post(`${url}`, { + // loginId: account.loginId, + // pwd: account.pwd, + // }) + const { data } = await axiosInstance(`${process.env.NEXT_PUBLIC_QSP_API_URL}`).post(`/api/user/login`, { loginId: account.loginId, pwd: account.pwd, }) From 479643216ce2db3f5da1c86da31c1f84a6d80c1e Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Wed, 28 May 2025 14:35:08 +0900 Subject: [PATCH 04/12] chore: update QSP API URL in development and localhost environment files --- .env.development | 2 +- .env.localhost | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.development b/.env.development index 2ad3a20..2c96d85 100644 --- a/.env.development +++ b/.env.development @@ -6,7 +6,7 @@ NEXT_PUBLIC_API_URL=http://172.30.1.65:3000 #qsp 로그인 api # NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120 -NEXT_PUBLIC_QSP_API_URL=http://121.168.9.37:8080 +NEXT_PUBLIC_QSP_API_URL=https://jp-dev.qsalesplatform.com #1:1문의 api NEXT_PUBLIC_INQUIRY_API_URL=http://172.23.4.129:8110 diff --git a/.env.localhost b/.env.localhost index c88c5a0..a7ceb68 100644 --- a/.env.localhost +++ b/.env.localhost @@ -6,7 +6,7 @@ NEXT_PUBLIC_API_URL=http://172.30.1.65:3000 #qsp 로그인 api # NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120 -NEXT_PUBLIC_QSP_API_URL=http://121.168.9.37:8080 +NEXT_PUBLIC_QSP_API_URL=https://jp-dev.qsalesplatform.com #1:1문의 api NEXT_PUBLIC_INQUIRY_API_URL=http://172.23.4.129:8110 From 82cdb2a7557b1418cbd986b9615c2e7b439e0bbb Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Wed, 28 May 2025 14:43:10 +0900 Subject: [PATCH 05/12] chore: revert QSP API URL to previous configuration in Login component --- .env.development | 4 ++-- .env.localhost | 4 ++-- src/components/Login.tsx | 6 +----- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/.env.development b/.env.development index 2c96d85..28a0774 100644 --- a/.env.development +++ b/.env.development @@ -5,8 +5,8 @@ NEXT_PUBLIC_RUN_MODE=development NEXT_PUBLIC_API_URL=http://172.30.1.65:3000 #qsp 로그인 api -# NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120 -NEXT_PUBLIC_QSP_API_URL=https://jp-dev.qsalesplatform.com +NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120 +# NEXT_PUBLIC_QSP_API_URL=https://jp-dev.qsalesplatform.com #1:1문의 api NEXT_PUBLIC_INQUIRY_API_URL=http://172.23.4.129:8110 diff --git a/.env.localhost b/.env.localhost index a7ceb68..8bee910 100644 --- a/.env.localhost +++ b/.env.localhost @@ -5,8 +5,8 @@ NEXT_PUBLIC_RUN_MODE=local NEXT_PUBLIC_API_URL=http://172.30.1.65:3000 #qsp 로그인 api -# NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120 -NEXT_PUBLIC_QSP_API_URL=https://jp-dev.qsalesplatform.com +NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120 +# NEXT_PUBLIC_QSP_API_URL=https://jp-dev.qsalesplatform.com #1:1문의 api NEXT_PUBLIC_INQUIRY_API_URL=http://172.23.4.129:8110 diff --git a/src/components/Login.tsx b/src/components/Login.tsx index 6c60b99..4a77ad6 100644 --- a/src/components/Login.tsx +++ b/src/components/Login.tsx @@ -79,11 +79,7 @@ export default function Login() { url = '/api/partner' } - // const { data } = await axiosInstance('').post(`${url}`, { - // loginId: account.loginId, - // pwd: account.pwd, - // }) - const { data } = await axiosInstance(`${process.env.NEXT_PUBLIC_QSP_API_URL}`).post(`/api/user/login`, { + const { data } = await axiosInstance('').post(`${url}`, { loginId: account.loginId, pwd: account.pwd, }) From 5014162f2f7e7dfc33e3ec4b6b1f1af00c70fa17 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Wed, 28 May 2025 14:45:52 +0900 Subject: [PATCH 06/12] chore: comment out axios login request in Login component --- src/components/Login.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/Login.tsx b/src/components/Login.tsx index 4a77ad6..af2c3fd 100644 --- a/src/components/Login.tsx +++ b/src/components/Login.tsx @@ -83,6 +83,10 @@ export default function Login() { loginId: account.loginId, pwd: account.pwd, }) + // const { data } = await axiosInstance(`${process.env.NEXT_PUBLIC_QSP_API_URL}`).post(`/api/user/login`, { + // loginId: account.loginId, + // pwd: account.pwd, + // }) return data }, From dc0009ddd7a2d7ecd860b9f8b021e3eec8b62282 Mon Sep 17 00:00:00 2001 From: yoosangwook Date: Wed, 28 May 2025 15:37:47 +0900 Subject: [PATCH 07/12] chore: add SMTP configuration to environment files and integrate nodemailer for email functionality --- .env.development | 9 ++++++++- .env.localhost | 9 ++++++++- .env.production | 9 ++++++++- package-lock.json | 10 ++++++++++ package.json | 2 ++ src/libs/mailer.ts | 47 ++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 src/libs/mailer.ts diff --git a/.env.development b/.env.development index 28a0774..d4d4309 100644 --- a/.env.development +++ b/.env.development @@ -16,4 +16,11 @@ DB_HOST=202.218.61.226 DB_USER=readonly DB_PASSWORD=aAjmFW12iHKW84l1 DB_DATABASE=qpartners -DB_PORT=3306 \ No newline at end of file +DB_PORT=3306 + +SMTP_HOST=autodiscover.qcells.com +SMTP_PORT=25 +SMTP_SECURE=true +SMTP_USER=hss404.u021@cleverse.dev +SMTP_PASSWORD=0000 +SMTP_FROM=qsalesplatform@qcells.com \ No newline at end of file diff --git a/.env.localhost b/.env.localhost index 8bee910..3f760ab 100644 --- a/.env.localhost +++ b/.env.localhost @@ -16,4 +16,11 @@ DB_HOST=202.218.61.226 DB_USER=readonly DB_PASSWORD=aAjmFW12iHKW84l1 DB_DATABASE=qpartners -DB_PORT=3306 \ No newline at end of file +DB_PORT=3306 + +SMTP_HOST=autodiscover.qcells.com +SMTP_PORT=25 +SMTP_SECURE=true +SMTP_USER=hss404.u021@cleverse.dev +SMTP_PASSWORD=0000 +SMTP_FROM=qsalesplatform@qcells.com diff --git a/.env.production b/.env.production index 1738ee7..72caa0d 100644 --- a/.env.production +++ b/.env.production @@ -14,4 +14,11 @@ DB_HOST=202.218.61.226 DB_USER=readonly DB_PASSWORD=aAjmFW12iHKW84l1 DB_DATABASE=qpartners -DB_PORT=3306 \ No newline at end of file +DB_PORT=3306 + +SMTP_HOST=autodiscover.qcells.com +SMTP_PORT=25 +SMTP_SECURE=true +SMTP_USER=hss404.u021@cleverse.dev +SMTP_PASSWORD=0000 +SMTP_FROM=qsalesplatform@qcells.com \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 73dbbf1..6a3c17f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "mssql": "^11.0.1", "mysql2": "^3.14.1", "next": "15.2.4", + "nodemailer": "^7.0.3", "react": "^19.0.0", "react-dom": "^19.0.0", "react-to-pdf": "^2.0.0", @@ -3700,6 +3701,15 @@ "license": "MIT", "optional": true }, + "node_modules/nodemailer": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.3.tgz", + "integrity": "sha512-Ajq6Sz1x7cIK3pN6KesGTah+1gnwMnx5gKl3piQlQQE/PwyJ4Mbc8is2psWYxK3RJTVeqsDaCv8ZzXLCDHMTZw==", + "license": "MIT-0", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/open": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", diff --git a/package.json b/package.json index 53ed0e8..5b0953b 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@prisma/client": "^6.7.0", "@tanstack/react-query": "^5.71.0", "@tanstack/react-query-devtools": "^5.71.0", + "@types/nodemailer": "^6.4.17", "axios": "^1.8.4", "env-cmd": "^10.1.0", "iron-session": "^8.0.4", @@ -25,6 +26,7 @@ "mssql": "^11.0.1", "mysql2": "^3.14.1", "next": "15.2.4", + "nodemailer": "^7.0.3", "react": "^19.0.0", "react-dom": "^19.0.0", "react-to-pdf": "^2.0.0", diff --git a/src/libs/mailer.ts b/src/libs/mailer.ts new file mode 100644 index 0000000..a3f06e7 --- /dev/null +++ b/src/libs/mailer.ts @@ -0,0 +1,47 @@ +import nodemailer from 'nodemailer' + +interface EmailParams { + to: string | string[] + cc?: string | string[] + subject: string + content: string +} + +export async function sendEmail({ to, cc, subject, content }: EmailParams): Promise { + // Create a transporter using SMTP + const transporter = nodemailer.createTransport({ + host: process.env.SMTP_HOST, + port: Number(process.env.SMTP_PORT), + secure: process.env.SMTP_SECURE === 'true', + auth: { + user: process.env.SMTP_USER, + pass: process.env.SMTP_PASSWORD, + }, + }) + + // Email options + const mailOptions = { + from: process.env.SMTP_USER, + to: Array.isArray(to) ? to.join(', ') : to, + cc: cc ? (Array.isArray(cc) ? cc.join(', ') : cc) : undefined, + subject, + html: content, + } + + try { + // Send email + await transporter.sendMail(mailOptions) + } catch (error) { + console.error('Error sending email:', error) + throw new Error('Failed to send email') + } +} + +async function sendEmailTest() { + await sendEmail({ + to: 'test@test.com', + cc: 'test2@test.com', + subject: 'Test Email', + content: '

Hello

This is a test email.

', + }) +} From 56f8ad9aaf174cd3d81d31695ff018fe963a9f33 Mon Sep 17 00:00:00 2001 From: keyy1315 Date: Wed, 28 May 2025 15:38:18 +0900 Subject: [PATCH 08/12] chore: update API URL in development and localhost environment files; enhance SurveySaleDownloadPdf component to handle null values gracefully --- .env.development | 2 +- .env.localhost | 2 +- src/components/pdf/SurveySaleDownloadPdf.tsx | 86 +++++++++++--------- 3 files changed, 50 insertions(+), 40 deletions(-) diff --git a/.env.development b/.env.development index 28a0774..da32b80 100644 --- a/.env.development +++ b/.env.development @@ -2,7 +2,7 @@ NEXT_PUBLIC_RUN_MODE=development # 모바일 디바이스로 로컬 서버 확인하려면 자신 IP 주소로 변경 # 다시 로컬에서 개발할때는 localhost로 변경 #route handler -NEXT_PUBLIC_API_URL=http://172.30.1.65:3000 +NEXT_PUBLIC_API_URL=http://172.30.1.23:3000 #qsp 로그인 api NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120 diff --git a/.env.localhost b/.env.localhost index 8bee910..138c28f 100644 --- a/.env.localhost +++ b/.env.localhost @@ -2,7 +2,7 @@ NEXT_PUBLIC_RUN_MODE=local # 모바일 디바이스로 로컬 서버 확인하려면 자신 IP 주소로 변경 # 다시 로컬에서 개발할때는 localhost로 변경 #route handler -NEXT_PUBLIC_API_URL=http://172.30.1.65:3000 +NEXT_PUBLIC_API_URL=http://172.30.1.23:3000 #qsp 로그인 api NEXT_PUBLIC_QSP_API_URL=http://1.248.227.176:8120 diff --git a/src/components/pdf/SurveySaleDownloadPdf.tsx b/src/components/pdf/SurveySaleDownloadPdf.tsx index 5abf49e..8d8adf9 100644 --- a/src/components/pdf/SurveySaleDownloadPdf.tsx +++ b/src/components/pdf/SurveySaleDownloadPdf.tsx @@ -50,9 +50,13 @@ export default function SurveySaleDownloadPdf() { router.push(`/survey-sale/${id}`) }) } + const supplementList = supplementaryFacilities + .filter((facility) => surveyDetail?.detailInfo?.supplementaryFacilities?.includes(facility.id.toString())) + .map((facility) => facility.name) + return ( <> - + {/* */}

- {surveyDetail?.store} + {surveyDetail?.store ?? '-'}

現地阴買日

- {surveyDetail?.investigationDate} + {surveyDetail?.investigationDate ?? '-'}

@@ -122,7 +126,7 @@ export default function SurveySaleDownloadPdf() { boxSizing: 'border-box', }} > - {surveyDetail?.customerName} + {surveyDetail?.customerName ?? '-'} @@ -189,7 +193,7 @@ export default function SurveySaleDownloadPdf() { boxSizing: 'border-box', }} > - {surveyDetail?.detailInfo?.contractCapacity} + {surveyDetail?.detailInfo?.contractCapacity ?? '-'} - {surveyDetail?.detailInfo?.retailCompany} + {surveyDetail?.detailInfo?.retailCompany ?? '-'} @@ -246,13 +250,11 @@ export default function SurveySaleDownloadPdf() { boxSizing: 'border-box', }} > - {supplementaryFacilities - .filter((facility) => surveyDetail?.detailInfo?.supplementaryFacilities?.includes(facility.id.toString())) - .map((facility) => facility.name) - .join(', ')} - {surveyDetail?.detailInfo?.supplementaryFacilitiesEtc - ? `, (その他) ${surveyDetail?.detailInfo?.supplementaryFacilitiesEtc}` - : '-'} + {supplementList === null && surveyDetail?.detailInfo?.supplementaryFacilitiesEtc === null + ? '-' + : surveyDetail?.detailInfo?.supplementaryFacilitiesEtc + ? `${supplementList.join(', ')}, ${surveyDetail?.detailInfo?.supplementaryFacilitiesEtc}` + : supplementList.join(', ')} @@ -282,11 +284,16 @@ export default function SurveySaleDownloadPdf() { boxSizing: 'border-box', }} > - { - selectBoxOptions.installationSystem.find((system) => system.id.toString() === surveyDetail?.detailInfo?.installationSystem) - ?.name - } - {surveyDetail?.detailInfo?.installationSystemEtc ? `, (その他) ${surveyDetail?.detailInfo?.installationSystemEtc}` : '-'} + {/* {selectBoxOptions.installationSystem.find ((system) => system.id.toString() === surveyDetail?.detailInfo?.installationSystem) + ?.name ?? surveyDetail?.detailInfo?.installationSystemEtc !== null + ? `${surveyDetail?.detailInfo?.installationSystemEtc}` + : '-'} */} + {surveyDetail?.detailInfo?.installationSystem === null && surveyDetail?.detailInfo?.installationSystemEtc === null + ? '-' + : surveyDetail?.detailInfo?.installationSystemEtc + ? `${surveyDetail?.detailInfo?.installationSystemEtc}` + : selectBoxOptions.installationSystem.find((system) => system.id.toString() === surveyDetail?.detailInfo?.installationSystem) + ?.name} @@ -351,11 +358,13 @@ export default function SurveySaleDownloadPdf() { boxSizing: 'border-box', }} > - {roofMaterial - .filter((material) => surveyDetail?.detailInfo?.roofMaterial?.includes(material.id.toString())) - .map((material) => material.name) - .join(', ')} - {surveyDetail?.detailInfo?.roofMaterialEtc ? `, (その他) ${surveyDetail?.detailInfo?.roofMaterialEtc}` : '-'} + {surveyDetail?.detailInfo?.roofMaterial === null && surveyDetail?.detailInfo?.roofMaterialEtc === null + ? '-' + : roofMaterial + .filter((material) => surveyDetail?.detailInfo?.roofMaterial?.includes(material.id.toString())) + .map((material) => material.name) + .join(', ')} + {surveyDetail?.detailInfo?.roofMaterialEtc ? `, ${surveyDetail?.detailInfo?.roofMaterialEtc}` : ''} - {selectBoxOptions.roofShape.find((shape) => shape.id.toString() === surveyDetail?.detailInfo?.roofShape)?.name} + {selectBoxOptions.roofShape.find((shape) => shape.id.toString() === surveyDetail?.detailInfo?.roofShape)?.name ?? + (surveyDetail?.detailInfo?.roofShapeEtc ? ` ${surveyDetail?.detailInfo?.roofShapeEtc}` : '-')} @@ -411,7 +421,7 @@ export default function SurveySaleDownloadPdf() { boxSizing: 'border-box', }} > - {`${surveyDetail?.detailInfo?.roofSlope} 寸`} + {surveyDetail?.detailInfo?.roofSlope ? `${surveyDetail?.detailInfo?.roofSlope} 寸` : '-'} - {`${surveyDetail?.detailInfo?.houseStructure ? '木製' : '(その他)'} ${surveyDetail?.detailInfo?.houseStructureEtc}`} + {surveyDetail?.detailInfo?.houseStructure ? '木製' : ''} + {surveyDetail?.detailInfo?.houseStructureEtc ? ` ${surveyDetail?.detailInfo?.houseStructureEtc}` : '-'} @@ -468,8 +479,10 @@ export default function SurveySaleDownloadPdf() { boxSizing: 'border-box', }} > - {radioEtcData.rafterMaterial.find((material) => material.id.toString() === surveyDetail?.detailInfo?.rafterMaterial)?.label ?? - (surveyDetail?.detailInfo?.rafterMaterialEtc ? `(その他) ${surveyDetail?.detailInfo?.rafterMaterialEtc}` : '-')} + {surveyDetail?.detailInfo?.rafterMaterial === null && surveyDetail?.detailInfo?.rafterMaterialEtc === null + ? '-' + : radioEtcData.rafterMaterial.find((material) => material.id.toString() === surveyDetail?.detailInfo?.rafterMaterial)?.label ?? + surveyDetail?.detailInfo?.rafterMaterialEtc} {selectBoxOptions.rafterSize.find((size) => size.id.toString() === surveyDetail?.detailInfo?.rafterSize)?.name ?? - (surveyDetail?.detailInfo?.rafterSizeEtc ? `(その他) ${surveyDetail?.detailInfo?.rafterSizeEtc}` : '-')} + (surveyDetail?.detailInfo?.rafterSizeEtc ? ` ${surveyDetail?.detailInfo?.rafterSizeEtc}` : '-')} @@ -528,7 +541,7 @@ export default function SurveySaleDownloadPdf() { }} > {selectBoxOptions.rafterPitch.find((pitch) => pitch.id.toString() === surveyDetail?.detailInfo?.rafterPitch)?.name ?? - (surveyDetail?.detailInfo?.rafterPitchEtc ? `(その他) ${surveyDetail?.detailInfo?.rafterPitchEtc}` : '-')} + (surveyDetail?.detailInfo?.rafterPitchEtc ? ` ${surveyDetail?.detailInfo?.rafterPitchEtc}` : '-')} {selectBoxOptions.openFieldPlateKind.find((kind) => kind.id.toString() === surveyDetail?.detailInfo?.openFieldPlateKind)?.name ?? - (surveyDetail?.detailInfo?.openFieldPlateKindEtc ? `(その他) ${surveyDetail?.detailInfo?.openFieldPlateKindEtc}` : '-')} + (surveyDetail?.detailInfo?.openFieldPlateKindEtc ? `${surveyDetail?.detailInfo?.openFieldPlateKindEtc}` : '-')} {radioEtcData.waterproofMaterial.find((material) => material.id.toString() === surveyDetail?.detailInfo?.waterproofMaterial) - ?.label ?? - (surveyDetail?.detailInfo?.waterproofMaterialEtc ? `(その他) ${surveyDetail?.detailInfo?.waterproofMaterialEtc}` : '-')} + ?.label ?? (surveyDetail?.detailInfo?.waterproofMaterialEtc ? ` ${surveyDetail?.detailInfo?.waterproofMaterialEtc}` : '-')} @@ -711,7 +723,7 @@ export default function SurveySaleDownloadPdf() { radioEtcData.insulationPresence.find((presence) => presence.id.toString() === surveyDetail?.detailInfo?.insulationPresence) ?.label } - {surveyDetail?.detailInfo?.insulationPresenceEtc ? `(その他) ${surveyDetail?.detailInfo?.insulationPresenceEtc}` : '-'} + {surveyDetail?.detailInfo?.insulationPresenceEtc ? ` ${surveyDetail?.detailInfo?.insulationPresenceEtc}` : '-'} @@ -742,7 +754,7 @@ export default function SurveySaleDownloadPdf() { }} > {selectBoxOptions.structureOrder.find((order) => order.id.toString() === surveyDetail?.detailInfo?.structureOrder)?.name ?? - (surveyDetail?.detailInfo?.structureOrderEtc ? `(その他) ${surveyDetail?.detailInfo?.structureOrderEtc}` : '-')} + (surveyDetail?.detailInfo?.structureOrderEtc ? ` ${surveyDetail?.detailInfo?.structureOrderEtc}` : '-')} @@ -785,9 +797,7 @@ export default function SurveySaleDownloadPdf() { (availability) => availability.id.toString() === surveyDetail?.detailInfo?.installationAvailability, )?.name } - {surveyDetail?.detailInfo?.installationAvailabilityEtc - ? `(その他) ${surveyDetail?.detailInfo?.installationAvailabilityEtc}` - : '-'} + {surveyDetail?.detailInfo?.installationAvailabilityEtc ? ` ${surveyDetail?.detailInfo?.installationAvailabilityEtc}` : '-'} From 03d91f3fa0208fdce5d7cd744515474f17da3fdf Mon Sep 17 00:00:00 2001 From: keyy1315 Date: Wed, 28 May 2025 16:49:45 +0900 Subject: [PATCH 09/12] feat: implement spinning when generate survey-sale pdf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 조사매물 pdf 다운로드 기능 완성 - 지붕 정보 주택 구조 순서 radiobox로 변경경 --- src/components/pdf/SurveySaleDownloadPdf.tsx | 53 ++++++++++--------- .../popup/SurveySaleSubmitPopup.tsx | 17 +++++- .../survey-sale/detail/RoofForm.tsx | 36 ++++++------- 3 files changed, 58 insertions(+), 48 deletions(-) diff --git a/src/components/pdf/SurveySaleDownloadPdf.tsx b/src/components/pdf/SurveySaleDownloadPdf.tsx index 8d8adf9..02ba732 100644 --- a/src/components/pdf/SurveySaleDownloadPdf.tsx +++ b/src/components/pdf/SurveySaleDownloadPdf.tsx @@ -1,27 +1,29 @@ 'use client' -import { useEffect, useRef, useState } from 'react' +import { useEffect, useRef } from 'react' import generatePDF, { Margin, Resolution } from 'react-to-pdf' import { useParams, useRouter } from 'next/navigation' import { useSurvey } from '@/hooks/useSurvey' import { radioEtcData, roofMaterial, selectBoxOptions, supplementaryFacilities } from '../survey-sale/detail/RoofForm' +import { useSpinnerStore } from '@/store/spinnerStore' export default function SurveySaleDownloadPdf() { const params = useParams() const id = params.id + const router = useRouter() const { surveyDetail, isLoadingSurveyDetail } = useSurvey(Number(id)) - const [isLoading, setIsLoading] = useState(false) - const router = useRouter() + const { setIsShow } = useSpinnerStore() const targetRef = useRef(null) const isGeneratedRef = useRef(false) - // useEffect(() => { - // if (isLoadingSurveyDetail || !surveyDetail || isGeneratedRef.current) return - // isGeneratedRef.current = true - // handleDownPdf() - // }, [surveyDetail?.id, isLoadingSurveyDetail]) + useEffect(() => { + setIsShow(true) + if (isLoadingSurveyDetail || !surveyDetail || isGeneratedRef.current) return + isGeneratedRef.current = true + handleDownPdf() + }, [surveyDetail?.id, isLoadingSurveyDetail]) const handleDownPdf = () => { const options = { @@ -47,6 +49,7 @@ export default function SurveySaleDownloadPdf() { } generatePDF(targetRef, options).then(() => { + setIsShow(false) router.push(`/survey-sale/${id}`) }) } @@ -56,11 +59,9 @@ export default function SurveySaleDownloadPdf() { return ( <> - {/* */}
-
+
HWJ 現地調査シート1/2 @@ -449,8 +448,8 @@ export default function SurveySaleDownloadPdf() { boxSizing: 'border-box', }} > - {surveyDetail?.detailInfo?.houseStructure ? '木製' : ''} - {surveyDetail?.detailInfo?.houseStructureEtc ? ` ${surveyDetail?.detailInfo?.houseStructureEtc}` : '-'} + {radioEtcData.houseStructure.find((structure) => structure.id.toString() === surveyDetail?.detailInfo?.houseStructure)?.label ?? + (surveyDetail?.detailInfo?.houseStructureEtc ? ` ${surveyDetail?.detailInfo?.houseStructureEtc}` : '-')} @@ -479,10 +478,12 @@ export default function SurveySaleDownloadPdf() { boxSizing: 'border-box', }} > - {surveyDetail?.detailInfo?.rafterMaterial === null && surveyDetail?.detailInfo?.rafterMaterialEtc === null + {/* {surveyDetail?.detailInfo?.rafterMaterial === null && surveyDetail?.detailInfo?.rafterMaterialEtc === null ? '-' : radioEtcData.rafterMaterial.find((material) => material.id.toString() === surveyDetail?.detailInfo?.rafterMaterial)?.label ?? - surveyDetail?.detailInfo?.rafterMaterialEtc} + surveyDetail?.detailInfo?.rafterMaterialEtc} */} + {radioEtcData.rafterMaterial.find((material) => material.id.toString() === surveyDetail?.detailInfo?.rafterMaterial)?.label ?? + (surveyDetail?.detailInfo?.rafterMaterialEtc ? ` ${surveyDetail?.detailInfo?.rafterMaterialEtc}` : '-')} presence.id.toString() === surveyDetail?.detailInfo?.insulationPresence) ?.label } - {surveyDetail?.detailInfo?.insulationPresenceEtc ? ` ${surveyDetail?.detailInfo?.insulationPresenceEtc}` : '-'} + {surveyDetail?.detailInfo?.insulationPresenceEtc ? `, ${surveyDetail?.detailInfo?.insulationPresenceEtc}` : ''} @@ -753,8 +754,8 @@ export default function SurveySaleDownloadPdf() { boxSizing: 'border-box', }} > - {selectBoxOptions.structureOrder.find((order) => order.id.toString() === surveyDetail?.detailInfo?.structureOrder)?.name ?? - (surveyDetail?.detailInfo?.structureOrderEtc ? ` ${surveyDetail?.detailInfo?.structureOrderEtc}` : '-')} + {radioEtcData.structureOrder.find((order) => order.id.toString() === surveyDetail?.detailInfo?.structureOrder)?.label ?? + (surveyDetail?.detailInfo?.structureOrderEtc ? `${surveyDetail?.detailInfo?.structureOrderEtc}` : '-')} @@ -792,12 +793,12 @@ export default function SurveySaleDownloadPdf() { boxSizing: 'border-box', }} > - { - selectBoxOptions.installationAvailability.find( - (availability) => availability.id.toString() === surveyDetail?.detailInfo?.installationAvailability, - )?.name - } - {surveyDetail?.detailInfo?.installationAvailabilityEtc ? ` ${surveyDetail?.detailInfo?.installationAvailabilityEtc}` : '-'} + {surveyDetail?.detailInfo?.installationAvailability === null && surveyDetail.detailInfo?.installationAvailabilityEtc === null + ? '-' + : selectBoxOptions.installationAvailability.find( + (availability) => availability.id.toString() === surveyDetail?.detailInfo?.installationAvailability, + )?.name} + {surveyDetail?.detailInfo?.installationAvailabilityEtc ? `, ${surveyDetail?.detailInfo?.installationAvailabilityEtc}` : ''} diff --git a/src/components/popup/SurveySaleSubmitPopup.tsx b/src/components/popup/SurveySaleSubmitPopup.tsx index 426d49c..8d02bfe 100644 --- a/src/components/popup/SurveySaleSubmitPopup.tsx +++ b/src/components/popup/SurveySaleSubmitPopup.tsx @@ -6,12 +6,14 @@ import { useEffect, useState } from 'react' import { useSessionStore } from '@/store/session' import { useCommCode } from '@/hooks/useCommCode' import { CommCode } from '@/types/CommCode' +// import { sendEmail } from '@/libs/mailer' +import { useSpinnerStore } from '@/store/spinnerStore' interface SubmitFormData { saleBase: string | null store: string sender: string - receiver: string[] + receiver: string[] | string reference: string | null title: string contents: string @@ -29,6 +31,7 @@ export default function SurveySaleSubmitPopup() { const params = useParams() const routeId = params.id + const { setIsShow } = useSpinnerStore() const [commCodeList, setCommCodeList] = useState([]) const { getCommCode } = useCommCode() @@ -86,10 +89,22 @@ export default function SurveySaleSubmitPopup() { const handleSubmit = () => { if (validateData(submitData)) { window.neoConfirm('送信しますか? 送信後は変更・修正することはできません。', () => { + setIsShow(true) submitSurvey({ targetId: submitData.store }) + // sendEmail({ + // to: submitData.receiver, + // subject: submitData.title, + // content: submitData.contents, + // }) + // .then(() => { if (!isSubmittingSurvey) { popupController.setSurveySaleSubmitPopup(false) } + // }) + // .catch((error) => { + // console.error('Error sending email:', error) + // alert('メール送信に失敗しました。') + // }) }) } } diff --git a/src/components/survey-sale/detail/RoofForm.tsx b/src/components/survey-sale/detail/RoofForm.tsx index 3e8dcc2..4760808 100644 --- a/src/components/survey-sale/detail/RoofForm.tsx +++ b/src/components/survey-sale/detail/RoofForm.tsx @@ -1,7 +1,14 @@ import { useState } from 'react' import type { Mode, SurveyDetailInfo, SurveyDetailRequest } from '@/types/Survey' -type RadioEtcKeys = 'houseStructure' | 'rafterMaterial' | 'waterproofMaterial' | 'insulationPresence' | 'rafterDirection' | 'leakTrace' +type RadioEtcKeys = + | 'structureOrder' + | 'houseStructure' + | 'rafterMaterial' + | 'waterproofMaterial' + | 'insulationPresence' + | 'rafterDirection' + | 'leakTrace' type SelectBoxKeys = | 'installationSystem' | 'constructionYear' @@ -9,7 +16,6 @@ type SelectBoxKeys = | 'rafterPitch' | 'rafterSize' | 'openFieldPlateKind' - | 'structureOrder' | 'installationAvailability' export const supplementaryFacilities = [ @@ -115,24 +121,6 @@ export const selectBoxOptions: Record = { + structureOrder: [ + { + id: 1, + label: '屋根材 - 防水材 - 屋根の基礎 - 垂木', //지붕재 방수재 지붕의기초 서까래 + }, + ], houseStructure: [ { id: 1, @@ -438,7 +432,7 @@ export default function RoofForm(props: {
{/* 지붕 구조의 순서 */}
屋根構造の順序
- +
{/* 지붕 제품명 설치 가능 여부 확인 */} From 8f365f998e40af127ba3ccb645ec6a281cf168aa Mon Sep 17 00:00:00 2001 From: keyy1315 Date: Wed, 28 May 2025 17:00:22 +0900 Subject: [PATCH 10/12] fix: add finally function after failed send email --- .../popup/SurveySaleSubmitPopup.tsx | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/components/popup/SurveySaleSubmitPopup.tsx b/src/components/popup/SurveySaleSubmitPopup.tsx index 8d02bfe..7a50406 100644 --- a/src/components/popup/SurveySaleSubmitPopup.tsx +++ b/src/components/popup/SurveySaleSubmitPopup.tsx @@ -6,7 +6,7 @@ import { useEffect, useState } from 'react' import { useSessionStore } from '@/store/session' import { useCommCode } from '@/hooks/useCommCode' import { CommCode } from '@/types/CommCode' -// import { sendEmail } from '@/libs/mailer' +import { sendEmail } from '@/libs/mailer' import { useSpinnerStore } from '@/store/spinnerStore' interface SubmitFormData { @@ -91,20 +91,23 @@ export default function SurveySaleSubmitPopup() { window.neoConfirm('送信しますか? 送信後は変更・修正することはできません。', () => { setIsShow(true) submitSurvey({ targetId: submitData.store }) - // sendEmail({ - // to: submitData.receiver, - // subject: submitData.title, - // content: submitData.contents, - // }) - // .then(() => { + sendEmail({ + to: submitData.receiver, + subject: submitData.title, + content: submitData.contents, + }) + .then(() => { if (!isSubmittingSurvey) { popupController.setSurveySaleSubmitPopup(false) } - // }) - // .catch((error) => { - // console.error('Error sending email:', error) - // alert('メール送信に失敗しました。') - // }) + }) + .catch((error) => { + console.error('Error sending email:', error) + alert('メール送信に失敗しました。') + }) + .finally(() => { + setIsShow(false) + }) }) } } From 495aeef2c2d4276129ef565a417f95ac502a6356 Mon Sep 17 00:00:00 2001 From: keyy1315 Date: Wed, 28 May 2025 17:04:26 +0900 Subject: [PATCH 11/12] chore: change set env --- .env.localhost | 2 +- src/libs/mailer.ts | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.env.localhost b/.env.localhost index 482880c..844bc76 100644 --- a/.env.localhost +++ b/.env.localhost @@ -20,7 +20,7 @@ DB_PORT=3306 SMTP_HOST=autodiscover.qcells.com SMTP_PORT=25 -SMTP_SECURE=true +SMTP_SECURE=false SMTP_USER=hss404.u021@cleverse.dev SMTP_PASSWORD=0000 SMTP_FROM=qsalesplatform@qcells.com diff --git a/src/libs/mailer.ts b/src/libs/mailer.ts index a3f06e7..bfff92f 100644 --- a/src/libs/mailer.ts +++ b/src/libs/mailer.ts @@ -13,6 +13,7 @@ export async function sendEmail({ to, cc, subject, content }: EmailParams): Prom host: process.env.SMTP_HOST, port: Number(process.env.SMTP_PORT), secure: process.env.SMTP_SECURE === 'true', + requireTLS: true, auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASSWORD, From 0465f2306b61a6483a46038f33a5537ab38f8fa1 Mon Sep 17 00:00:00 2001 From: keyy1315 Date: Wed, 28 May 2025 17:07:05 +0900 Subject: [PATCH 12/12] chore: change set env --- .env.development | 2 +- src/libs/mailer.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.env.development b/.env.development index e47f69e..2034c56 100644 --- a/.env.development +++ b/.env.development @@ -20,7 +20,7 @@ DB_PORT=3306 SMTP_HOST=autodiscover.qcells.com SMTP_PORT=25 -SMTP_SECURE=true +SMTP_SECURE=false SMTP_USER=hss404.u021@cleverse.dev SMTP_PASSWORD=0000 SMTP_FROM=qsalesplatform@qcells.com \ No newline at end of file diff --git a/src/libs/mailer.ts b/src/libs/mailer.ts index bfff92f..0636df2 100644 --- a/src/libs/mailer.ts +++ b/src/libs/mailer.ts @@ -1,3 +1,5 @@ +'use server' + import nodemailer from 'nodemailer' interface EmailParams {