feat: 전사 공유 일정(주간 캘린더) 기능 추가
상단 nav 독립 메뉴 '일정' — 주간 타임라인(간트형) 캘린더. 카테고리=레인, 일정=막대(다중일 지원), 우측 상세 패널, 일정/카테고리 CRUD. 백엔드(Schedule 모듈): - ScheduleCategory/ScheduleEvent 엔티티 + 참석자(다대다) + 작성자 - 카테고리/일정 CRUD, 기간 겹침 조회, 참석자 풀(전사 사용자) - 기본 카테고리 12종 onModuleInit 멱등 시드 - 인증 사용자 누구나 관리(전역 일정, 글로벌 관리자 개념 없음) - 운영 마이그레이션(AddSchedule) 추가, @nestjs/schedule 임포트는 CronModule 로 alias 프론트: - /schedule 라우트 + 사이드바 nav 항목 - 주간 네비(이전/다음/오늘), 유형 필터·카테고리 관리 드롭다운 - 타임라인/상세 패널/일정 모달/카테고리 모달(hue 슬라이더)/참석자 멀티셀렉트 - schedule.store + useSchedule + scheduleDate 유틸 런타임 검증: dev 부팅·시드(12건)·라우트 매핑 정상, 인증 게이트(401), 일정 생성/조회/수정/삭제 + 참석자/전직원/다중일 스모크 전부 정상. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
import { useApi } from './useApi'
|
||||
import type {
|
||||
ApiScheduleCategory,
|
||||
ApiScheduleEvent,
|
||||
ApiSchedulePerson,
|
||||
ScheduleCategoryPayload,
|
||||
ScheduleEventPayload,
|
||||
} from '@/types/schedule'
|
||||
|
||||
// 일정 도메인 API Composable — 인터셉터가 success/data 를 언래핑
|
||||
export function useSchedule() {
|
||||
const api = useApi()
|
||||
|
||||
// 카테고리
|
||||
async function listCategories(): Promise<ApiScheduleCategory[]> {
|
||||
return (await api.get('/schedule/categories')) as unknown as ApiScheduleCategory[]
|
||||
}
|
||||
async function createCategory(
|
||||
payload: ScheduleCategoryPayload,
|
||||
): Promise<ApiScheduleCategory> {
|
||||
return (await api.post('/schedule/categories', payload)) as unknown as ApiScheduleCategory
|
||||
}
|
||||
async function updateCategory(
|
||||
id: string,
|
||||
payload: Partial<ScheduleCategoryPayload>,
|
||||
): Promise<ApiScheduleCategory> {
|
||||
return (await api.patch(`/schedule/categories/${id}`, payload)) as unknown as ApiScheduleCategory
|
||||
}
|
||||
async function deleteCategory(id: string): Promise<void> {
|
||||
await api.delete(`/schedule/categories/${id}`)
|
||||
}
|
||||
|
||||
// 참석자 풀
|
||||
async function listPeople(): Promise<ApiSchedulePerson[]> {
|
||||
return (await api.get('/schedule/people')) as unknown as ApiSchedulePerson[]
|
||||
}
|
||||
|
||||
// 일정
|
||||
async function listEvents(
|
||||
start: string,
|
||||
end: string,
|
||||
): Promise<ApiScheduleEvent[]> {
|
||||
return (await api.get('/schedule/events', {
|
||||
params: { start, end },
|
||||
})) as unknown as ApiScheduleEvent[]
|
||||
}
|
||||
async function createEvent(
|
||||
payload: ScheduleEventPayload,
|
||||
): Promise<ApiScheduleEvent> {
|
||||
return (await api.post('/schedule/events', payload)) as unknown as ApiScheduleEvent
|
||||
}
|
||||
async function updateEvent(
|
||||
id: string,
|
||||
payload: Partial<ScheduleEventPayload>,
|
||||
): Promise<ApiScheduleEvent> {
|
||||
return (await api.patch(`/schedule/events/${id}`, payload)) as unknown as ApiScheduleEvent
|
||||
}
|
||||
async function deleteEvent(id: string): Promise<void> {
|
||||
await api.delete(`/schedule/events/${id}`)
|
||||
}
|
||||
|
||||
return {
|
||||
listCategories,
|
||||
createCategory,
|
||||
updateCategory,
|
||||
deleteCategory,
|
||||
listPeople,
|
||||
listEvents,
|
||||
createEvent,
|
||||
updateEvent,
|
||||
deleteEvent,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user