diff --git a/backend/__pycache__/main.cpython-311.pyc b/backend/__pycache__/main.cpython-311.pyc index 2c02d95..8c6c584 100644 Binary files a/backend/__pycache__/main.cpython-311.pyc and b/backend/__pycache__/main.cpython-311.pyc differ diff --git a/backend/database/__pycache__/database.cpython-311.pyc b/backend/database/__pycache__/database.cpython-311.pyc index 44c2a05..8e59265 100644 Binary files a/backend/database/__pycache__/database.cpython-311.pyc and b/backend/database/__pycache__/database.cpython-311.pyc differ diff --git a/backend/database/__pycache__/models.cpython-311.pyc b/backend/database/__pycache__/models.cpython-311.pyc index 43ad793..b9bb198 100644 Binary files a/backend/database/__pycache__/models.cpython-311.pyc and b/backend/database/__pycache__/models.cpython-311.pyc differ diff --git a/backend/database/__pycache__/schemas.cpython-311.pyc b/backend/database/__pycache__/schemas.cpython-311.pyc index 9a2735c..34df5b7 100644 Binary files a/backend/database/__pycache__/schemas.cpython-311.pyc and b/backend/database/__pycache__/schemas.cpython-311.pyc differ diff --git a/backend/routers/__pycache__/auth.cpython-311.pyc b/backend/routers/__pycache__/auth.cpython-311.pyc index 77a4f57..dcd7677 100644 Binary files a/backend/routers/__pycache__/auth.cpython-311.pyc and b/backend/routers/__pycache__/auth.cpython-311.pyc differ diff --git a/backend/routers/__pycache__/daily_work.cpython-311.pyc b/backend/routers/__pycache__/daily_work.cpython-311.pyc index 1963909..2b3e23f 100644 Binary files a/backend/routers/__pycache__/daily_work.cpython-311.pyc and b/backend/routers/__pycache__/daily_work.cpython-311.pyc differ diff --git a/backend/routers/__pycache__/inbox.cpython-311.pyc b/backend/routers/__pycache__/inbox.cpython-311.pyc new file mode 100644 index 0000000..e53ad54 Binary files /dev/null and b/backend/routers/__pycache__/inbox.cpython-311.pyc differ diff --git a/backend/routers/__pycache__/issues.cpython-311.pyc b/backend/routers/__pycache__/issues.cpython-311.pyc index c22b607..34d6e8c 100644 Binary files a/backend/routers/__pycache__/issues.cpython-311.pyc and b/backend/routers/__pycache__/issues.cpython-311.pyc differ diff --git a/backend/routers/__pycache__/page_permissions.cpython-311.pyc b/backend/routers/__pycache__/page_permissions.cpython-311.pyc new file mode 100644 index 0000000..b80eeae Binary files /dev/null and b/backend/routers/__pycache__/page_permissions.cpython-311.pyc differ diff --git a/backend/routers/__pycache__/projects.cpython-311.pyc b/backend/routers/__pycache__/projects.cpython-311.pyc index 9cdddd0..94c4787 100644 Binary files a/backend/routers/__pycache__/projects.cpython-311.pyc and b/backend/routers/__pycache__/projects.cpython-311.pyc differ diff --git a/backend/routers/__pycache__/reports.cpython-311.pyc b/backend/routers/__pycache__/reports.cpython-311.pyc index 7f4fee9..9303efd 100644 Binary files a/backend/routers/__pycache__/reports.cpython-311.pyc and b/backend/routers/__pycache__/reports.cpython-311.pyc differ diff --git a/backend/services/__pycache__/auth_service.cpython-311.pyc b/backend/services/__pycache__/auth_service.cpython-311.pyc index fa1fa55..0e0ad90 100644 Binary files a/backend/services/__pycache__/auth_service.cpython-311.pyc and b/backend/services/__pycache__/auth_service.cpython-311.pyc differ diff --git a/backend/services/__pycache__/file_service.cpython-311.pyc b/backend/services/__pycache__/file_service.cpython-311.pyc index 38557d6..e9ed27c 100644 Binary files a/backend/services/__pycache__/file_service.cpython-311.pyc and b/backend/services/__pycache__/file_service.cpython-311.pyc differ diff --git a/frontend/admin.html b/frontend/admin.html index a5af5f2..35efd10 100644 --- a/frontend/admin.html +++ b/frontend/admin.html @@ -56,13 +56,50 @@ border-color: #60a5fa; box-shadow: 0 0 0 3px rgba(96, 165, 250, 0.1); } + + /* 부드러운 페이드인 애니메이션 */ + .fade-in { + opacity: 0; + transform: translateY(20px); + transition: opacity 0.6s ease-out, transform 0.6s ease-out; + } + + .fade-in.visible { + opacity: 1; + transform: translateY(0); + } + + /* 헤더 전용 빠른 페이드인 */ + .header-fade-in { + opacity: 0; + transform: translateY(-10px); + transition: opacity 0.4s ease-out, transform 0.4s ease-out; + } + + .header-fade-in.visible { + opacity: 1; + transform: translateY(0); + } + + /* 본문 컨텐츠 지연 페이드인 */ + .content-fade-in { + opacity: 0; + transform: translateY(30px); + transition: opacity 0.8s ease-out, transform 0.8s ease-out; + transition-delay: 0.2s; + } + + .content-fade-in.visible { + opacity: 1; + transform: translateY(0); + } -
+
@@ -228,6 +265,46 @@ let currentUser = null; let users = []; + // 애니메이션 함수들 + function animateHeaderAppearance() { + console.log('🎨 헤더 애니메이션 시작'); + + // 헤더 요소 찾기 (공통 헤더가 생성한 요소) + const headerElement = document.querySelector('header') || document.querySelector('[class*="header"]') || document.querySelector('nav'); + + if (headerElement) { + headerElement.classList.add('header-fade-in'); + setTimeout(() => { + headerElement.classList.add('visible'); + console.log('✨ 헤더 페이드인 완료'); + + // 헤더 애니메이션 완료 후 본문 애니메이션 + setTimeout(() => { + animateContentAppearance(); + }, 200); + }, 50); + } else { + // 헤더를 찾지 못했으면 바로 본문 애니메이션 + console.log('⚠️ 헤더 요소를 찾지 못함 - 본문 애니메이션 시작'); + animateContentAppearance(); + } + } + + // 본문 컨텐츠 애니메이션 + function animateContentAppearance() { + console.log('🎨 본문 컨텐츠 애니메이션 시작'); + + // 모든 content-fade-in 요소들을 순차적으로 애니메이션 + const contentElements = document.querySelectorAll('.content-fade-in'); + + contentElements.forEach((element, index) => { + setTimeout(() => { + element.classList.add('visible'); + console.log(`✨ 컨텐츠 ${index + 1} 페이드인 완료`); + }, index * 100); // 100ms씩 지연 + }); + } + // API 로드 후 초기화 함수 async function initializeAdmin() { const token = localStorage.getItem('access_token'); @@ -244,6 +321,11 @@ // 공통 헤더 초기화 await window.commonHeader.init(user, 'users_manage'); + // 헤더 초기화 후 부드러운 애니메이션 시작 + setTimeout(() => { + animateHeaderAppearance(); + }, 100); + // 페이지 접근 권한 체크 setTimeout(() => { if (!canAccessPage('users_manage')) { diff --git a/frontend/daily-work.html b/frontend/daily-work.html index 197930a..c99b2d0 100644 --- a/frontend/daily-work.html +++ b/frontend/daily-work.html @@ -89,6 +89,43 @@ background-color: #3b82f6; color: white; } + + /* 부드러운 페이드인 애니메이션 */ + .fade-in { + opacity: 0; + transform: translateY(20px); + transition: opacity 0.6s ease-out, transform 0.6s ease-out; + } + + .fade-in.visible { + opacity: 1; + transform: translateY(0); + } + + /* 헤더 전용 빠른 페이드인 */ + .header-fade-in { + opacity: 0; + transform: translateY(-10px); + transition: opacity 0.4s ease-out, transform 0.4s ease-out; + } + + .header-fade-in.visible { + opacity: 1; + transform: translateY(0); + } + + /* 본문 컨텐츠 지연 페이드인 */ + .content-fade-in { + opacity: 0; + transform: translateY(30px); + transition: opacity 0.8s ease-out, transform 0.8s ease-out; + transition-delay: 0.2s; + } + + .content-fade-in.visible { + opacity: 1; + transform: translateY(0); + } @@ -96,7 +133,7 @@ -
+

@@ -195,6 +232,46 @@ let dailyWorkData = []; let projectEntryCounter = 0; + // 애니메이션 함수들 + function animateHeaderAppearance() { + console.log('🎨 헤더 애니메이션 시작'); + + // 헤더 요소 찾기 (공통 헤더가 생성한 요소) + const headerElement = document.querySelector('header') || document.querySelector('[class*="header"]') || document.querySelector('nav'); + + if (headerElement) { + headerElement.classList.add('header-fade-in'); + setTimeout(() => { + headerElement.classList.add('visible'); + console.log('✨ 헤더 페이드인 완료'); + + // 헤더 애니메이션 완료 후 본문 애니메이션 + setTimeout(() => { + animateContentAppearance(); + }, 200); + }, 50); + } else { + // 헤더를 찾지 못했으면 바로 본문 애니메이션 + console.log('⚠️ 헤더 요소를 찾지 못함 - 본문 애니메이션 시작'); + animateContentAppearance(); + } + } + + // 본문 컨텐츠 애니메이션 + function animateContentAppearance() { + console.log('🎨 본문 컨텐츠 애니메이션 시작'); + + // 모든 content-fade-in 요소들을 순차적으로 애니메이션 + const contentElements = document.querySelectorAll('.content-fade-in'); + + contentElements.forEach((element, index) => { + setTimeout(() => { + element.classList.add('visible'); + console.log(`✨ 컨텐츠 ${index + 1} 페이드인 완료`); + }, index * 100); // 100ms씩 지연 + }); + } + // API 로드 후 초기화 함수 async function initializeDailyWork() { const token = localStorage.getItem('access_token'); @@ -211,6 +288,11 @@ // 공통 헤더 초기화 await window.commonHeader.init(user, 'daily_work'); + // 헤더 초기화 후 부드러운 애니메이션 시작 + setTimeout(() => { + animateHeaderAppearance(); + }, 100); + // 페이지 접근 권한 체크 (일일 공수 페이지) setTimeout(() => { if (!canAccessPage('daily_work')) { diff --git a/frontend/issue-view.html b/frontend/issue-view.html index 8749722..22ddc27 100644 --- a/frontend/issue-view.html +++ b/frontend/issue-view.html @@ -66,13 +66,50 @@ background-color: #3b82f6; color: white; } + + /* 부드러운 페이드인 애니메이션 */ + .fade-in { + opacity: 0; + transform: translateY(20px); + transition: opacity 0.6s ease-out, transform 0.6s ease-out; + } + + .fade-in.visible { + opacity: 1; + transform: translateY(0); + } + + /* 헤더 전용 빠른 페이드인 */ + .header-fade-in { + opacity: 0; + transform: translateY(-10px); + transition: opacity 0.4s ease-out, transform 0.4s ease-out; + } + + .header-fade-in.visible { + opacity: 1; + transform: translateY(0); + } + + /* 본문 컨텐츠 지연 페이드인 */ + .content-fade-in { + opacity: 0; + transform: translateY(30px); + transition: opacity 0.8s ease-out, transform 0.8s ease-out; + transition-delay: 0.2s; + } + + .content-fade-in.visible { + opacity: 1; + transform: translateY(0); + } -
+
@@ -162,6 +199,46 @@ let selectedStartDate = null; let selectedEndDate = null; + // 애니메이션 함수들 + function animateHeaderAppearance() { + console.log('🎨 헤더 애니메이션 시작'); + + // 헤더 요소 찾기 (공통 헤더가 생성한 요소) + const headerElement = document.querySelector('header') || document.querySelector('[class*="header"]') || document.querySelector('nav'); + + if (headerElement) { + headerElement.classList.add('header-fade-in'); + setTimeout(() => { + headerElement.classList.add('visible'); + console.log('✨ 헤더 페이드인 완료'); + + // 헤더 애니메이션 완료 후 본문 애니메이션 + setTimeout(() => { + animateContentAppearance(); + }, 200); + }, 50); + } else { + // 헤더를 찾지 못했으면 바로 본문 애니메이션 + console.log('⚠️ 헤더 요소를 찾지 못함 - 본문 애니메이션 시작'); + animateContentAppearance(); + } + } + + // 본문 컨텐츠 애니메이션 + function animateContentAppearance() { + console.log('🎨 본문 컨텐츠 애니메이션 시작'); + + // 모든 content-fade-in 요소들을 순차적으로 애니메이션 + const contentElements = document.querySelectorAll('.content-fade-in'); + + contentElements.forEach((element, index) => { + setTimeout(() => { + element.classList.add('visible'); + console.log(`✨ 컨텐츠 ${index + 1} 페이드인 완료`); + }, index * 100); // 100ms씩 지연 + }); + } + // API 로드 후 초기화 함수 async function initializeIssueView() { const token = localStorage.getItem('access_token'); @@ -178,6 +255,11 @@ // 공통 헤더 초기화 await window.commonHeader.init(user, 'issues_view'); + // 헤더 초기화 후 부드러운 애니메이션 시작 + setTimeout(() => { + animateHeaderAppearance(); + }, 100); + // 사용자 역할에 따른 페이지 제목 설정 updatePageTitle(user); diff --git a/frontend/issues-inbox.html b/frontend/issues-inbox.html index 111c2bc..8d7039d 100644 --- a/frontend/issues-inbox.html +++ b/frontend/issues-inbox.html @@ -74,6 +74,43 @@ .badge-new { background: #dbeafe; color: #1e40af; } .badge-processing { background: #fef3c7; color: #92400e; } .badge-completed { background: #d1fae5; color: #065f46; } + + /* 부드러운 페이드인 애니메이션 */ + .fade-in { + opacity: 0; + transform: translateY(20px); + transition: opacity 0.6s ease-out, transform 0.6s ease-out; + } + + .fade-in.visible { + opacity: 1; + transform: translateY(0); + } + + /* 헤더 전용 빠른 페이드인 */ + .header-fade-in { + opacity: 0; + transform: translateY(-10px); + transition: opacity 0.4s ease-out, transform 0.4s ease-out; + } + + .header-fade-in.visible { + opacity: 1; + transform: translateY(0); + } + + /* 본문 컨텐츠 지연 페이드인 */ + .content-fade-in { + opacity: 0; + transform: translateY(30px); + transition: opacity 0.8s ease-out, transform 0.8s ease-out; + transition-delay: 0.2s; + } + + .content-fade-in.visible { + opacity: 1; + transform: translateY(0); + } @@ -88,7 +125,7 @@ -
+
@@ -384,6 +421,46 @@ let filteredIssues = []; let readStatus = new Set(); // 읽은 부적합 ID 저장 + // 애니메이션 함수들 + function animateHeaderAppearance() { + console.log('🎨 헤더 애니메이션 시작'); + + // 헤더 요소 찾기 (공통 헤더가 생성한 요소) + const headerElement = document.querySelector('header') || document.querySelector('[class*="header"]') || document.querySelector('nav'); + + if (headerElement) { + headerElement.classList.add('header-fade-in'); + setTimeout(() => { + headerElement.classList.add('visible'); + console.log('✨ 헤더 페이드인 완료'); + + // 헤더 애니메이션 완료 후 본문 애니메이션 + setTimeout(() => { + animateContentAppearance(); + }, 200); + }, 50); + } else { + // 헤더를 찾지 못했으면 바로 본문 애니메이션 + console.log('⚠️ 헤더 요소를 찾지 못함 - 본문 애니메이션 시작'); + animateContentAppearance(); + } + } + + // 본문 컨텐츠 애니메이션 + function animateContentAppearance() { + console.log('🎨 본문 컨텐츠 애니메이션 시작'); + + // 모든 content-fade-in 요소들을 순차적으로 애니메이션 + const contentElements = document.querySelectorAll('.content-fade-in'); + + contentElements.forEach((element, index) => { + setTimeout(() => { + element.classList.add('visible'); + console.log(`✨ 컨텐츠 ${index + 1} 페이드인 완료`); + }, index * 100); // 100ms씩 지연 + }); + } + // API 로드 후 초기화 함수 async function initializeInbox() { console.log('🚀 수신함 초기화 시작'); @@ -406,6 +483,11 @@ // 공통 헤더 초기화 await window.commonHeader.init(user, 'issues_inbox'); + + // 헤더 초기화 후 부드러운 애니메이션 시작 + setTimeout(() => { + animateHeaderAppearance(); + }, 100); // 페이지 접근 권한 체크 setTimeout(() => { @@ -454,6 +536,10 @@ const user = JSON.parse(localStorage.getItem('currentUser') || '{}'); if (user.id) { await window.commonHeader.init(user, 'issues_inbox'); + // 에러 상황에서도 애니메이션 적용 + setTimeout(() => { + animateHeaderAppearance(); + }, 100); } } catch (headerError) { console.error('공통 헤더 초기화 실패:', headerError); diff --git a/frontend/project-management.html b/frontend/project-management.html index 1b591f5..ec80fab 100644 --- a/frontend/project-management.html +++ b/frontend/project-management.html @@ -46,13 +46,50 @@ outline: none; box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); } + + /* 부드러운 페이드인 애니메이션 */ + .fade-in { + opacity: 0; + transform: translateY(20px); + transition: opacity 0.6s ease-out, transform 0.6s ease-out; + } + + .fade-in.visible { + opacity: 1; + transform: translateY(0); + } + + /* 헤더 전용 빠른 페이드인 */ + .header-fade-in { + opacity: 0; + transform: translateY(-10px); + transition: opacity 0.4s ease-out, transform 0.4s ease-out; + } + + .header-fade-in.visible { + opacity: 1; + transform: translateY(0); + } + + /* 본문 컨텐츠 지연 페이드인 */ + .content-fade-in { + opacity: 0; + transform: translateY(30px); + transition: opacity 0.8s ease-out, transform 0.8s ease-out; + transition-delay: 0.2s; + } + + .content-fade-in.visible { + opacity: 1; + transform: translateY(0); + } -
+

@@ -169,6 +206,46 @@ // 사용자 확인 (관리자만 접근 가능) let currentUser = null; + // 애니메이션 함수들 + function animateHeaderAppearance() { + console.log('🎨 헤더 애니메이션 시작'); + + // 헤더 요소 찾기 (공통 헤더가 생성한 요소) + const headerElement = document.querySelector('header') || document.querySelector('[class*="header"]') || document.querySelector('nav'); + + if (headerElement) { + headerElement.classList.add('header-fade-in'); + setTimeout(() => { + headerElement.classList.add('visible'); + console.log('✨ 헤더 페이드인 완료'); + + // 헤더 애니메이션 완료 후 본문 애니메이션 + setTimeout(() => { + animateContentAppearance(); + }, 200); + }, 50); + } else { + // 헤더를 찾지 못했으면 바로 본문 애니메이션 + console.log('⚠️ 헤더 요소를 찾지 못함 - 본문 애니메이션 시작'); + animateContentAppearance(); + } + } + + // 본문 컨텐츠 애니메이션 + function animateContentAppearance() { + console.log('🎨 본문 컨텐츠 애니메이션 시작'); + + // 모든 content-fade-in 요소들을 순차적으로 애니메이션 + const contentElements = document.querySelectorAll('.content-fade-in'); + + contentElements.forEach((element, index) => { + setTimeout(() => { + element.classList.add('visible'); + console.log(`✨ 컨텐츠 ${index + 1} 페이드인 완료`); + }, index * 100); // 100ms씩 지연 + }); + } + async function initAuth() { console.log('인증 초기화 시작'); const token = localStorage.getItem('access_token'); @@ -205,6 +282,11 @@ // 공통 헤더 초기화 await window.commonHeader.init(currentUser, 'projects_manage'); + // 헤더 초기화 후 부드러운 애니메이션 시작 + setTimeout(() => { + animateHeaderAppearance(); + }, 100); + // 페이지 접근 권한 체크 (프로젝트 관리 페이지) setTimeout(() => { if (!canAccessPage('projects_manage')) {