Skip to content

Commit

Permalink
fix(admin): cron 유료로 클릭시 최신반영 플로우로 변경 (#173)
Browse files Browse the repository at this point in the history
  • Loading branch information
saseungmin authored Aug 21, 2024
1 parent c14a8e9 commit 9d56aa4
Show file tree
Hide file tree
Showing 14 changed files with 141 additions and 95 deletions.
Binary file not shown.
Binary file not shown.
1 change: 1 addition & 0 deletions apps/admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"dependencies": {
"@dnd-academy/core": "*",
"@dnd-academy/ui": "*",
"@tanstack/react-query": "5.52.0",
"@vercel/blob": "0.23.4",
"clsx": "2.1.1",
"framer-motion": "11.2.10",
Expand Down
38 changes: 4 additions & 34 deletions apps/admin/src/app/api/cron/current-applicant-count/route.ts
Original file line number Diff line number Diff line change
@@ -1,51 +1,21 @@
import { NextRequest, NextResponse } from 'next/server';

import { put } from '@vercel/blob';
import { JWT } from 'google-auth-library';
import { GoogleSpreadsheet } from 'google-spreadsheet';
import { updateCurrentApplicantCount } from '@/app/api/handler';

export const dynamic = 'force-dynamic';

export const runtime = 'nodejs';

export async function GET(request: NextRequest) {
export async function PUT(request: NextRequest) {
const authHeader = request.headers.get('authorization');

if (authHeader !== `Bearer ${process.env.CRON_SECRET}`) {
return new Response('Unauthorized', {
status: 401,
});
}

const serviceAccountAuth = new JWT({
email: process.env.GOOGLE_CLIENT_EMAIL,
key: process.env.GOOGLE_PRIVATE_KEY.replace(/\\n/g, '\n'),
scopes: ['https://www.googleapis.com/auth/spreadsheets'],
});

const developerApplicantDoc = new GoogleSpreadsheet('1LLxVCTkqtTZoMftrEkYOlwVdyEwoEKwCg7WvXwfW2Rk', serviceAccountAuth);
const designerApplicantDoc = new GoogleSpreadsheet('1BToiD3gjzT-SKWeKnQMRuFvGXmYv44oEigSIJy_w1Jc', serviceAccountAuth);

await developerApplicantDoc.loadInfo();
await designerApplicantDoc.loadInfo();

const developerApplicantRows = await developerApplicantDoc.sheetsByIndex[0].getRows();
const designerApplicantRows = await designerApplicantDoc.sheetsByIndex[0].getRows();

const currentApplicantCountForm = {
developer: developerApplicantRows.length,
designer: designerApplicantRows.length,
};

const jsonString = JSON.stringify(currentApplicantCountForm);

const requestBlob = new Blob([jsonString], { type: 'application/json' });

await put('current_applicant_count.json', requestBlob, {
access: 'public',
token: process.env.DND_ACADEMY_V2_BLOB_READ_WRITE_TOKEN,
addRandomSuffix: false,
cacheControlMaxAge: 3600,
});
const currentApplicantCountForm = await updateCurrentApplicantCount();

return NextResponse.json(currentApplicantCountForm, {
status: 200,
Expand Down
15 changes: 15 additions & 0 deletions apps/admin/src/app/api/current-applicant-count/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { NextResponse } from 'next/server';

import { updateCurrentApplicantCount } from '@/app/api/handler';

export const dynamic = 'force-dynamic';

export const runtime = 'nodejs';

export async function PUT() {
const currentApplicantCountForm = await updateCurrentApplicantCount();

return NextResponse.json(currentApplicantCountForm, {
status: 200,
});
}
39 changes: 39 additions & 0 deletions apps/admin/src/app/api/handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { put } from '@vercel/blob';
import { JWT } from 'google-auth-library';
import { GoogleSpreadsheet } from 'google-spreadsheet';

// eslint-disable-next-line import/prefer-default-export
export const updateCurrentApplicantCount = async () => {
const serviceAccountAuth = new JWT({
email: process.env.GOOGLE_CLIENT_EMAIL,
key: process.env.GOOGLE_PRIVATE_KEY.replace(/\\n/g, '\n'),
scopes: ['https://www.googleapis.com/auth/spreadsheets'],
});

const developerApplicantDoc = new GoogleSpreadsheet('1LLxVCTkqtTZoMftrEkYOlwVdyEwoEKwCg7WvXwfW2Rk', serviceAccountAuth);
const designerApplicantDoc = new GoogleSpreadsheet('1BToiD3gjzT-SKWeKnQMRuFvGXmYv44oEigSIJy_w1Jc', serviceAccountAuth);

await developerApplicantDoc.loadInfo();
await designerApplicantDoc.loadInfo();

const developerApplicantRows = await developerApplicantDoc.sheetsByIndex[0].getRows();
const designerApplicantRows = await designerApplicantDoc.sheetsByIndex[0].getRows();

const currentApplicantCountForm = {
developer: developerApplicantRows.length,
designer: designerApplicantRows.length,
};

const jsonString = JSON.stringify(currentApplicantCountForm);

const requestBlob = new Blob([jsonString], { type: 'application/json' });

await put('current_applicant_count.json', requestBlob, {
access: 'public',
token: process.env.DND_ACADEMY_V2_BLOB_READ_WRITE_TOKEN,
addRandomSuffix: false,
cacheControlMaxAge: 3600,
});

return currentApplicantCountForm;
};
5 changes: 2 additions & 3 deletions apps/admin/src/app/current-applicant-count/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { api, type CurrentApplicantCount } from '@dnd-academy/core';
import { Counter, PageTitle } from '@dnd-academy/ui';

import CurrentApplicantCountForm from '@/components/CurrentApplicantCountForm';
import CurrentApplicantCountAction from '@/components/CurrentApplicantCountAction';

import styles from './page.module.scss';

Expand All @@ -25,9 +25,8 @@ async function page() {
<Counter count={currentApplicantCount} />
명이 지원했어요!
</div>
<CurrentApplicantCountForm initialApplicantCount={currentApplicantCountData} />
<CurrentApplicantCountAction />
</>

);
}

Expand Down
5 changes: 4 additions & 1 deletion apps/admin/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { pretendardFont } from '@/app/_fonts';
import ClientProvider from '@/components/common/ClientLayout';

import '@dnd-academy/ui/style.css';
import 'src/styles/global.scss';
Expand All @@ -11,7 +12,9 @@ function RootLayout({ children }: {
<html lang="ko" className={pretendardFont.variable}>
<body>
<main className={styles.main}>
{children}
<ClientProvider>
{children}
</ClientProvider>
</main>
</body>
</html>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
.applicantCountFormWrapper {
.applicantCountWrapper {
display: flex;
flex-direction: column;
gap: 20px;
margin-top: 20px;

.applicantCountForm {
display: flex;
flex-direction: row;
}

.message {
@include text('body1');

Expand Down
31 changes: 31 additions & 0 deletions apps/admin/src/components/CurrentApplicantCountAction/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use client';

import { api, type CurrentApplicantCount } from '@dnd-academy/core';
import { Button } from '@dnd-academy/ui';
import { useMutation } from '@tanstack/react-query';
import clsx from 'clsx';

import styles from './index.module.scss';

function CurrentApplicantCountAction() {
const { mutate, isSuccess } = useMutation({
mutationFn: async () => {
await api<CurrentApplicantCount>({
url: '/current-applicant-count',
method: 'PUT',
type: 'bff',
});
},
});

return (
<div className={styles.applicantCountWrapper}>
<Button onClick={() => mutate()}>최신 지원자수 반영하기</Button>
{isSuccess && (
<div className={clsx(styles.message, styles.success)}>지원자수가 최신으로 업데이트 되었습니다.</div>
)}
</div>
);
}

export default CurrentApplicantCountAction;
50 changes: 0 additions & 50 deletions apps/admin/src/components/CurrentApplicantCountForm/index.tsx

This file was deleted.

24 changes: 24 additions & 0 deletions apps/admin/src/components/common/ClientLayout/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
'use client';

import { PropsWithChildren } from 'react';

import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

const queryClient = new QueryClient({
defaultOptions: {
queries: {
retry: false,
refetchOnWindowFocus: false,
},
},
});

function ClientProvider({ children }: PropsWithChildren) {
return (
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
);
}

export default ClientProvider;
2 changes: 1 addition & 1 deletion apps/admin/vercel.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"crons": [{
"path": "/api/cron/current-applicant-count",
"schedule": "0 * * * *"
"schedule": "0 0 * * *"
}]
}
19 changes: 19 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4289,6 +4289,24 @@ __metadata:
languageName: node
linkType: hard

"@tanstack/query-core@npm:5.52.0":
version: 5.52.0
resolution: "@tanstack/query-core@npm:5.52.0"
checksum: 10/cd21e87ad7a0bbb262dea21704352eb1bbaafc26776ae1602b4be9a2d0d1f16a89cc4b5951f69083e26f970d75386431240d5a573ed9bce5a37ba2dc862e376a
languageName: node
linkType: hard

"@tanstack/react-query@npm:5.52.0":
version: 5.52.0
resolution: "@tanstack/react-query@npm:5.52.0"
dependencies:
"@tanstack/query-core": "npm:5.52.0"
peerDependencies:
react: ^18.0.0
checksum: 10/6976d309d306f0dd70f25e0de820812c47bfc39b654294e1512d4bb5320d0abad1bc3d6de16a25b7ae6766eb9b928c5e396e996d7d6689d33a1c1436de68cf7b
languageName: node
linkType: hard

"@testing-library/dom@npm:10.1.0":
version: 10.1.0
resolution: "@testing-library/dom@npm:10.1.0"
Expand Down Expand Up @@ -5780,6 +5798,7 @@ __metadata:
"@dnd-academy/eslint-config": "npm:*"
"@dnd-academy/ui": "npm:*"
"@next/eslint-plugin-next": "npm:14.2.4"
"@tanstack/react-query": "npm:5.52.0"
"@testing-library/dom": "npm:10.3.1"
"@testing-library/jest-dom": "npm:6.4.6"
"@testing-library/react": "npm:16.0.0"
Expand Down

0 comments on commit 9d56aa4

Please sign in to comment.