import { vars } from '../archive/variable.js'; import { overviewVars } from './overviewVariable.js'; //πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½ 곡용 ν•¨μˆ˜ μ‹œμž‘ πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½ // 곡동도급 ν˜•μ‹ 자λ₯΄κΈ° export function splitStr(data) { if (data === null || data === undefined) return; if (data.includes('^&')) { const splitStr = data.split('^&'); return splitStr; } } // λ‚ μ§œ ν¬λ§·νŒ… export function sliceDate(date){ if(!date) return null; const formattedDate = date.slice(0,4) + '-' + date.slice(4,6) + '-' + date.slice(6,8); return formattedDate; } export function overviewVarsInit() { if(overviewVars.sectionTabData)overviewVars.sectionTabData = JSON.parse(JSON.stringify(overviewVars.originalSectionTabData)) overviewVars.deleteTaskHistory = []; if (!arraysEqual(overviewVars.filesArr, overviewVars.originalFilesArr)) overviewVars.filesArr = [...overviewVars.originalFilesArr]; if (!arraysEqual(overviewVars.filesSizeArr, overviewVars.originalFilesSizeArr))overviewVars.filesSizeArr = [...overviewVars.originalFilesSizeArr]; if (!arraysEqual(overviewVars.filesNameArr, overviewVars.originalFilesNameArr)) overviewVars.filesNameArr = [...overviewVars.originalFilesNameArr]; overviewDropboxInit(); } function arraysEqual(a, b) { if (!Array.isArray(a) || !Array.isArray(b)) return false; if (a.length !== b.length) return false; return a.every((value, index) => value === b[index]); } export function setOverviewType(){ // overseasλΆ„κΈ°μš© if(!window.location.host.toLowerCase().includes('overseas.')){ document.querySelectorAll('.only-overseas').forEach(ele => { ele.remove(); }) overviewVars.overseas = false; } else { document.querySelectorAll('.no-overseas').forEach(ele => { ele.remove(); }); overviewVars.overseas = true; } } //πŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”Ό 곡용 ν•¨μˆ˜ 끝 πŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”Ό //πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½ Section-Left μ‚¬μš© ν•¨μˆ˜ μ‹œμž‘ πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½ // 이미지 쀑볡 이름, ν™•μž₯자 체크 ν•¨μˆ˜ export function checkDuplicatesFileNameAndExt(files){ const duplicateNameArr = []; const notAllowExtArr = []; const acceptExt = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'] files.forEach(file => { const fileExt = file.name.split('.').pop().toLowerCase(); if(!acceptExt.includes(fileExt)){ notAllowExtArr.push(file); return; } const isDuplicateFile = overviewVars.filesArr.some(f => f.name === file.name); const isDuplicateFileName = overviewVars.filesNameArr.includes('overview/' + file.name); const isDuplicateFileSize = overviewVars.filesSizeArr.some(f => f.size === file.size); if(!isDuplicateFile && !isDuplicateFileName && !isDuplicateFileSize){ overviewVars.filesArr.push(file); overviewVars.filesNameArr.push(file.name); if(overviewVars.filesSizeArr[0] === 0 ) overviewVars.filesSizeArr = []; overviewVars.filesSizeArr.push(file.size); } else { duplicateNameArr.push(file); } }); if(duplicateNameArr.length > 0 || notAllowExtArr.length > 0){ alert(`λ‹€μŒ ν™•μž₯자만 등둝할 수 μžˆμŠ΅λ‹ˆλ‹€ : \n- ${acceptExt}\n \n` + 'κ·Έ 외에 ν™•μž₯자 λ˜λŠ” μ€‘λ³΅λœ νŒŒμΌμ€ 등둝할 수 μ—†μŠ΅λ‹ˆλ‹€.'); } } // DropBox에 파일 리슀트 생성 ν•¨μˆ˜ export function displayFileName(){ const dropbox = document.querySelector('.overview-modal.section-left .dropbox'); if(overviewVars.filesNameArr.length > 0 ){ dropbox.innerHTML = ''; dropbox.style.backgroundColor = '#fff' dropbox.style.alignItems = 'stretch'; dropbox.style.justifyContent = 'normal'; } overviewVars.filesNameArr.forEach(file => { const originalName = file; const displayName = file.replace('overview/', ''); const wrapDiv = document.createElement('div'); wrapDiv.classList.add('file-wrap-div'); wrapDiv.dataset.filepath = file; const iconImg = document.createElement('img'); iconImg.src = '/main/img/overview/icon-imageFile.svg'; iconImg.classList.add('dropbox-file-img'); const fileName = document.createElement('h3'); fileName.innerText = displayName; fileName.style.width = '95%'; const button = document.createElement('button'); button.classList.add('xs-btn'); button.addEventListener('click', async ()=> { const fileIndex = overviewVars.filesArr.findIndex(f => f.name === displayName); if(fileIndex !== -1) overviewVars.filesArr.splice(fileIndex, 1); const nameIndex = overviewVars.filesNameArr.findIndex(f => f === file); // λ°°μ—΄ μ‚­μ œ μ „ μ§€μ›Œμ•Όλ  key κ°’ μ €μž₯ let key = overviewVars.filesNameArr[nameIndex]; if(nameIndex !== -1){ overviewVars.filesNameArr.splice(nameIndex, 1); overviewVars.filesSizeArr.splice(nameIndex, 1); } // object-storage에 μ €μž₯된 file만 s3 api μ΄μš©ν•΄μ„œ μ‚­μ œ if(document.querySelector(`.overview .swiper-slide[data-filepath="${file}"]`)){ overviewVars.deleteImgArr.push(key); } overviewDropboxInit() wrapDiv.remove(); }); const buttonimg = document.createElement('img'); buttonimg.src = '/main/img/overview/icon-close-111.svg'; button.appendChild(buttonimg); wrapDiv.append(iconImg, fileName, button); dropbox.appendChild(wrapDiv); }); } export function overviewDropboxInit(){ if(overviewVars.filesNameArr.length === 0){ const dropbox = document.querySelector('.overview-modal.section-left .dropbox'); dropbox.innerHTML = `
icon-dropfile

μ—¬κΈ°λ‘œ νŒŒμΌμ„ λ“œλž˜κ·Έν•˜κ±°λ‚˜
우츑 μƒλ‹¨μ—μ„œ 이미지 νŒŒμΌμ„ μ—…λ‘œλ“œν•˜μ„Έμš”.

` dropbox.style.justifyContent = 'center'; dropbox.style.alignItems = 'center'; dropbox.style.backgroundColor = '#eee'; } } // μ ‘κ·Όμš© presignedUrl λ°œκΈ‰ export async function getPresignedURL(key) { const res = await axios.get(`/${vars.project_id}/overview/generateGetImgUrl`, { params: { key: key } }); const url = res.data; return url; }; // μ‚­μ œμš© presignedUrl λ°œκΈ‰ 이후에 minIO μ‚­μ œμš”μ²­ export async function generateDeleteImgUrl(key) { if (key === undefined) return; try { const res = await axios.delete(`/${vars.project_id}/overview/generateDeleteImgUrl`, { data: { key } }); let { url } = res.data; await axios.delete(url) return true; } catch (err) { console.error(err); } } // μ—…λ‘œλ“œμš© presignedURL λ°œκΈ‰ export async function uploadImgData(file) { try { const presignedUrlRes = await axios.post(`/${vars.project_id}/overview/generateUploadUrl`, { fileName: file.name }); let { url, key } = presignedUrlRes.data; const bucketRes = await axios.put(url, file, { headers: { 'Content-type': file.type || 'application/octet-stream' } }); if (bucketRes.status == 200) { return key; } } catch (error) { console.error('이미지 μ—…λ‘œλ“œ μ‹€νŒ¨: ', error) } } //πŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”Ό Section-Left μ‚¬μš© ν•¨μˆ˜ 끝 πŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”Ό //πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½ Section-Middle μ‚¬μš© ν•¨μˆ˜ μ‹œμž‘ πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½ // κ³΅λ™λ„κΈ‰ν‘œ κ΅¬λΆ„μž μΆ”κ°€ ν•¨μˆ˜ export function addJointContractDelimiter() { let representativeCompany = document.querySelector('.overview-modal .joint-contract-company-name')?.innerText; let companyName = ''; document.querySelectorAll('.overview-modal .joint-contract-company-name').forEach((name) => { companyName += name.innerText.trim().replace(/,/g, '') + '^&'; if (companyName === '^&') companyName = ''; }); let companyShares = ''; document.querySelectorAll('.overview-modal .joint-contract-company-shares').forEach((shares) => { companyShares += shares.innerText.trim().replace(/,/g, '') + '^&'; if (companyShares === '^&') companyShares = ''; }); let contractKrw = ''; document.querySelectorAll('.overview-modal .joint-contract-krw').forEach((krw) => { contractKrw += krw.innerText.trim().replace(/,/g, '') + '^&'; if (contractKrw === '^&') contractKrw = ''; }); let contractUsd = ''; document.querySelectorAll('.overview-modal .joint-contract-usd').forEach((usd) => { contractUsd += usd.innerText.trim().replace(/,/g, '') + '^&'; if (contractUsd === '^&') contractUsd = ''; }); return { representativeCompany, companyName, companyShares, contractKrw, contractUsd } } // 곡동도급 λ¬Έμžμ—΄ μž…λ ₯ μ œν•œ ν•¨μˆ˜ export function restrictToNumber(element, event) { let text = element.innerText; const shares = element.classList.contains('joint-contract-company-shares'); const payment = element.classList.contains('joint-contract-krw') || element.classList.contains('joint-contract-usd'); // μ§€λΆ„μœ¨ μ†Œμˆ˜μ  ν—ˆμš© if (shares) { text = text.replace(/[^0-9.]/g, ''); // μ†Œμˆ˜μ  쀑볡 μ œν•œ (숫자, .) const parts = text.split('.'); let integerPart = parts[0].replace(/^0+(?=\d)/,''); if(integerPart === '') integerPart = '0' if (parts.length > 1) { text = integerPart + '.' + parts.slice(1).join(''); } else { text = integerPart; } element.innerText = text; } else { // λ¬Έμžμ—΄ μ œν•œ (였직 숫자만) text = text.replace(/[^0-9]/g, ''); } // κ³„μ•½κΈˆ , 생성 if (payment) { //κ³„μ•½κΈˆ ,(콀마) 생성 if (isNaN(parseFloat(text))) { element.innerText = ''; } else { element.innerText = parseFloat(text).toLocaleString(); } if (!(event.data >= '0' && event.data <= '9')) showToolTip(element, '숫자만 μž…λ ₯ κ°€λŠ₯ν•©λ‹ˆλ‹€.'); } else { element.innerText = text; if (!((event.data >= '0' && event.data <= '9') || event.data == '.')) showToolTip(element, 'μˆ«μžμ™€ .만 μž…λ ₯ κ°€λŠ₯ν•©λ‹ˆλ‹€.'); } // μ»€μ„œ 맨끝으둜 μ΄λ™μ‹œν‚€κΈ° const range = document.createRange(); const sel = window.getSelection(); range.selectNodeContents(element); range.collapse(false); sel.removeAllRanges(); sel.addRange(range); } // λ¬Έμžμ—΄ μž…λ ₯ν–ˆμ„λ•Œ 툴팁 export function showToolTip(element, message) { let tooltip = document.querySelector('.overview-modal-tooltip'); if (!tooltip) { tooltip = document.createElement('div'); tooltip.className = 'overview-modal-tooltip'; document.body.appendChild(tooltip); } if (tooltip.dataset.active === 'true') return; tooltip.textContent = message; tooltip.style.opacity = '0.8'; tooltip.style.visibility = 'visible'; tooltip.dataset.active = 'true'; const rect = element.getBoundingClientRect(); tooltip.style.left = `${rect.left + window.scrollX + (rect.width / 2) - (tooltip.offsetWidth / 2)}px`; tooltip.style.top = `${rect.bottom + window.scrollY + 5}px`; setTimeout(() => { tooltip.style.opacity = '0'; tooltip.style.visibility = 'hidden'; tooltip.dataset.active = 'false' }, 1000); } // 곡동도급 μ§€λΆ„μœ¨,κ³„μ•½κΈˆ 계산 export function calculateTotalJointContract(element) { let totalValue = 0; let className = element.className; if (className === 'joint-contract-company-name' || className === 'total-joint-contract-company-name' || className === 'total-joint-contract-company-shares' || className === 'total-joint-contract-krw'|| className === 'total-joint-contract-usd' || className === 'sticky') return; document.querySelectorAll(`.overview-modal .${className}`).forEach(joint => { let value = parseFloat(joint.innerText.replaceAll(',', '').trim()); if (isNaN(value)) value = 0; totalValue += value; }); if (isNaN(totalValue)) totalValue = 0; if (className === 'joint-contract-company-shares') { // μ§€λΆ„μœ¨ 100%λ₯Ό λ„˜κ²Όμ„ λ•Œ κ°•μ œλ‘œ 남은 μ§€λΆ„μœ¨λ§ŒνΌλ§Œ μž…λ ₯λ˜λ„λ‘ if(totalValue > 100){ const excess = totalValue - 100; let current = parseFloat(element.innerText); element.innerText = current-excess; document.querySelector(`.overview-modal .total-${className}`).innerText = 100; showToolTip(element, 'μ§€λΆ„μœ¨μ€ 100%λ₯Ό λ„˜κΈΈ 수 μ—†μŠ΅λ‹ˆλ‹€.'); return; } document.querySelector(`.overview-modal .total-${className}`).innerText = totalValue; } else { document.querySelector(`.overview-modal .total-${className}`).innerText = totalValue.toLocaleString(); } } export function restrictDuplicatedTabName(){ // 쀑볡 νƒ­ 이름 μ œν•œ const tabs = document.querySelectorAll('.overview-modal .section-tabs .tab'); const tabValues = []; for(let tab of tabs){ const input = tab.querySelector('input'); const val = input ? input.value.trim() : ''; if(tabValues.includes(val)){ alert('μ€‘λ³΅λœ νƒ­ 이름이 μžˆμŠ΅λ‹ˆλ‹€.') return false; } tabValues.push(val); } return true; } //πŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”Ό Section-Middle μ‚¬μš© ν•¨μˆ˜ 끝 πŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”Ό //πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½ Section-Right μ‚¬μš© ν•¨μˆ˜ μ‹œμž‘ πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½πŸ”½ export function formatHour(hour) { const normalized = (hour + 24) % 24; const h = Math.floor(normalized); // μ •μˆ˜ μ‹œκ°„ const m = Math.round((normalized - h) * 60); // μ†Œμˆ˜μ  -> λΆ„ return `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`; } export function parseTimeToDecimal(timeStr) { const [h, m] = timeStr.split(':').map(Number); return h + (m / 60); } // 1μ‹œκ°„λ‹Ή 1.75rem κΈ°μ€€μœΌλ‘œ μœ„μΉ˜ 계산 export function calculateRemPosition(currentTime) { const currentHour = parseInt(currentTime.split(':')[0]); const currentMinute = parseInt(currentTime.split(':')[1]); const hourRem = 1.75 const minuteRem = 1.75 / 60; const moveHour = currentHour * hourRem; const moveMinute = currentMinute * minuteRem; // left 0으둜 λ†“μ•˜μ„λ•Œ 00:00에 μœ„μΉ˜ν•˜λ„λ‘ 보정 const moveRem = moveHour + moveMinute - 3.5; return moveRem } // νƒ€μž„μ‘΄ 계산을 톡해 μ–΄λŠ μž₯μ†Œμ—μ„œλ“  λ™μΌν•œ 결과값을 보μž₯ export function getTimeToTimeZone(timeZone) { const now = new Date(); const formatter = new Intl.DateTimeFormat('en-US', { hour: '2-digit', minute: '2-digit', hour12: false, timeZone: timeZone }); return formatter.format(now); } // 연속일정 Color λ³€κ²½ ν•¨μˆ˜ --> 연속일정에 λ°±κ·ΈλΌμš΄λ“œ 컬러λ₯Ό κ·ΈλŒ€λ‘œ λ„£μ—ˆλ‹€κ°„ 일정이 보여지지 μ•Šμ•„ 투λͺ…도λ₯Ό 높인 μƒ‰κΉ”λ‘œ λ³€κ²½ν•˜μ—¬ 연속일정에 적용 export function changeColor(color) { let dataColor = null; switch (color) { case "#F21D0D": dataColor = "#FEE9E7"; break; case "#B92ED1": dataColor = "#F8EBFB"; break; case "#6D3DC2": dataColor = "#F1ECF9"; break; case "#0D8DF2": dataColor = "#E7F4FE"; break; case "#4DB251": dataColor = "#EEF8EE"; break; case "#FFBF00": dataColor = "#FFF9E6"; break; case "#A0705F": dataColor = "#F6F1EF"; break; case "#7F7F7F": dataColor = "#F3F3F3"; break; case "#688897": dataColor = "#F0F4F5"; break; default: dataColor = "#FFFFFF"; } return dataColor; } // μ£Όμš”μΌμ • λͺ¨λ‹¬ μž‘λ™μ‹œ ν˜„μž¬μ‹œκ°„ 적용 export function setDefaultScheduleTime() { const now = new Date(); const yyyy = now.getFullYear(); const mm = (now.getMonth() + 1).toString().padStart(2, '0'); const dd = now.getDate().toString().padStart(2, '0'); const hh = now.getHours().toString().padStart(2, '0'); const min = now.getMinutes().toString().padStart(2, '0'); const today = `${yyyy}-${mm}-${dd}`; const timeNow = `${hh}:${min}`; const oneHourLater = new Date(now.getTime() + 60 * 60 * 1000); const hh2 = oneHourLater.getHours().toString().padStart(2, '0'); const min2 = oneHourLater.getMinutes().toString().padStart(2, '0'); const timeLater = `${hh2}:${min2}`; document.querySelector('.startDate').value = today; document.querySelector('.endDate').value = today; document.querySelector('.startTime').value = timeNow; document.querySelector('.endTime').value = timeLater; document.querySelector('.startTime').disabled = false document.querySelector('.endTime').disabled = false }; export function setIssueEditMode(isEdit){ const editBtn = document.querySelector('.overview .xs-btn-type.issue-edit'); const saveBtn = document.querySelector('.overview .xs-btn-type.issue-save'); const cancleBtn = document.querySelector('.overview .xs-btn-type.issue-cancle'); const issueMessage = document.querySelector('.overview .box.issue .wrap .message') const issueContent = document.querySelector('.overview .box.issue .wrap .issue-content'); editBtn.style.display = isEdit ? 'none' : 'block'; saveBtn.style.display = isEdit ? 'block' : 'none'; cancleBtn.style.display = isEdit ? 'block' : 'none'; issueContent.disabled = !isEdit; issueContent.style.color = isEdit ? '#ff3d00' : '#111'; if(isEdit){ issueMessage.classList.add('active'); issueMessage.innerText = 'λ‚΄μš©μ„ μž‘μ„±/μˆ˜μ •ν•œ ν›„ μ €μž₯ λ²„νŠΌμ„ λˆŒλŸ¬μ£Όμ„Έμš”'; issueMessage.style.color = '#111'; } else { issueMessage.classList.remove('active'); issueMessage.innerText = 'μˆ˜μ • 버턴을 눌러 λ‚΄μš©μ„ μž‘μ„±/μˆ˜μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.'; issueMessage.style.color = '#777'; } if(isEdit && issueContent.value.length > 0) issueMessage.style.color = '#ddd'; } export function applyUtcOffsetTime(offset){ const now = new Date(); const hourOffset = Math.trunc(offset/3600); let minuteOffset = 0; if(offset % 3600 !==0){ minuteOffset = (offset/3600) - hourOffset; if(minuteOffset == 0.75) minuteOffset = 45; if(minuteOffset == 0.5) minuteOffset = 30; if(minuteOffset == 0.25) minuteOffset = 15; } const hours = now.getUTCHours() + hourOffset; const minute = now.getUTCMinutes() + minuteOffset; const date = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), hours, minute)) return `${date.getUTCHours().toString().padStart(2,'0')}:${date.getUTCMinutes().toString().padStart(2,'0')}`; } export function fillPartialBlock(block, fraction, isStart) { if (!block || fraction === 0) return; const halfBlock = block.querySelectorAll('.timetable-half-block'); const quarterBlock = block.querySelectorAll('.timetable-quarter-block'); if(isStart){ if(fraction == 0.25){ quarterBlock[1].classList.add('work-hour'); halfBlock[1].classList.add('work-hour'); } if(fraction == 0.5)halfBlock[1].classList.add('work-hour'); if(fraction == 0.75)quarterBlock[3].classList.add('work-hour'); } else { if(fraction == 0.25)quarterBlock[0].classList.add('work-hour'); if(fraction == 0.5)halfBlock[0].classList.add('work-hour'); if(fraction == 0.75){ halfBlock[0].classList.add('work-hour'); quarterBlock[2].classList.add('work-hour'); } } } //πŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”Ό Section-Right μ‚¬μš© ν•¨μˆ˜ 끝 πŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”ΌπŸ”Ό