Skip to content

Commit e34cbe9

Browse files
authored
Merge pull request #211 from GDGoCINHA/master
Master 강제 병합
2 parents c5ebe10 + d041cd4 commit e34cbe9

14 files changed

Lines changed: 1114 additions & 8 deletions

File tree

package-lock.json

Lines changed: 77 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"@heroui/system": "^2.4.7",
1515
"@heroui/theme": "^2.4.6",
1616
"@nextui-org/react": "^2.6.11",
17+
"@react-google-maps/api": "^2.20.7",
1718
"@splidejs/react-splide": "^0.7.12",
1819
"@splidejs/splide": "^4.1.4",
1920
"@splidejs/splide-extension-auto-scroll": "^0.5.3",

public/images/homecoming/bg.png

749 KB
Loading
2.26 MB
Loading

src/app/admin/member-manager/page.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ import AdminTableBottomContent from '@/components/admin/AdminTableBottomContent'
2323

2424
/** 백엔드 enum과 일치하는 값(전송용) */
2525
const ROLE_OPTIONS = ['GUEST', 'MEMBER', 'CORE', 'LEAD', 'ORGANIZER', 'ADMIN'];
26-
const TEAM_ENUM_VALUES = ['BD', 'HR', 'TECH', 'PR_DESIGN'];
26+
const TEAM_ENUM_VALUES = ['BD', 'HR', 'TECH', 'PR_DESIGN', 'HQ'];
2727

2828
/** 화면 표시용 라벨 */
2929
const TEAM_LABEL = {
30-
BD: 'BD', HR: 'HR', TECH: 'TECH', PR_DESIGN: 'PR/DESIGN',
30+
BD: 'BD', HR: 'HR', TECH: 'TECH', PR_DESIGN: 'PR/DESIGN', HQ: 'HQ',
3131
};
3232

3333
const roleColor = (r) => ({

src/app/core-attendance/page.jsx

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,32 @@ const setQS = (entries) => {
1414
window.history.replaceState({}, '', u.toString());
1515
};
1616

17+
// ===== CSV 저장 공통 헬퍼 =====
18+
const saveResponseAsFile = (res, fallbackName) => {
19+
// Excel 한글 깨짐 방지용 BOM
20+
const BOM = new Uint8Array([0xEF, 0xBB, 0xBF]);
21+
const blob = new Blob([BOM, res.data], { type: 'text/csv;charset=utf-8' });
22+
23+
// 서버가 파일명 내려주면 우선 사용
24+
let filename = fallbackName;
25+
const cd = res.headers && (res.headers['content-disposition'] || res.headers['Content-Disposition']);
26+
if (cd) {
27+
const m = /filename\*=UTF-8''([^;]+)|filename="?([^"]+)"?/i.exec(cd);
28+
const decoded = m && decodeURIComponent((m[1] || m[2] || '').trim());
29+
if (decoded) filename = decoded;
30+
}
31+
32+
const url = URL.createObjectURL(blob);
33+
const a = document.createElement('a');
34+
a.href = url;
35+
a.download = filename;
36+
document.body.appendChild(a);
37+
a.click();
38+
a.remove();
39+
URL.revokeObjectURL(url);
40+
};
41+
42+
1743
export default function AttendancePage() {
1844
const {apiClient} = useAuthenticatedApi();
1945

@@ -49,6 +75,17 @@ export default function AttendancePage() {
4975
})).data.data,
5076

5177
summary: async (d) => (await apiClient.get(`/core-attendance/meetings/${d}/summary`)).data.data,
78+
79+
downloadSummaryCsvForDateAndSave: async (d) => {
80+
const res = await apiClient.get(`/core-attendance/meetings/${d}/summary.csv`, { responseType: 'blob' });
81+
saveResponseAsFile(res, `attendance-${d}.csv`);
82+
},
83+
84+
downloadSummaryCsvAllAndSave: async () => {
85+
const res = await apiClient.get('/core-attendance/meetings/summary.csv', { responseType: 'blob' });
86+
saveResponseAsFile(res, 'attendance-summary.csv');
87+
},
88+
5289
};
5390

5491
/** URL 동기화 */
@@ -366,6 +403,25 @@ export default function AttendancePage() {
366403
<Card className="bg-default-100 dark:bg-default-50">
367404
<CardBody className="gap-3 text-white">
368405
<b>요약</b>
406+
<Button
407+
size="sm"
408+
variant="flat"
409+
color="primary"
410+
onPress={() => api.downloadSummaryCsvForDateAndSave(date)}
411+
isDisabled={!date}
412+
>
413+
날짜 CSV
414+
</Button>
415+
416+
<Button
417+
size="sm"
418+
variant="flat"
419+
color="secondary"
420+
onPress={() => api.downloadSummaryCsvAllAndSave()}
421+
>
422+
전체 CSV
423+
</Button>
424+
369425
{summary ? (<div className="text-sm">
370426
<div className="mb-2">전체 {summary.present} / {summary.total}</div>
371427
<Divider/>

src/app/homecoming/layout.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Suspense } from "react";
2+
import Loader from '@/components/ui/common/Loader.jsx';
3+
4+
export const metadata = {
5+
title: "Homecoming",
6+
description: "GDGoC INHA 제1회 홈커밍 데이 행사 안내 및 참여 페이지",
7+
};
8+
9+
export default function HomecomingLayout({ children }) {
10+
return (
11+
<Suspense fallback={ <Loader /> }>
12+
{children}
13+
</Suspense>
14+
);
15+
}

0 commit comments

Comments
 (0)