Skip to content

Commit 54e559f

Browse files
committed
코드 리팩토링
1 parent e177cd7 commit 54e559f

File tree

8 files changed

+110
-66
lines changed

8 files changed

+110
-66
lines changed

apps/front/src/containers/home/search/autocomplete.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { useAtomValue } from "jotai/utils";
33
import Image from "next/image";
44
import Link from "next/link";
55

6-
import { AutocompleteList } from "pages/api/autocomplete";
6+
import type { AutocompleteList } from "lib/autocomplete";
77

88
import {
99
isOpenAutocompleteAtom,

apps/front/src/containers/home/search/form.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export default function Form() {
1212
return (
1313
<form
1414
onSubmit={() => router.push(`/search/${keyword}`)}
15-
className="center flex-1 py-[2rem]"
15+
className="center flex-1"
1616
>
1717
<Input />
1818
<button

apps/front/src/containers/home/search/hooks.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { useAtom } from "jotai";
22
import { useAtomCallback, useAtomValue, useUpdateAtom } from "jotai/utils";
33
import { useCallback, useState } from "react";
44

5-
import { AutocompleteList } from "pages/api/autocomplete";
5+
import type { AutocompleteList } from "lib/autocomplete";
66

77
import {
88
autocompleteAtom,

apps/front/src/containers/home/search/input.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { useRouter } from "next/router";
33
import { useEffect, useState } from "react";
44
import { useDebounce } from "rooks";
55

6-
import { AutocompleteList } from "pages/api/autocomplete";
6+
import type { AutocompleteList } from "lib/autocomplete";
77
import { Keys } from "utils/keyboard";
88

99
import { useIsOpenAutocomplete, useSelectedIndex } from "./hooks";
@@ -77,7 +77,7 @@ export default function Input() {
7777
type="text"
7878
spellCheck="false"
7979
autoComplete="off"
80-
className="flex-1 ml-[1rem] bg-transparent font-light text-almost-black"
80+
className="flex-1 h-[9rem] pl-[2rem] py-[2rem] bg-transparent font-light text-almost-black"
8181
placeholder="소환사 검색"
8282
value={items[selectedIndex]?.name ?? keyword}
8383
onPaste={onPaste}

apps/front/src/containers/home/search/store.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { atom } from "jotai";
22
import { atomWithQuery } from "jotai/query";
33
import ky from "ky-universal";
44

5-
import { AutocompleteList } from "pages/api/autocomplete";
5+
import type { AutocompleteList } from "lib/autocomplete";
66

77
const initialData: AutocompleteList = [];
88

apps/front/src/lib/autocomplete.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import ky from "ky";
2+
3+
type OPGGAutocompleteResponse = {
4+
sections: {
5+
groups: {
6+
type: string;
7+
items: {
8+
level: number;
9+
name: string;
10+
profileIconUrl: string;
11+
tierRank: { tierRank: string; lp: number };
12+
}[];
13+
}[];
14+
}[];
15+
};
16+
17+
export type AutocompleteItem = {
18+
level: number;
19+
name: string;
20+
profileIconUrl: string;
21+
tierRank: string | null;
22+
lp: number | null;
23+
winningPercentate?: number;
24+
};
25+
26+
export type AutocompleteList = AutocompleteItem[];
27+
28+
export async function getAutoCompleteList(keyword: string) {
29+
const { sections } = await ky(
30+
`https://www.op.gg/ajax/autocomplete.json/keyword=${encodeURI(keyword)}`,
31+
{ searchParams: { api_key: process.env.RIOT_API_KEY as string } }
32+
).json<OPGGAutocompleteResponse>();
33+
34+
const data: AutocompleteList = sections
35+
.map(({ groups }) =>
36+
groups
37+
.filter((group) => group.type === "SUMMONER")
38+
.map(({ items }) =>
39+
items
40+
.filter(({ name }) => name.replaceAll(" ", "").length > 1)
41+
.map(
42+
({
43+
level,
44+
name,
45+
profileIconUrl,
46+
tierRank: { tierRank, lp } = {
47+
tierRank: null,
48+
lp: null,
49+
},
50+
}) => ({
51+
level,
52+
name,
53+
profileIconUrl,
54+
tierRank,
55+
lp,
56+
})
57+
)
58+
)
59+
.flat()
60+
)
61+
.flat();
62+
63+
return data;
64+
}
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import { NextRequest } from "next/server";
1+
import { NextRequest, NextResponse } from "next/server";
22

33
import { IS_PRODUCTION, IS_USING_RATE_LIMIT } from "utils";
44
import ipRateLimit from "utils/ip-rate-limit";
55

6-
export async function middleware(req: NextRequest) {
7-
if (IS_PRODUCTION && IS_USING_RATE_LIMIT) {
8-
return await ipRateLimit(req);
9-
}
10-
}
6+
export const middleware = async (req: NextRequest) => {
7+
return IS_PRODUCTION && IS_USING_RATE_LIMIT
8+
? await ipRateLimit(req)
9+
: NextResponse.next();
10+
};
Lines changed: 34 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,43 @@
1-
import ky from "ky-universal";
1+
import { type AutocompleteList, getAutoCompleteList } from "lib/autocomplete";
22
import type { NextApiRequest, NextApiResponse } from "next";
3-
4-
type OPGGAutocompleteResponse = {
5-
sections: {
6-
groups: {
7-
type: string;
8-
items: {
9-
level: number;
10-
name: string;
11-
profileIconUrl: string;
12-
tierRank: { tierRank: string; lp: number };
13-
}[];
14-
}[];
15-
}[];
16-
};
17-
18-
export type AutocompleteList = {
19-
level: number;
20-
name: string;
21-
profileIconUrl: string;
22-
tierRank: string | null;
23-
lp: number | null;
24-
}[];
3+
import { prisma } from "utils/prisma";
254

265
export default async function handler(
276
req: NextApiRequest,
287
res: NextApiResponse<AutocompleteList>
298
) {
309
const keyword = req.query.keyword as string;
3110

32-
const { sections } = await ky(
33-
`https://www.op.gg/ajax/autocomplete.json/keyword=${encodeURI(keyword)}`
34-
).json<OPGGAutocompleteResponse>();
35-
const data = sections
36-
.map(({ groups }) =>
37-
groups
38-
.filter((group) => group.type === "SUMMONER")
39-
.map(({ items }) =>
40-
items.map(
41-
({
42-
level,
43-
name,
44-
profileIconUrl,
45-
tierRank: { tierRank, lp } = {
46-
tierRank: null,
47-
lp: null,
48-
},
49-
}) => ({
50-
level,
51-
name,
52-
profileIconUrl,
53-
tierRank,
54-
lp,
55-
})
56-
)
57-
)
58-
.flat()
59-
)
60-
.flat();
61-
62-
res.status(200).json(data);
11+
const data = await getAutoCompleteList(keyword);
12+
13+
if (data.length === 0) return;
14+
15+
const names = data.map(({ name }) => name);
16+
17+
const summoners = await prisma.summoner.findMany({
18+
where: {
19+
name: { in: names },
20+
leagues: { some: { queueType: "RANKED_SOLO_5x5" } },
21+
},
22+
include: {
23+
leagues: true,
24+
},
25+
});
26+
27+
const result: AutocompleteList = data.map((item) => {
28+
const summoner = summoners.find((summoner) => summoner.name === item.name);
29+
30+
if (summoner !== undefined && summoner.leagues.length > 0) {
31+
const { wins, losses } = summoner.leagues[0];
32+
const total = wins + losses;
33+
return {
34+
...item,
35+
winningPercentage: ((wins / total) * 100).toFixed(2),
36+
};
37+
} else {
38+
return item;
39+
}
40+
});
41+
42+
return res.json(result);
6343
}

0 commit comments

Comments
 (0)