prepare(" SELECT name, rank_name, join_date, sys_comp_code FROM edu_users WHERE member_id = ? AND sys_comp_code = ? LIMIT 1 "); $stmtUser->execute([$memberId, $sysCompCode]); $userRow = $stmtUser->fetch() ?: []; $userName = $userRow['name'] ?? '사용자'; $userRank = $userRow['rank_name'] ?? ''; $sysCompCode = (string)($userRow['sys_comp_code'] ?? $sysCompCode); // join_date 기준 14일 마감 계산 $today = new DateTime(date('Y-m-d')); try { $joinBase = !empty($userRow['join_date']) ? new DateTime(date('Y-m-d', strtotime($userRow['join_date']))) : clone $today; } catch (Exception $e) { $joinBase = clone $today; } $deadline = (clone $joinBase)->modify('+14 days'); $dDay = ($today <= $deadline) ? (int)$today->diff($deadline)->days : 0; $deadlineStr = $deadline->format('n월 j일'); ?>

님, 0?'입사를 환영합니다.':''?>

0?'D-'.$dDay:'' ?>0?'('.htmlspecialchars($deadlineStr, ENT_QUOTES, 'UTF-8').')':'' ?>0?'까지':''?> 필수 콘텐츠 시청을 완료해주세요.

query("SHOW TABLES LIKE 'edu_content_histories'"); if ($checkTable->rowCount() === 0) { $useContentHistories = false; } } catch (Exception $e) { $useContentHistories = false; } if ($useContentHistories) { try { $stmt = $pdo->prepare(" SELECT c.*, COALESCE(lh.watch_tm, 0) AS watch_tm, COALESCE(lh.content_tm, 0) AS content_tm, lh.completed_at AS lh_completed_at, CASE WHEN ch.content_id IS NULL THEN 'none' WHEN ch.completed_at IS NOT NULL THEN 'completed' ELSE 'in_progress' END AS learning_status FROM edu_contents c LEFT JOIN edu_learning_histories lh ON lh.content_id = c.content_id AND lh.member_id = ? AND lh.sys_comp_code = ? LEFT JOIN edu_content_histories ch ON ch.content_id = c.content_id AND ch.member_id = ? AND ch.sys_comp_code = ? WHERE c.category_group IN ($placeholders) ORDER BY FIELD(c.category_group, 'CA200O01','CA200O02','CA200O03','CA200O04','CA200O05','CA200O06','CA200O07','CA200O08','CA200O09','CA200O10'), COALESCE(NULLIF(c.sort_order, 0), 9999), c.content_id "); $stmt->execute(array_merge([$memberId, $sysCompCode, $memberId, $sysCompCode], $onboardingGroups)); $rows = $stmt->fetchAll(); } catch (Exception $e) { // edu_content_histories JOIN 실패 시 fallback $useContentHistories = false; } } if (!$useContentHistories) { // fallback: edu_learning_histories만 사용 $stmt = $pdo->prepare(" SELECT c.*, COALESCE(lh.watch_tm, 0) AS watch_tm, COALESCE(lh.content_tm, 0) AS content_tm, lh.completed_at AS lh_completed_at, CASE WHEN lh.content_id IS NULL THEN 'none' WHEN lh.completed_at IS NOT NULL THEN 'completed' ELSE 'in_progress' END AS learning_status FROM edu_contents c LEFT JOIN edu_learning_histories lh ON lh.content_id = c.content_id AND lh.member_id = ? AND lh.sys_comp_code = ? WHERE c.category_group IN ($placeholders) ORDER BY FIELD(c.category_group, 'CA200O01','CA200O02','CA200O03','CA200O04','CA200O05','CA200O06','CA200O07','CA200O08','CA200O09','CA200O10'), COALESCE(NULLIF(c.sort_order, 0), 9999), c.content_id "); $stmt->execute(array_merge([$memberId, $sysCompCode], $onboardingGroups)); $rows = $stmt->fetchAll(); } // 2. category_group -> 퍼즐 피스/영역 매핑 // area: family(소개), hanmac(DX), value(가치), company(회사생활) $categoryMap = [ 'CA200O01' => ['pieceId' => 1, 'group' => 3, 'area' => 'value'], 'CA200O02' => ['pieceId' => 2, 'group' => 2, 'area' => 'hanmac'], 'CA200O03' => ['pieceId' => 3, 'group' => 2, 'area' => 'hanmac'], 'CA200O04' => ['pieceId' => 4, 'group' => 2, 'area' => 'hanmac'], 'CA200O05' => ['pieceId' => 5, 'group' => 2, 'area' => 'hanmac'], 'CA200O06' => ['pieceId' => 6, 'group' => 3, 'area' => 'value'], 'CA200O07' => ['pieceId' => 7, 'group' => 4, 'area' => 'company'], 'CA200O08' => ['pieceId' => 8, 'group' => 4, 'area' => 'company'], 'CA200O09' => ['pieceId' => 9, 'group' => 1, 'area' => 'family'], 'CA200O10' => ['pieceId' => 10, 'group' => 1, 'area' => 'family'], ]; // ✅ 온보딩 챕터 제목을 edu_codes 테이블에서 동적으로 로드 // 관리자가 edu_codes에서 code_name을 수정하면 자동으로 퍼즐 제목이 변경됨 $chapterNameMap = []; try { $stmtCodes = $pdo->prepare(" SELECT base_code, code_name FROM edu_codes WHERE group_code = 'CA200' AND base_code IN ('CA200O01','CA200O02','CA200O03','CA200O04','CA200O05','CA200O06','CA200O07','CA200O08','CA200O09','CA200O10') ORDER BY base_code "); $stmtCodes->execute(); $codeRows = $stmtCodes->fetchAll(); foreach ($codeRows as $codeRow) { $baseCode = (string)($codeRow['base_code'] ?? ''); $codeName = trim((string)($codeRow['code_name'] ?? '')); if ($baseCode && $codeName) { $chapterNameMap[$baseCode] = $codeName; } } } catch (Exception $e) { // 학습 부분은 진행되어야 하므로 조용히 실패 처리 error_log('[onboarding.php] edu_codes 조회 실패: ' . $e->getMessage()); } // 3. 같은 category_group은 같은 모달(챕터)로 묶고 lessons에 1/2/3차시 누적 $chapterMap = []; foreach ($rows as $idx => $row) { $categoryGroup = $row['category_group'] ?? ''; $mapped = $categoryMap[$categoryGroup] ?? null; // description 컬럼명 편차 대응 $description = trim((string)($row['description'] ?? $row['description1'] ?? $row['description_1'] ?? $row['content_desc'] ?? $row['content_desc1'] ?? $row['content_description'] ?? $row['content_description1'] ?? '')); $description2 = trim((string)($row['description2'] ?? $row['description_2'] ?? $row['content_desc2'] ?? $row['content_description2'] ?? '')); // 미정의 category_group은 뒤 순번으로 안전 처리 $pid = $mapped['pieceId'] ?? ($idx + 1); $group = $mapped['group'] ?? 1; $area = $mapped['area'] ?? 'family'; if (!isset($chapterMap[$categoryGroup])) { $chapterMap[$categoryGroup] = [ 'id' => 0, // 아래에서 순차 부여 // ✅ 챕터 제목은 고정된 chapterNameMap에서 가져옴 (콘텐츠 title이 아님) 'name' => $chapterNameMap[$categoryGroup] ?? str_replace('[온보딩] ', '', (string)$row['title']), 'pieceId' => $pid, 'type' => 'youtube', 'group' => $group, 'category_group' => $categoryGroup, 'area' => $area, 'lessons' => [], ]; } $lessonNo = (int)($row['sort_order'] ?? 0); if ($lessonNo <= 0) { $lessonNo = count($chapterMap[$categoryGroup]['lessons']) + 1; } // learning_status: none(미진행), in_progress(학습중), completed(학습완료) $learningStatus = $row['learning_status'] ?? 'none'; $chapterMap[$categoryGroup]['lessons'][] = [ 'content_id' => $row['content_id'], // 북마크/댓글은 edu_contents.content_id와 동일한 문자열 키를 사용한다. 'bookmark_content_id' => $row['content_id'], 'comment_content_id' => $row['content_id'], 'title' => $row['title'], 'label' => str_replace('[온보딩] ', '', $row['title']), 'description' => $description, 'description2' => $description2, 'url' => $row['content_url'], 'completed' => ($learningStatus === 'completed'), 'learning_status' => $learningStatus, 'watch_tm' => (int)$row['watch_tm'], 'content_tm' => (int)$row['content_tm'], ]; } // 4. 북마크 상태 로드 (is_active: 1=표시, 0=미표시) $bookmarkIds = []; foreach ($chapterMap as $chapterItem) { foreach (($chapterItem['lessons'] ?? []) as $lessonItem) { $bookmarkId = trim((string)($lessonItem['bookmark_content_id'] ?? '')); if ($bookmarkId !== '') { $bookmarkIds[] = $bookmarkId; } } } $bookmarkIds = array_values(array_unique($bookmarkIds)); $wishlistMap = []; if (!empty($bookmarkIds)) { $wishlistPlaceholders = implode(',', array_fill(0, count($bookmarkIds), '?')); $stmtWishlist = $pdo->prepare( "SELECT content_id, is_active FROM edu_content_wishlist WHERE member_id = ? AND sys_comp_code = ? AND content_id IN ($wishlistPlaceholders)" ); $stmtWishlist->execute(array_merge([$memberId, $sysCompCode], $bookmarkIds)); $wishlistRows = $stmtWishlist->fetchAll(); foreach ($wishlistRows as $wishlistRow) { $wishlistMap[(string)$wishlistRow['content_id']] = ((string)($wishlistRow['is_active'] ?? '0') === '1'); } } foreach ($chapterMap as &$chapterItem) { foreach ($chapterItem['lessons'] as &$lessonItem) { $bookmarkId = trim((string)($lessonItem['bookmark_content_id'] ?? '')); $lessonItem['is_bookmarked'] = ($bookmarkId !== '' && !empty($wishlistMap[$bookmarkId])); } unset($lessonItem); } unset($chapterItem); // category_group 정의 순서대로 챕터 정렬 + id 재부여 $puzzleData = []; foreach ($onboardingGroups as $code) { if (!isset($chapterMap[$code])) { continue; } $chapterMap[$code]['id'] = count($puzzleData) + 1; $puzzleData[] = $chapterMap[$code]; } $puzzleJson = json_encode($puzzleData, JSON_UNESCAPED_UNICODE); ?>