feat: 신규 페이지 구현 및 HR/설정 기능 개선

신규 페이지:
- 회계관리: 거래처, 예상비용, 청구서, 발주서
- 게시판: 공지사항, 자료실, 커뮤니티
- 고객센터: 문의/FAQ
- 설정: 계정, 알림, 출퇴근, 팝업, 구독, 결제내역
- 리포트 (차트 시각화)
- 개발자 테스트 URL 페이지

기능 개선:
- HR 직원관리/휴가관리/카드관리 강화
- IntegratedListTemplateV2 확장
- AuthenticatedLayout 패딩 표준화
- 로그인 페이지 UI 개선

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
byeongcheolryu
2025-12-19 19:12:34 +09:00
parent d742c0ce26
commit c6b605200d
213 changed files with 32644 additions and 775 deletions

View File

@@ -0,0 +1,206 @@
# 모바일 출퇴근 시스템 구현 체크리스트
> Last Updated: 2025-12-18
## 개요
- **목적**: 모바일 기기에서 GPS 기반 출퇴근 기록
- **대상**: 특정 사용자 (하드코딩)
- **조건**: 지정된 현장 좌표 100m 반경 내에서만 출퇴근 가능
## 기술 스택
- **지도 API**: Google Maps JavaScript API (카카오맵에서 변경)
- **API 키**: `.env.local``NEXT_PUBLIC_GOOGLE_MAPS_API_KEY` 저장
- **현장 좌표**: `37.557358, 126.864414` (본사)
- **반경**: 100m
---
## Phase 1: 환경 설정 ✅
- [x] Google Maps API 키 .env.local에 추가
- [x] @types/google.maps 패키지 설치
## Phase 2: 페이지 구조 ✅
- [x] `/hr/attendance` 라우트 생성 (기존 protected 레이아웃 활용)
- [x] 모바일 전용 레이아웃 (AuthenticatedLayout 모바일 모드 활용)
- [x] 페이지 컴포넌트 기본 구조
## Phase 3: 지도 컴포넌트 ✅
- [x] GoogleMap 컴포넌트 생성 (`src/components/attendance/GoogleMap.tsx`)
- [x] 현장 좌표에 100m 파란 원(Circle) 표시
- [x] 현재 위치 마커 표시 (빨간색)
- [x] GPS watchPosition으로 실시간 위치 추적
- [x] 개발 환경 GPS 시뮬레이션 (localhost에서 본사 근처 50m로 자동 설정)
## Phase 4: 출퇴근 로직 ✅
- [x] GPS 거리 계산 함수 (Haversine formula)
- [x] 100m 반경 체크 → 버튼 활성화/비활성화
- [x] 출근 상태 관리 (출근전/출근중/퇴근완료)
- [x] 현재 시간 실시간 표시
## Phase 5: 완료 화면 ✅
- [x] 출근 완료 화면 구현 (`src/components/attendance/AttendanceComplete.tsx`)
- [x] ✓ 체크 아이콘
- [x] "출근 완료" 텍스트 (빨간색)
- [x] 시간 표시 (HH:MM:SS)
- [x] 날짜 표시 (YYYY년 MM월 DD일 요일)
- [x] 위치 표시 (본사)
- [x] 확인 버튼
- [x] 퇴근 완료 화면 구현 (동일 컴포넌트 재사용)
## Phase 6: 모바일 감지 & 리다이렉트 ⏳
- [ ] User-Agent 기반 모바일 감지
- [ ] 특정 사용자 하드코딩 체크
- [ ] 로그인 후 자동 리다이렉트 로직
- [ ] 별도 모바일 레이아웃 (헤더/사이드바 제거)
- [ ] 웹에서 접근 차단 (모바일 전용)
## Phase 7: API 연동 ⏳
- [ ] 출퇴근 기록 API 설계
- [ ] 출근 API (`POST /api/attendance/check-in`)
- [ ] 퇴근 API (`POST /api/attendance/check-out`)
- [ ] 오늘 출퇴근 상태 조회 API (`GET /api/attendance/today`)
- [ ] 현장 좌표 API에서 가져오기 (하드코딩 제거)
## Phase 8: 사용자 정보 연동 ⏳
- [ ] 로그인 사용자 정보 연동 (TEST_USER 제거)
- [ ] 출퇴근 가능 사용자 권한 체크
- [ ] 현장별 사용자 배정 로직
---
## 생성된 파일
| 파일 | 설명 |
|------|------|
| `src/components/attendance/GoogleMap.tsx` | Google Maps 컴포넌트 (원, 마커, GPS 추적) |
| `src/components/attendance/AttendanceComplete.tsx` | 출퇴근 완료 화면 |
| `src/app/[locale]/(protected)/hr/attendance/page.tsx` | 출퇴근 메인 페이지 |
---
## 테스트 URL
```
http://localhost:3000/ko/hr/attendance
```
모바일 테스트: Chrome DevTools → Toggle Device Toolbar (Ctrl+Shift+M)
---
## 하드코딩 설정값 (추후 API로 대체 필요)
```typescript
// 현장 좌표 (본사) - page.tsx:12-17
const SITE_LOCATION = {
name: '본사',
lat: 37.557358,
lng: 126.864414,
radius: 100, // meters
};
// 테스트용 사용자 정보 - page.tsx:19-23
const TEST_USER = {
name: '홍길동',
department: '부서명',
position: '직급명',
};
```
---
## 개발 중 해결한 이슈
### 1. Hydration 에러
- **원인**: 서버/클라이언트 HTML 불일치 (Date, localStorage 등)
- **해결**: `mounted` 상태 체크 + `suppressHydrationWarning` 속성
### 2. Google Maps API 중복 로드
- **원인**: React 컴포넌트 리렌더링 시 스크립트 중복 추가
- **해결**: `window.googleMapsLoading` 플래그 + 기존 스크립트 체크
### 3. GPS 권한 거부 (localhost)
- **원인**: HTTPS가 아닌 환경에서 GPS 권한 제한
- **해결**: 개발 환경 감지 후 테스트 좌표로 시뮬레이션
```typescript
const isDevelopment =
hostname === 'localhost' ||
hostname === '127.0.0.1' ||
hostname.startsWith('192.168.') ||
process.env.NODE_ENV === 'development';
```
---
## UI 스펙 (스크린샷 기반)
### 출퇴근 메인 화면
```
┌─────────────────────────────┐
│ < 🏠 ⚙️⚙️⚙️ ☰ │ ← 헤더 (AuthenticatedLayout)
├─────────────────────────────┤
│ 출퇴근하기 │ ← 타이틀
├─────────────────────────────┤
│ │
│ ┌───────────────────┐ │
│ │ │ │
│ │ 🔵 (100m 원) │ │ ← Google Maps
│ │ 📍 │ │
│ │ │ │
│ └───────────────────┘ │
│ │
├─────────────────────────────┤
│ 👤 홍길동 │
│ 부서명 직급명 │
│ │
│ 08:43:15 (빨간색) │ ← 실시간 시간
├─────────────────────────────┤
│ [ 출근하기 ] [ 퇴근하기 ]│ ← 버튼
└─────────────────────────────┘
```
### 완료 화면
```
┌─────────────────────────────┐
│ < 🏠 ⚙️⚙️⚙️ ☰ │
├─────────────────────────────┤
│ 출근하기 │
├─────────────────────────────┤
│ │
│ ✓ │ ← 체크 아이콘 (원형)
│ │
│ 출근 완료 │ ← 빨간색
│ 08:43:15 │
│ │
│ 2025년 12월 15일 (월) │
│ │
│ 📍 본사 │
│ │
├─────────────────────────────┤
│ [ 확인 ] │
└─────────────────────────────┘
```
---
## 다음 작업 TODO
1. **Phase 6 진행**: 모바일 전용 레이아웃 + User-Agent 감지
2. **API 설계**: 백엔드 팀과 출퇴근 API 협의
3. **테스트**: 실제 모바일 기기에서 GPS 테스트 (HTTPS 환경)
---
## 참고 사항
- MVP 버전: API 연동 없이 하드코딩으로 동작 확인 (현재 상태)
- 추후 개선: 출퇴근 기록 API, 현장 좌표 DB 저장, 사용자 권한 체크
- Phase 6 (모바일 감지 & 리다이렉트)는 MVP 테스트 후 진행

View File

@@ -0,0 +1,86 @@
# [IMPL-2025-12-19] 카드관리 기능 구현
## 개요
- 위치: 기준정보 > 카드관리
- 경로: `/hr/card-management`
## 구현 체크리스트
### 1. Types 정의
- [x] `types.ts` - Card 타입, 상태, 카드사 옵션 정의
### 2. 컴포넌트 구현
- [x] `src/components/hr/CardManagement/index.tsx` - 리스트 컴포넌트 (IntegratedListTemplateV2 사용)
- [x] `src/components/hr/CardManagement/CardDetail.tsx` - 상세 컴포넌트
- [x] `src/components/hr/CardManagement/CardForm.tsx` - 등록/수정 폼 컴포넌트
- [x] `src/components/hr/CardManagement/types.ts` - 타입 정의
### 3. 페이지 라우팅
- [x] `src/app/[locale]/(protected)/hr/card-management/page.tsx` - 리스트 페이지
- [x] `src/app/[locale]/(protected)/hr/card-management/[id]/page.tsx` - 상세 페이지
- [x] `src/app/[locale]/(protected)/hr/card-management/[id]/edit/page.tsx` - 수정 페이지
- [x] `src/app/[locale]/(protected)/hr/card-management/new/page.tsx` - 등록 페이지
### 4. 문서 업데이트
- [x] `claudedocs/[REF] all-pages-test-urls.md` 업데이트
## 스크린샷 기반 필드 정의
### 리스트 테이블 컬럼
| 컬럼 | 설명 |
|------|------|
| No. | 번호 |
| 카드사 | 카드사 이름 |
| 카드번호 | 1234-****-****-1234 형식 |
| 카드명 | 카드 명칭 |
| 상태 | 사용/정지 |
| 부서 | 사용자 부서 |
| 사용자 | 사용자 이름 |
| 직책 | 사용자 직책 |
| 작업 | 선택 시 수정/삭제 버튼 |
### 상세 페이지 필드
#### 기본 정보
| 필드 | 타입 | 설명 |
|------|------|------|
| 카드사 | Select | 카드사 선택 |
| 카드번호 | Input | 1234-1234-1234-1234 |
| 유효기간 | Input | MMYY 형식 |
| 카드 비밀번호 앞 2자리 | Input | ** |
| 카드명 | Input | 카드 명칭 |
| 상태 | Select | 사용/정지 |
#### 사용자 정보
| 필드 | 타입 | 설명 |
|------|------|------|
| 부서/이름/직책 | Select | 사용자 선택 셀렉트박스 |
## 진행 상황
- 시작일: 2025-12-19
- 완료일: 2025-12-19
- 현재 상태: 완료
## 생성된 파일 목록
```
src/components/hr/CardManagement/
├── types.ts # 카드 타입 정의
├── index.tsx # 리스트 컴포넌트
├── CardDetail.tsx # 상세 컴포넌트
└── CardForm.tsx # 등록/수정 폼 컴포넌트
src/app/[locale]/(protected)/hr/card-management/
├── page.tsx # 리스트 페이지
├── new/
│ └── page.tsx # 등록 페이지
└── [id]/
├── page.tsx # 상세 페이지
└── edit/
└── page.tsx # 수정 페이지
```
## 테스트 URL
- 리스트: http://localhost:3000/ko/hr/card-management
- 등록: http://localhost:3000/ko/hr/card-management/new
- 상세: http://localhost:3000/ko/hr/card-management/1
- 수정: http://localhost:3000/ko/hr/card-management/1/edit