Skip to content

Commit 2299738

Browse files
authored
Merge pull request #67 from hs-shell/feat/mock-dev-mode
feat: mock 데이터 기반 개발 환경 추가
2 parents be99caa + ab6a6e6 commit 2299738

6 files changed

Lines changed: 315 additions & 2 deletions

File tree

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,7 @@ tmp/
4343
temp/
4444

4545
*.zip
46-
dist
46+
dist
47+
48+
*.md
49+
!README.md

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"scripts": {
77
"dev": "vite",
88
"build": "tsc -b && vite build",
9+
"build:mock": "tsc -b && vite build --mode mock",
910
"lint": "eslint .",
1011
"preview": "vite preview"
1112
},

src/hooks/useCourseData.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,34 @@ export function useCourseData(courses: CourseBase[]) {
1414
const [remainingTime, setRemainingTime] = useState(0);
1515
const [isError, setIsError] = useState(false);
1616

17+
// dev 모드: mock 데이터 로드
18+
useEffect(() => {
19+
if (!import.meta.env.VITE_MOCK) return;
20+
let cancelled = false;
21+
import('@/mocks/mockData').then(({ mockVods, mockAssigns, mockQuizes }) => {
22+
if (cancelled) return;
23+
setVods(mockVods);
24+
setAssigns(mockAssigns);
25+
setQuizes(mockQuizes);
26+
setRefreshTime(new Date().toLocaleTimeString());
27+
setRemainingTime(5);
28+
});
29+
return () => {
30+
cancelled = true;
31+
};
32+
}, []);
33+
34+
// dev 모드에서는 실제 fetch를 하지 않음
1735
const updateData = useCallback(async () => {
36+
if (import.meta.env.VITE_MOCK) {
37+
const { mockVods, mockAssigns, mockQuizes } = await import('@/mocks/mockData');
38+
setVods(mockVods);
39+
setAssigns(mockAssigns);
40+
setQuizes(mockQuizes);
41+
setRefreshTime(new Date().toLocaleTimeString());
42+
setRemainingTime(0);
43+
return;
44+
}
1845
try {
1946
setIsError(false);
2047
setIsPending(true);

src/hooks/useGetCourse.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ export interface UseCourseResult {
1010
export const useGetCourses = (): UseCourseResult => {
1111
const [courses, setCourses] = useState<CourseBase[]>([]);
1212
useEffect(() => {
13+
if (import.meta.env.VITE_MOCK) {
14+
import('@/mocks/mockData').then(({ mockCourses }) => {
15+
setCourses(mockCourses);
16+
saveDataToStorage('courses', JSON.stringify(mockCourses));
17+
console.info('[Dotbugi] DEV 모드: mock 강의 목록 사용');
18+
});
19+
return;
20+
}
1321
if (!document) return;
1422
const courseData = Array.from(document.querySelectorAll('.course_box'));
1523
const data = courseData

src/mocks/mockData.ts

Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
import { CourseBase, Vod, Assign, Quiz } from '@/content/types';
2+
3+
function offsetDate(days: number, hours = 0): string {
4+
const d = new Date();
5+
d.setDate(d.getDate() + days);
6+
d.setHours(d.getHours() + hours);
7+
const pad = (n: number) => String(n).padStart(2, '0');
8+
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;
9+
}
10+
11+
function makeRange(startDays: number, endDays: number): string {
12+
return `${offsetDate(startDays)} ~ ${offsetDate(endDays)}`;
13+
}
14+
15+
export const mockCourses: CourseBase[] = [
16+
{ courseId: '1001', courseTitle: '자료구조', prof: '김교수' },
17+
{ courseId: '1002', courseTitle: '운영체제', prof: '이교수' },
18+
{ courseId: '1003', courseTitle: '컴퓨터네트워크', prof: '박교수' },
19+
{ courseId: '1004', courseTitle: '데이터베이스', prof: '최교수' },
20+
];
21+
22+
export const mockVods: Vod[] = [
23+
// 출석 완료 + 기간 내
24+
{
25+
courseId: '1001',
26+
courseTitle: '자료구조',
27+
prof: '김교수',
28+
week: 7,
29+
subject: '7주차',
30+
title: '이진 탐색 트리',
31+
url: '#',
32+
range: makeRange(-3, 5),
33+
length: '45:00',
34+
isAttendance: 'O',
35+
weeklyAttendance: '1/1',
36+
},
37+
// 결석 + 마감 임박 (오늘 안에 끝남)
38+
{
39+
courseId: '1001',
40+
courseTitle: '자료구조',
41+
prof: '김교수',
42+
week: 7,
43+
subject: '7주차',
44+
title: '힙과 우선순위 큐',
45+
url: '#',
46+
range: makeRange(-5, 0, ),
47+
length: '38:00',
48+
isAttendance: 'X',
49+
weeklyAttendance: '0/1',
50+
},
51+
// 결석 + 기간 여유
52+
{
53+
courseId: '1002',
54+
courseTitle: '운영체제',
55+
prof: '이교수',
56+
week: 6,
57+
subject: '6주차',
58+
title: '프로세스 동기화',
59+
url: '#',
60+
range: makeRange(-2, 7),
61+
length: '50:00',
62+
isAttendance: 'X',
63+
weeklyAttendance: '0/1',
64+
},
65+
// 출석 완료
66+
{
67+
courseId: '1002',
68+
courseTitle: '운영체제',
69+
prof: '이교수',
70+
week: 6,
71+
subject: '6주차',
72+
title: '데드락',
73+
url: '#',
74+
range: makeRange(-2, 7),
75+
length: '42:00',
76+
isAttendance: 'O',
77+
weeklyAttendance: '1/1',
78+
},
79+
// 결석 + 마감 매우 임박 (몇 시간 남음)
80+
{
81+
courseId: '1003',
82+
courseTitle: '컴퓨터네트워크',
83+
prof: '박교수',
84+
week: 5,
85+
subject: '5주차',
86+
title: 'TCP/IP 프로토콜',
87+
url: '#',
88+
range: makeRange(-6, 0),
89+
length: '55:00',
90+
isAttendance: 'X',
91+
weeklyAttendance: '0/2',
92+
},
93+
{
94+
courseId: '1003',
95+
courseTitle: '컴퓨터네트워크',
96+
prof: '박교수',
97+
week: 5,
98+
subject: '5주차',
99+
title: 'UDP와 소켓 프로그래밍',
100+
url: '#',
101+
range: makeRange(-6, 0),
102+
length: '35:00',
103+
isAttendance: 'O',
104+
weeklyAttendance: '1/2',
105+
},
106+
// 출석 + range가 넉넉
107+
{
108+
courseId: '1004',
109+
courseTitle: '데이터베이스',
110+
prof: '최교수',
111+
week: 4,
112+
subject: '4주차',
113+
title: '정규화 이론',
114+
url: '#',
115+
range: makeRange(-1, 14),
116+
length: '60:00',
117+
isAttendance: 'O',
118+
weeklyAttendance: '1/1',
119+
},
120+
];
121+
122+
export const mockAssigns: Assign[] = [
123+
// 미제출 + 마감 임박 (내일)
124+
{
125+
courseId: '1001',
126+
courseTitle: '자료구조',
127+
prof: '김교수',
128+
subject: '7주차',
129+
title: '이진 트리 구현 과제',
130+
url: '#',
131+
isSubmit: false,
132+
dueDate: offsetDate(1),
133+
},
134+
// 미제출 + 마감 3일 뒤
135+
{
136+
courseId: '1002',
137+
courseTitle: '운영체제',
138+
prof: '이교수',
139+
subject: '6주차',
140+
title: '프로세스 스케줄링 시뮬레이션',
141+
url: '#',
142+
isSubmit: false,
143+
dueDate: offsetDate(3),
144+
},
145+
// 제출 완료 + 마감 아직
146+
{
147+
courseId: '1001',
148+
courseTitle: '자료구조',
149+
prof: '김교수',
150+
subject: '6주차',
151+
title: '스택/큐 구현 과제',
152+
url: '#',
153+
isSubmit: true,
154+
dueDate: offsetDate(5),
155+
},
156+
// 미제출 + 마감 7일 뒤
157+
{
158+
courseId: '1003',
159+
courseTitle: '컴퓨터네트워크',
160+
prof: '박교수',
161+
subject: '5주차',
162+
title: '소켓 프로그래밍 실습',
163+
url: '#',
164+
isSubmit: false,
165+
dueDate: offsetDate(7),
166+
},
167+
// 제출 완료 + 마감 지남 (새로고침 전 마감 테스트)
168+
{
169+
courseId: '1004',
170+
courseTitle: '데이터베이스',
171+
prof: '최교수',
172+
subject: '4주차',
173+
title: 'SQL 쿼리 작성',
174+
url: '#',
175+
isSubmit: true,
176+
dueDate: offsetDate(-1),
177+
},
178+
// 미제출 + 마감 몇 시간 뒤 (긴급)
179+
{
180+
courseId: '1004',
181+
courseTitle: '데이터베이스',
182+
prof: '최교수',
183+
subject: '5주차',
184+
title: 'ERD 설계 과제',
185+
url: '#',
186+
isSubmit: false,
187+
dueDate: offsetDate(0, 3),
188+
},
189+
// 미제출 + 마감 이미 지남 (새로고침 전 마감 테스트)
190+
{
191+
courseId: '1002',
192+
courseTitle: '운영체제',
193+
prof: '이교수',
194+
subject: '5주차',
195+
title: '메모리 관리 보고서',
196+
url: '#',
197+
isSubmit: false,
198+
dueDate: offsetDate(-2),
199+
},
200+
// dueDate null 케이스
201+
{
202+
courseId: '1003',
203+
courseTitle: '컴퓨터네트워크',
204+
prof: '박교수',
205+
subject: '6주차',
206+
title: '네트워크 분석 레포트',
207+
url: '#',
208+
isSubmit: false,
209+
dueDate: null,
210+
},
211+
];
212+
213+
export const mockQuizes: Quiz[] = [
214+
// 마감 임박 (내일)
215+
{
216+
courseId: '1001',
217+
courseTitle: '자료구조',
218+
prof: '김교수',
219+
subject: '7주차',
220+
title: '트리 구조 퀴즈',
221+
url: '#',
222+
dueDate: offsetDate(1),
223+
},
224+
// 마감 여유 (5일)
225+
{
226+
courseId: '1002',
227+
courseTitle: '운영체제',
228+
prof: '이교수',
229+
subject: '6주차',
230+
title: '프로세스 관리 퀴즈',
231+
url: '#',
232+
dueDate: offsetDate(5),
233+
},
234+
// 마감 몇 시간 뒤 (긴급)
235+
{
236+
courseId: '1003',
237+
courseTitle: '컴퓨터네트워크',
238+
prof: '박교수',
239+
subject: '5주차',
240+
title: 'OSI 모델 퀴즈',
241+
url: '#',
242+
dueDate: offsetDate(0, 5),
243+
},
244+
// 마감 이미 지남 (새로고침 전 마감)
245+
{
246+
courseId: '1004',
247+
courseTitle: '데이터베이스',
248+
prof: '최교수',
249+
subject: '4주차',
250+
title: 'SQL 기초 퀴즈',
251+
url: '#',
252+
dueDate: offsetDate(-1),
253+
},
254+
// 마감 2주 뒤
255+
{
256+
courseId: '1004',
257+
courseTitle: '데이터베이스',
258+
prof: '최교수',
259+
subject: '5주차',
260+
title: '정규화 퀴즈',
261+
url: '#',
262+
dueDate: offsetDate(14),
263+
},
264+
// dueDate null 케이스
265+
{
266+
courseId: '1001',
267+
courseTitle: '자료구조',
268+
prof: '김교수',
269+
subject: '8주차',
270+
title: '그래프 탐색 퀴즈',
271+
url: '#',
272+
dueDate: null,
273+
},
274+
];

vite.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export default defineConfig(({ mode }) => {
1616
react(),
1717
tsconfigPaths(),
1818
Pages(),
19-
// dev 환경에서는 crx 플러그인을 제외
19+
// dev 서버에서는 crx 플러그인을 제외 (mock 빌드에서는 포함)
2020
!isDev &&
2121
crx({
2222
manifest,

0 commit comments

Comments
 (0)