Skip to content

Commit

Permalink
Merge pull request #127 from softeerbootcamp4th/feat/#124-admin-api
Browse files Browse the repository at this point in the history
[Feat] admin API 연동 구현
  • Loading branch information
sooyeoniya authored Aug 12, 2024
2 parents d7a3b17 + 4532a44 commit 198c1d3
Show file tree
Hide file tree
Showing 29 changed files with 1,200 additions and 306 deletions.
1 change: 1 addition & 0 deletions admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"dependencies": {
"class-variance-authority": "^0.7.0",
"react": "^18.3.1",
"react-cookie": "^7.2.0",
"react-dom": "^18.3.1",
"react-router-dom": "^6.25.1"
},
Expand Down
29 changes: 29 additions & 0 deletions admin/src/apis/authAPI.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { PostAuthParams, PostAuthResponse } from "@/types/authApi";
import "@/types/lotteryApi";
import { fetchWithTimeout } from "@/utils/fetchWithTimeout";

const baseURL = `${import.meta.env.VITE_API_URL}/admin/auth`;
const headers = {
"Content-Type": "application/json",
};

export const AuthAPI = {
async postAuth(body: PostAuthParams): Promise<PostAuthResponse> {
try {
return new Promise((resolve) =>
resolve({
accessToken: "access token",
})
);
const response = await fetchWithTimeout(`${baseURL}`, {
method: "POST",
headers: headers,
body: JSON.stringify(body),
});
return response.json();
} catch (error) {
console.error("Error:", error);
throw error;
}
},
};
136 changes: 136 additions & 0 deletions admin/src/apis/lotteryAPI.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import {
GetLotteryExpectationsParams,
GetLotteryExpectationsResponse,
GetLotteryResponse,
GetLotteryWinnerParams,
GetLotteryWinnerResponse,
PostLotteryWinnerParams,
PostLotteryWinnerResponse,
} from "@/types/lotteryApi";
import { fetchWithTimeout } from "@/utils/fetchWithTimeout";

const baseURL = `${import.meta.env.VITE_API_URL}/admin/event/lottery`;
const headers = {
"Content-Type": "application/json",
};

export const LotteryAPI = {
async getLottery(): Promise<GetLotteryResponse> {
try {
return new Promise((resolve) =>
resolve([
{
lotteryEventId: 1,
startDate: "2024-07-26 00:00",
endDate: "2024-08-25 23:59",
appliedCount: 1000000,
winnerCount: 363,
},
])
);
const response = await fetchWithTimeout(`${baseURL}`, {
method: "GET",
headers: headers,
});
return response.json();
} catch (error) {
console.error("Error:", error);
throw error;
}
},
async postLotteryWinner({ id }: PostLotteryWinnerParams): Promise<PostLotteryWinnerResponse> {
try {
return new Promise((resolve) => resolve({ message: "요청에 성공하였습니다." }));
const response = await fetchWithTimeout(`${baseURL}/${id}/winner`, {
method: "POST",
headers: headers,
});
return response.json();
} catch (error) {
console.error("Error:", error);
throw error;
}
},
async getLotteryWinner({
id,
size,
page,
phoneNumber,
}: GetLotteryWinnerParams): Promise<GetLotteryWinnerResponse> {
try {
return new Promise((resolve) =>
resolve({
data: [
{
id: 1,
phoneNumber: "010-1111-2222",
linkClickedCounts: 1,
expectation: 1,
appliedCount: 3,
},
{
id: 2,
phoneNumber: "010-1111-2223",
linkClickedCounts: 1,
expectation: 1,
appliedCount: 3,
},
{
id: 3,
phoneNumber: "010-1111-2224",
linkClickedCounts: 1,
expectation: 1,
appliedCount: 3,
},
],
isLastPage: false,
})
);
const response = await fetchWithTimeout(
`${baseURL}/${id}/winner?size=${size}&page=${page}&number=${phoneNumber}`,
{
method: "GET",
headers: headers,
}
);
return response.json();
} catch (error) {
console.error("Error:", error);
throw error;
}
},
async getLotteryExpectations({
lotteryId,
participantId,
}: GetLotteryExpectationsParams): Promise<GetLotteryExpectationsResponse> {
try {
return new Promise((resolve) =>
resolve([
{
casperId: 1,
expectation: "기대평 1",
},
{
casperId: 2,
expectation: "기대평 2",
},
{
casperId: 3,
expectation: "기대평 3",
},
])
);
const response = await fetchWithTimeout(
`${baseURL}/${lotteryId}/participants/${participantId}/expectations`,
{
method: "GET",
headers: headers,
}
);
return response.json();
} catch (error) {
console.error("Error:", error);
throw error;
}
},
};
145 changes: 145 additions & 0 deletions admin/src/apis/rushAPI.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import {
GetRushOptionsParams,
GetRushOptionsResponse,
GetRushParticipantListParams,
GetRushParticipantListResponse,
GetRushWinnerListParams,
} from "@/types/rushApi";
import { fetchWithTimeout } from "@/utils/fetchWithTimeout";

const baseURL = `${import.meta.env.VITE_API_URL}/admin/event/rush`;
const headers = {
"Content-Type": "application/json",
};

export const RushAPI = {
async getRushParticipantList({
id,
phoneNumber,
size,
page,
option,
}: GetRushParticipantListParams): Promise<GetRushParticipantListResponse> {
try {
return new Promise((resolve) =>
resolve({
data: [
{
id: 1,
phoneNumber: "010-1111-2222",
balanceGameChoice: option,
createdAt: "2024-07-25 20:00:123",
rank: 1,
},
{
id: 3,
phoneNumber: "010-1111-2222",
balanceGameChoice: option,
createdAt: "2024-07-25 20:00:125",
rank: 2,
},
{
id: 4,
phoneNumber: "010-1111-2222",
balanceGameChoice: option,
createdAt: "2024-07-25 20:00:127",
rank: 3,
},
],
isLastPage: false,
})
);
const response = await fetchWithTimeout(
`${baseURL}/${id}/participants?number=${phoneNumber}&size=${size}&page=${page}&option=${option}`,
{
method: "GET",
headers: headers,
}
);
return response.json();
} catch (error) {
console.error("Error:", error);
throw error;
}
},
async getRushWinnerList({
id,
phoneNumber,
size,
page,
}: GetRushWinnerListParams): Promise<GetRushParticipantListResponse> {
try {
return new Promise((resolve) =>
resolve({
data: [
{
id: 1,
phoneNumber: "010-3843-6999",
balanceGameChoice: 1,
createdAt: "2024-07-25 20:00:123",
rank: 1,
},
{
id: 3,
phoneNumber: "010-1111-2222",
balanceGameChoice: 1,
createdAt: "2024-07-25 20:00:125",
rank: 2,
},
{
id: 4,
phoneNumber: "010-1111-2222",
balanceGameChoice: 1,
createdAt: "2024-07-25 20:00:127",
rank: 3,
},
],
isLastPage: false,
})
);
const response = await fetchWithTimeout(
`${baseURL}/${id}/participants?number=${phoneNumber}&size=${size}&page=${page}`,
{
method: "GET",
headers: headers,
}
);
return response.json();
} catch (error) {
console.error("Error:", error);
throw error;
}
},
async getRushOptions({ id }: GetRushOptionsParams): Promise<GetRushOptionsResponse> {
try {
return new Promise((resolve) =>
resolve([
{
rushOptionId: 1,
mainText: "첫 차로 저렴한 차 사기",
subText: " 첫 차는 가성비가 짱이지!",
resultMainText: "누구보다 가성비 갑인 캐스퍼 일렉트릭",
resultSubText: "전기차 평균보다 훨씬 저렴한 캐스퍼 일렉트릭!",
imageUrl: "left_image.png",
},
{
rushOptionId: 2,
mainText: "첫 차로 성능 좋은 차 사기",
subText: " 차는 당연히 성능이지!",
resultMainText: "필요한 건 다 갖춘 캐스퍼 일렉트릭",
resultSubText: "전기차 평균보다 훨씨니 저렴한 캐스퍼 일렉트릭!",
imageUrl: "left_image.png",
},
])
);
const response = await fetchWithTimeout(`${baseURL}/${id}/options`, {
method: "GET",
headers: headers,
});
return response.json();
} catch (error) {
console.error("Error:", error);
throw error;
}
},
};
4 changes: 2 additions & 2 deletions admin/src/components/Input/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { HTMLProps } from "react";
import { ComponentProps } from "react";

interface InputProps extends HTMLProps<HTMLInputElement> {
interface InputProps extends ComponentProps<"input"> {
label?: string;
}

Expand Down
27 changes: 27 additions & 0 deletions admin/src/components/Route/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useCookies } from "react-cookie";
import { Navigate, Outlet } from "react-router-dom";
import { COOKIE_KEY } from "@/constants/cookie";

interface RouteProps {
redirectPath?: string;
}

export function ProtectedRoute({ redirectPath = "/login" }: RouteProps) {
const [cookies] = useCookies([COOKIE_KEY.ACCESS_TOKEN]);

if (!cookies[COOKIE_KEY.ACCESS_TOKEN]) {
return <Navigate to={redirectPath} replace />;
}

return <Outlet />;
}

export function UnProtectedRoute({ redirectPath = "/lottery" }: RouteProps) {
const [cookies] = useCookies([COOKIE_KEY.ACCESS_TOKEN]);

if (cookies[COOKIE_KEY.ACCESS_TOKEN]) {
return <Navigate to={redirectPath} replace />;
}

return <Outlet />;
}
38 changes: 38 additions & 0 deletions admin/src/components/SelectForm/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { ReactNode } from "react";

interface SelectFormProps {
header: ReactNode;
data: ReactNode[][];
}

export default function SelectForm({ header, data }: SelectFormProps) {
return (
<div className="relative sm:rounded-lg w-[730px] border">
<div className="overflow-y-auto h-full">
<table className="w-full text-sm rtl:text-right text-gray-500 text-center">
<thead className="sticky top-0 z-[5] text-gray-700 bg-gray-50">
<tr>
<th colSpan={2} className="px-6 py-3 h-body-2-medium">
{header}
</th>
</tr>
</thead>
<tbody>
{data.map((tableData, idx) => (
<tr key={`table-data-${idx}`} className="bg-white border-b">
{tableData.map((dataNode, idx) => (
<td
key={`${header}-data-${idx}`}
className="px-6 py-4 h-body-2-regular"
>
{dataNode}
</td>
))}
</tr>
))}
</tbody>
</table>
</div>
</div>
);
}
Loading

0 comments on commit 198c1d3

Please sign in to comment.