Files
egbim_homepage/egbim/skin/sales/html/main_sub/weekly_plan.php
T
2026-07-23 16:15:57 +09:00

478 lines
13 KiB
PHP

<?php
$pdo = new PDO("mysql:host=localhost;dbname=egbim;charset=utf8mb4","egbim","baron3840!!");
$rows = $pdo->query("
SELECT
s.schedule_date,
s.time_period,
s.content,
s.emp_no,
m.emp_name,
c.client_name
FROM sales_schedules s
LEFT JOIN sales_members m ON s.emp_no = m.emp_no
LEFT JOIN sales_clients c ON s.client_code = c.client_code
")->fetchAll(PDO::FETCH_ASSOC);
// 사번 매핑
$tagMap = [
"j01201" => "권",
"223070" => "염",
"m21430" => "김",
"b21367" => "윤",
];
$eventsData = [];
foreach ($rows as $r) {
$date = $r["schedule_date"];
$empNo = strtolower($r["emp_no"]);
if (!isset($eventsData[$date])) {
$eventsData[$date] = [];
}
$time = trim($r["time_period"]); // 공백 제거
$time = str_replace(["\r", "\n", "\t"], "", $time); // 숨은 문자 제거
$eventsData[$date][] = [
"time" => $time, // ⭐ 핵심
"title" => $r["content"],
"tags" => [ $tagMap[$empNo] ?? "" ]
];
}
// JS로 전달
echo "<script>var eventsData = " . json_encode($eventsData, JSON_UNESCAPED_UNICODE) . ";</script>";
?>
<div class="main-weekly weekly" id="weekly">
<div class="weekly-grid">
<div class="weekly-header">
<div class="weekly-title">
<p>주간 영업 계획</p>
<div class="week-navigation">
<button class="week-nav-btn" id="prevWeek" title="이전 주">
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#424242"
stroke-width="2"
>
<path d="M15 18l-6-6 6-6" />
</svg>
</button>
<h3 id="weekTitle">11월 5주차</h3>
<button class="week-nav-btn" id="nextWeek" title="다음 주">
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="#424242"
stroke-width="2"
>
<path d="M9 18l6-6-6-6" />
</svg>
</button>
</div>
</div>
<ul class="person-list">
<li>
<span class="badge-green">권</span><span class="name">권혁진 <small>수석</small></span>
</li>
<li>
<span class="badge-purple">염</span><span class="name">염승호 <small>수석</small></span>
</li>
<li>
<span class="badge-teal">김</span><span class="name">김지영 <small>선임</small></span>
</li>
<li>
<span class="badge-black">윤</span><span class="name">윤준수 <small>선임</small></span>
</li>
</ul>
</div>
<div class="schedule" id="scheduleContainer"></div>
</div>
<div class="main-issue">
<div class="issue-header">
<h3>주요 이슈 사항</h3>
</div>
<div class="issue">
<ul class="issue-list">
<li>주요 이슈 A</li>
<li>주요 이슈 B</li>
</ul>
</div>
</div>
</div>
<script src="./assets/js/schedule-manager.min.js"></script>
<!-- <script src="./assets/js/events-data.min.js"></script> -->
<script>
const personOrder = {
"권": 1,
"염": 2,
"김": 3,
"윤": 4,
};
function isMorning(event) {
return event.time === "오전";
}
function isAfternoon(event) {
return event.time === "오후";
}
// 태그 매핑
const tagMapping = {
권: "green",
염: "purple",
김: "teal",
윤: "black",
};
(function() {
'use strict';
// ⭐ scheduleManager를 상단에 선언 (초기화는 나중에)
let scheduleManager;
async function loadIssueText() {
// ⭐ 현재 주간 달 기준으로 변경
const year = currentWeekStart.getFullYear();
const month = String(currentWeekStart.getMonth() + 1).padStart(2, "0");
const ym = `${year}-${month}`;
let res = await fetch(`/egbim/bbs/sales_issue.php?action=get&issue_month=${ym}`);
let json = await res.json();
const issue = json.issue_text ?? "";
const ul = document.querySelector(".issue-list");
ul.innerHTML = "";
if (issue.trim() === "") {
ul.innerHTML = "<li>이번 달 주요 이슈가 없습니다.</li>";
return;
}
issue.split("\n").forEach(line => {
if (line.trim() !== "") {
ul.innerHTML += `<li>${line}</li>`;
}
});
}
// 현재 날짜에서 이번 주 월요일 구하기
function getThisMonday() {
const today = new Date();
const day = today.getDay(); // 0(일) ~ 6(토)
const diff = day === 0 ? -6 : 1 - day; // 일요일이면 -6, 아니면 1-day
const monday = new Date(today);
monday.setDate(today.getDate() + diff);
monday.setHours(0, 0, 0, 0); // 시간 초기화
return monday;
}
// 현재 주차 상태
let currentWeekStart = getThisMonday();
// 주차 타이틀 업데이트
function updateWeekTitle() {
const weekStart = new Date(currentWeekStart);
const month = weekStart.getMonth() + 1;
const startDate = weekStart.getDate();
// 해당 월의 몇 번째 주인지 계산
const firstDayOfMonth = new Date(
weekStart.getFullYear(),
weekStart.getMonth(),
1,
);
const firstDayOfWeek = firstDayOfMonth.getDay() < 2 ? 7 : firstDayOfMonth.getDay();
const offset = firstDayOfWeek - 1;
//const weekOfMonth = Math.ceil((startDate + firstDayOfMonth.getDay()) / 7);
const weekOfMonth = Math.floor((startDate + offset) / 7);
document.getElementById("weekTitle").textContent =
`${month}월 ${weekOfMonth}주차`;
}
// 요일 이름 가져오기
function getDayName(dayIndex) {
const days = ["일", "월", "화", "수", "목", "금", "토"];
return days[dayIndex];
}
// 주간 일정 렌더링
function renderWeeklySchedule() {
const container = document.getElementById("scheduleContainer");
container.innerHTML = "";
// 월요일부터 금요일까지 (5일)
for (let i = 0; i < 5; i++) {
const currentDate = new Date(currentWeekStart);
currentDate.setDate(currentWeekStart.getDate() + i);
const year = currentDate.getFullYear();
const month = String(currentDate.getMonth() + 1).padStart(2, "0");
const day = String(currentDate.getDate()).padStart(2, "0");
const dateKey = `${year}-${month}-${day}`;
const dayOfWeek = getDayName(currentDate.getDay());
const dayEvents = eventsData[dateKey] || [];
dayEvents.sort((a, b) => {
const aTag = a.tags[0] ?? "";
const bTag = b.tags[0] ?? "";
return (personOrder[aTag] || 99) - (personOrder[bTag] || 99);
});
// 카드 생성
const dayCard = document.createElement("div");
dayCard.className = "day-card";
dayCard.dataset.date = dateKey;
let morningHTML = "";
let afternoonHTML = "";
dayEvents.forEach((event) => {
console.log(
dateKey,
event.time,
JSON.stringify(event.time),
isMorning(event),
isAfternoon(event)
);
});
dayEvents.forEach((event) => {
const tagsHTML = event.tags
.map(tag => `<span class="badge-${tagMapping[tag]}">${tag}</span>`)
.join("");
const itemHTML = `
<li>
<a href="#" class="schedule-item">
${tagsHTML}
${event.title}
</a>
</li>
`;
if (isMorning(event)) {
morningHTML += itemHTML;
}
if (isAfternoon(event)) {
afternoonHTML += itemHTML;
}
});
let dayHTML = `
<div class="day-title">${day}일 <span>(${dayOfWeek})</span></div>
<div class="day">
<dl>
<dt>오전</dt>
<dd class="day-content">
${morningHTML}
</dd>
</dl>
<dl>
<dt>오후</dt>
<dd class="day-content">
${afternoonHTML}
</dd>
</dl>
</div>
`;
dayCard.innerHTML = dayHTML;
container.appendChild(dayCard);
}
updateWeekTitle();
if (scheduleManager && typeof scheduleManager.initialize === "function") {
scheduleManager.initialize();
}
}
// 이벤트 리스너 등록 함수
function setupEventListeners() {
const prevWeekBtn = document.getElementById("prevWeek");
const nextWeekBtn = document.getElementById("nextWeek");
// 이전 주로 이동
if (prevWeekBtn) {
prevWeekBtn.addEventListener("click", () => {
currentWeekStart.setDate(currentWeekStart.getDate() - 7);
renderWeeklySchedule();
loadIssueText();
});
}
// 다음 주로 이동
if (nextWeekBtn) {
nextWeekBtn.addEventListener("click", () => {
currentWeekStart.setDate(currentWeekStart.getDate() + 7);
renderWeeklySchedule();
loadIssueText();
});
}
}
// ⭐ 초기화 함수
function init() {
// ScheduleManager가 존재하는지 확인
if (typeof ScheduleManager !== 'undefined') {
scheduleManager = new ScheduleManager();
scheduleManager.initialize();
}
// 이벤트 리스너 등록
setupEventListeners();
// 초기 렌더링
renderWeeklySchedule();
loadIssueText();
}
// ⭐ DOM 로드 완료 후 실행
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();
</script>
<script>
let isCalendarLoaded = false;
// 모달 열기
function openModal() {
const existingModal = document.getElementById("scheduleModal");
// 기존 모달이 있으면 제거
if (existingModal) {
existingModal.remove();
}
// 항상 새로 로드 (데이터 최신화)
fetchScheduleDetail();
}
// 모달 닫기
function closeModal() {
const modal = document.getElementById("scheduleModal");
modal.classList.add("closing");
isCalendarLoaded = false;
setTimeout(() => {
modal.remove();
}, 400);
}
// AJAX로 calendar.html 페이지 가져오기
let calendarScriptsLoaded = false;
function fetchScheduleDetail() {
const weekly = document.getElementById("weekly");
fetch(`./html/main_sub/calendar.php`)
.then((response) => response.text())
.then((html) => {
// 기존 모달 제거
const existingModal = document.getElementById("scheduleModal");
if (existingModal) existingModal.remove();
// 새로운 모달 삽입
const parser = new DOMParser();
const doc = parser.parseFromString(html, "text/html");
// ⭐ body의 자식 노드들을 추가
doc.body.childNodes.forEach(node => {
if (node.nodeType === Node.ELEMENT_NODE || node.nodeType === Node.TEXT_NODE) {
weekly.appendChild(node.cloneNode(true));
}
});
// ⭐ 스크립트 처리 개선
const scripts = doc.querySelectorAll("script");
if (!calendarScriptsLoaded) {
// 첫 번째 로딩: 모든 스크립트 실행
scripts.forEach(script => {
const newScript = document.createElement("script");
if (script.src) {
newScript.src = script.src;
} else {
newScript.textContent = script.textContent;
}
document.body.appendChild(newScript);
});
calendarScriptsLoaded = true;
} else {
// ⭐ 두 번째 이후: 인라인 스크립트만 재실행
scripts.forEach(script => {
if (!script.src) {
// src가 없는 인라인 스크립트만 실행
try {
eval(script.textContent);
} catch (error) {
console.error('Script execution error:', error);
}
}
});
}
// ⭐ 모달이 추가된 후 초기화 함수 명시적 호출
setTimeout(() => {
if (typeof initializeCalendar === "function") {
initializeCalendar();
}
if (typeof renderCalendar === "function") {
renderCalendar();
}
if (typeof checkOverflow === "function") {
checkOverflow();
}
if (typeof bindToggleEvents === "function") {
bindToggleEvents();
}
}, 100);
})
.catch(error => {
console.error('Calendar loading error:', error);
});
}
// 일정 항목 클릭 이벤트
document.addEventListener("DOMContentLoaded", function () {
document.addEventListener('click', function(e) {
if (e.target.closest('.schedule-item')) {
e.preventDefault();
const scheduleItem = e.target.closest('.schedule-item');
const scheduleId = scheduleItem.getAttribute("data-id");
openModal(scheduleId);
}
});
});
</script>