develop #71

병합
nankyung develop 에서 main 로 7 commits 를 머지했습니다 2026-03-06 07:38:45 +09:00
3개의 변경된 파일158개의 추가작업 그리고 0개의 파일을 삭제
Showing only changes of commit f974162e3a - Show all commits

파일 보기

@ -32,6 +32,7 @@
"react": "^19.2.0",
"react-dom": "^19.2.0",
"socket.io-client": "^4.8.3",
"xlsx": "^0.18.5",
"zustand": "^5.0.11"
},
"devDependencies": {
@ -2847,6 +2848,15 @@
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
"node_modules/adler-32": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz",
"integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==",
"license": "Apache-2.0",
"engines": {
"node": ">=0.8"
}
},
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
@ -3201,6 +3211,19 @@
],
"license": "CC-BY-4.0"
},
"node_modules/cfb": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz",
"integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==",
"license": "Apache-2.0",
"dependencies": {
"adler-32": "~1.3.0",
"crc-32": "~1.2.0"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@ -3265,6 +3288,15 @@
"node": ">= 6"
}
},
"node_modules/codepage": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz",
"integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==",
"license": "Apache-2.0",
"engines": {
"node": ">=0.8"
}
},
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@ -3340,6 +3372,18 @@
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
"license": "MIT"
},
"node_modules/crc-32": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz",
"integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==",
"license": "Apache-2.0",
"bin": {
"crc32": "bin/crc32.njs"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@ -4019,6 +4063,15 @@
"node": ">= 6"
}
},
"node_modules/frac": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz",
"integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==",
"license": "Apache-2.0",
"engines": {
"node": ">=0.8"
}
},
"node_modules/fraction.js": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz",
@ -5744,6 +5797,18 @@
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
"license": "BSD-3-Clause"
},
"node_modules/ssf": {
"version": "0.11.2",
"resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz",
"integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
"license": "Apache-2.0",
"dependencies": {
"frac": "~1.1.2"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
@ -6212,6 +6277,24 @@
"node": ">= 8"
}
},
"node_modules/wmf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz",
"integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==",
"license": "Apache-2.0",
"engines": {
"node": ">=0.8"
}
},
"node_modules/word": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz",
"integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==",
"license": "Apache-2.0",
"engines": {
"node": ">=0.8"
}
},
"node_modules/word-wrap": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
@ -6243,6 +6326,27 @@
}
}
},
"node_modules/xlsx": {
"version": "0.18.5",
"resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz",
"integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==",
"license": "Apache-2.0",
"dependencies": {
"adler-32": "~1.3.0",
"cfb": "~1.2.1",
"codepage": "~1.15.0",
"crc-32": "~1.2.1",
"ssf": "~0.11.2",
"wmf": "~1.0.1",
"word": "~0.3.0"
},
"bin": {
"xlsx": "bin/xlsx.njs"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/xmlhttprequest-ssl": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz",

파일 보기

@ -34,6 +34,7 @@
"react": "^19.2.0",
"react-dom": "^19.2.0",
"socket.io-client": "^4.8.3",
"xlsx": "^0.18.5",
"zustand": "^5.0.11"
},
"devDependencies": {

파일 보기

@ -1,4 +1,5 @@
import { useState, useEffect, useCallback } from 'react'
import * as XLSX from 'xlsx'
import { fetchInsurance } from '../services/assetsApi'
import type { ShipInsuranceItem } from '../services/assetsApi'
@ -69,6 +70,57 @@ function ShipInsurance() {
setIssueOrgFilter('')
}
const handleDownload = async () => {
try {
const all = await fetchInsurance({
search: search || undefined,
shipTp: shipTpFilter || undefined,
issueOrg: issueOrgFilter || undefined,
page: 1,
limit: 200,
})
// 200건 초과 시 추가 페이지 로드
let allRows = [...all.rows]
const pages = Math.ceil(all.total / 200)
for (let p = 2; p <= pages; p++) {
const res = await fetchInsurance({
search: search || undefined,
shipTp: shipTpFilter || undefined,
issueOrg: issueOrgFilter || undefined,
page: p,
limit: 200,
})
allRows = allRows.concat(res.rows)
}
const excelRows = allRows.map((r, i) => ({
'No': i + 1,
'선박명': r.shipNm,
'호출부호': r.callSign,
'IMO': r.imoNo,
'선박종류': r.shipTp,
'선박종류상세': r.shipTpDetail,
'선주': r.ownerNm,
'총톤수': r.grossTon ? Number(r.grossTon) : '',
'보험사': r.insurerNm,
'책임보험': r.liabilityYn,
'유류오염': r.oilPollutionYn,
'연료유오염': r.fuelOilYn,
'난파물제거': r.wreckRemovalYn,
'유효시작': r.validStart,
'유효종료': r.validEnd,
'발급기관': r.issueOrg,
}))
const ws = XLSX.utils.json_to_sheet(excelRows)
const wb = XLSX.utils.book_new()
XLSX.utils.book_append_sheet(wb, ws, '유류오염보장계약')
XLSX.writeFile(wb, `유류오염보장계약_${new Date().toISOString().slice(0, 10)}.xlsx`)
} catch {
alert('다운로드 중 오류가 발생했습니다.')
}
}
return (
<div className="flex flex-col flex-1 overflow-auto">
@ -147,6 +199,7 @@ function ShipInsurance() {
</div>
<button onClick={handleSearch} className="px-5 py-2 text-white border-none rounded-sm text-xs font-bold cursor-pointer" style={{ background: 'linear-gradient(135deg, var(--cyan), var(--blue))' }}></button>
<button onClick={handleReset} className="px-4 py-2 bg-bg-0 text-text-2 border border-border rounded-sm text-xs cursor-pointer"></button>
<button onClick={handleDownload} disabled={total === 0} className="px-4 py-2 text-xs font-bold cursor-pointer rounded-sm disabled:opacity-30 disabled:cursor-default" style={{ background: 'rgba(34,197,94,.12)', color: 'var(--green)', border: '1px solid rgba(34,197,94,.3)' }}> </button>
</div>
</div>