Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
d1aee6a
Update issue templates
Rose-my May 23, 2024
fe77c41
Create pull_request_template.md
Rose-my May 23, 2024
d562ccc
init: Vite로 React 초기세팅
Rose-my May 23, 2024
881dab2
etc: eslint, 프리티어 초기세팅
Rose-my May 23, 2024
81e8733
etc: 스타일컴포넌트 설치
Rose-my May 23, 2024
3a0a3ff
etc: 프리티어 설정 변경
Rose-my May 23, 2024
67584a9
etc: alias 수정, 패키지 관리
Rose-my May 27, 2024
afe98f7
etc: 아이콘 svg 설정
Rose-my May 27, 2024
b69bc9f
design: 공통 컴포넌트 UI
Rose-my May 27, 2024
8a5281e
design: 공통 layout UI
Rose-my May 27, 2024
da0c07c
feat: 라우팅 outlet 수정
Rose-my May 27, 2024
363e900
design: 전역스타일 + 공통버튼스타일
Rose-my May 27, 2024
d00ceef
feat: App.tsx, main.tsx
Rose-my May 27, 2024
8a79b50
etc: 네이밍 수정
Rose-my May 27, 2024
e071658
Merge pull request #2 from couplelog/etc/#1/main/initialization
noeyeyh May 27, 2024
5ba88a3
feat: 파트장 투표 페이지와 데모데이 투표 페이지 생성
noeyeyh May 28, 2024
e9ce03e
design: BtnBig 내부 텍스트 줄바꿈 수정
noeyeyh May 28, 2024
28291fd
design: BtnBig에 마우스 오버 시 백그라운드 색상 및 텍스트 색상 변경
noeyeyh May 28, 2024
1912ec2
etc: pages 내 Vote 폴더 생성
noeyeyh May 28, 2024
3c98b18
feat: 투표 결과 페이지 라우팅
noeyeyh Jun 1, 2024
d1e6743
refactor: VoteWrapper 투표 페이지에서도 사용하는 것으로 수정
noeyeyh Jun 3, 2024
602e0e7
feat: 투표 선택한 항목 콘솔창 출력
noeyeyh Jun 3, 2024
5e8f22a
design: 투표 페이지, 결과 페이지 반응형 수정
noeyeyh Jun 4, 2024
9e7e170
feat: 데모데이 결과 페이지 추가
noeyeyh Jun 4, 2024
cf6ed29
Merge pull request #4 from noeyeyh/design/#3/vote/voteUI
Rose-my Jun 19, 2024
ec339ed
design: theme 폰트 사이즈 변경
Rose-my Jun 20, 2024
7028a89
design: 회원가입 페이지 UI
Rose-my Jun 20, 2024
d68d6df
design: 로그인 페이지 UI
Rose-my Jun 20, 2024
f865070
design: 인풋필드 채우기 UI
Rose-my Jun 20, 2024
79686eb
feat: 버튼 클릭시 페이지 이동
Rose-my Jun 20, 2024
52f6aca
Merge pull request #6 from couplelog/design/#5/sign/UI
noeyeyh Jun 20, 2024
2b5e9b5
feat: postEmail api
Rose-my Jun 24, 2024
35f0185
feat: postSignIn api
Rose-my Jun 24, 2024
07027b6
feat: postSignUp api
Rose-my Jun 24, 2024
4130b74
feat: getTopics api
Rose-my Jun 24, 2024
ac9bd02
feat: signIn, signUp page
Rose-my Jun 24, 2024
4b4f4e9
design: theme 추가
Rose-my Jun 24, 2024
19eafa2
feat: custom axios
Rose-my Jun 24, 2024
e6081b7
etc: 필요한 라이브러리 설치
Rose-my Jun 24, 2024
55aaf4e
Merge pull request #8 from couplelog/feat/#7/sign/api
noeyeyh Jun 24, 2024
4cdf753
feat: 투표, 투표 결과 api
noeyeyh Jun 24, 2024
22e9038
feat: 투표 페이지 topicId에 따른 후보 출력
noeyeyh Jun 24, 2024
7c5ff2d
etc: 후보 출력 수정
noeyeyh Jun 25, 2024
cc20234
feat: 투표 결과 출력
noeyeyh Jun 25, 2024
01ce2a9
feat: 투표 결과 내림차순 정렬
noeyeyh Jun 25, 2024
da41a69
refactor: 코드 정리 및 네이밍 변경
noeyeyh Jun 25, 2024
78f854b
feat: customAxios
Rose-my Jun 25, 2024
8eed898
feat: postSignUp 파라미터 추가
Rose-my Jun 25, 2024
73d2982
design: 헤더 수정
Rose-my Jun 25, 2024
99e020c
feat: 회원가입 페이지 api
Rose-my Jun 25, 2024
6ac9357
feat: 라우터 수정
Rose-my Jun 25, 2024
b1f3b71
feat: 타입에 role 추가
Rose-my Jun 25, 2024
1353361
feat: hooks/usePostEmail
Rose-my Jun 25, 2024
e793042
feat: 로그인 페이지 로컬스토리지 저장
Rose-my Jun 25, 2024
f3522aa
Merge pull request #12 from couplelog/refactor/#10/sign/api
noeyeyh Jun 25, 2024
9653f1d
Merge branch 'develop' into feat/#9/vote/api
noeyeyh Jun 25, 2024
4b34fba
etc: develop merge
noeyeyh Jun 25, 2024
d954353
feat: cookie 함수 구현
Rose-my Jun 25, 2024
3228bf7
feat: ErrorHandler 구현
Rose-my Jun 25, 2024
9ec5f91
refactor: 로그인 api
Rose-my Jun 25, 2024
3a4eabb
refactor: 회원가입 페이지
Rose-my Jun 25, 2024
618117a
design: Vote 페이지
Rose-my Jun 25, 2024
8570763
feat: postVote response수정
Rose-my Jun 25, 2024
c6f057b
Merge pull request #11 from couplelog/feat/#9/vote/api
Rose-my Jun 25, 2024
3fe0211
feat: 투표페이지 투표 실패 시 alert 창 출력
noeyeyh Jun 26, 2024
69cdd13
refactor: VoteFront와 VoteBack을 VotePart로 통합
noeyeyh Jun 26, 2024
850c1d9
refactor: ResultFront와 ResultBack을 ResultPart로 통합
noeyeyh Jun 26, 2024
f554750
etc: 주석 추가
noeyeyh Jun 26, 2024
93d3fad
Merge pull request #15 from couplelog/feat/#14/vote/alert
Rose-my Jun 26, 2024
7b289b3
feat: 한 topic의 투표 선택지 반환에서 에러 alert 창으로 출력
noeyeyh Jun 26, 2024
da8e050
Merge branch 'develop' of https://github.com/couplelog/react-vote-cli…
noeyeyh Jun 26, 2024
e856fe8
etc: 로그인안해도 결과는 보이게
Rose-my Jun 27, 2024
75147de
feat: 결과만 보여주기 페이지
Rose-my Jun 27, 2024
9dade54
feat: 로그인 후 결과창과 결과만보여주기 분리
Rose-my Jun 27, 2024
8425e95
design: 버튼 스타일 변경
Rose-my Jun 27, 2024
0943eba
feat: Layout 빼고 결과만 보여주는 것을 분리
Rose-my Jun 27, 2024
fa18ad2
design: 버튼 호버추가
Rose-my Jun 27, 2024
197cbb9
fix: 배포 404에러
Rose-my Jun 27, 2024
b0579fd
Merge pull request #16 from couplelog/refactor/#13/sign
noeyeyh Jun 27, 2024
302f057
Create .htaccess
Rose-my Jun 27, 2024
0ca2d6e
vercel.json 추가
Rose-my Jun 27, 2024
a4d682d
etc: 데모데이 헤더텍스트 수정
noeyeyh Jun 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .github/ISSUE_TEMPLATE/template-issue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
name: template-issue
about: 이슈 템플릿
title: 'design: 투표페이지 뷰'
labels: ''
assignees: ''

---

## 목적

설명

## 작업 상세 내용

- [ ] todo1
- [ ] todo2
- [ ] todo3
22 changes: 22 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
## Related Issues

- close #issue_number

## PR 유형

어떤 변경 사항이 있나요?

- [ ] 새로운 기능 추가
- [ ] 오류 수정
- [ ] CSS 등 스타일 변경
- [ ] 코드에 영향을 주지 않는 변경사항(오타 수정, 탭 사이즈 변경, 변수명 변경)
- [ ] 코드 리팩토링
- [ ] 주석 추가 및 수정
- [ ] 문서 수정
- [ ] 테스트 추가, 테스트 리팩토링
- [ ] 파일 혹은 폴더 삭제

## 변경 사항 in Detail

- [ ] 변경 사항
- 변경 사항 상세 설명
21 changes: 21 additions & 0 deletions vote/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:react-hooks/recommended",
"some-other-config-you-use",
"prettier",
],
ignorePatterns: ["dist", ".eslintrc.cjs"],
parser: "@typescript-eslint/parser",
plugins: ["prettier"],
rules: {
"prettier/prettier": "error",
},
// plugins: ["react-refresh"],
// rules: {
// "react-refresh/only-export-components": ["warn", { allowConstantExport: true }],
// },
};
26 changes: 26 additions & 0 deletions vote/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

.env
8 changes: 8 additions & 0 deletions vote/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"semi": true,
"tabWidth": 2,
"printWidth": 80,
"trailingComma": "all",
"bracketSameLine": true,
"endOfLine": "auto"
}
9 changes: 9 additions & 0 deletions vote/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Vite로 React 실행하기

cd vote // Directory 이동

code . // 해당 디렉토리를 최상위로 VSCode 실행

yarn // 의존성 모듈 설치

yarn dev // React 앱 실행
21 changes: 21 additions & 0 deletions vote/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!doctype html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>리액트 투표페이지</title>
<link
rel="icon"
href="/src/assets/image/favicon.png"
type="image/svg+xml" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:[email protected]&display=swap"
rel="stylesheet" />
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
42 changes: 42 additions & 0 deletions vote/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"name": "vote",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

비트!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@songess 왜케 깜찍하게 말하세요

"build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
"dependencies": {
"@types/react-router-dom": "^5.3.3",
"axios": "^1.7.2",
"react": "^18.2.0",
"react-cookie": "^7.1.4",
"react-dom": "^18.2.0",
"react-query": "^3.39.3",
"react-router-dom": "^6.23.1",
"styled-components": "^6.1.11",
"styled-reset": "^4.5.2"
Comment on lines +20 to +21

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

스타일링을 위해서 styled-components 라이브러리를 사용하셨네요! 제가 지난 번에 전체 톡방에 올린 것처럼, reactJS 와 같이 CSR을 지원하는 라이브러리에서는 충분하지만 nextJS와 같이 서버 사이드 렌더링을 지원하는 경우 사용자가 네트워크가 느린 환경에서 애플리케이션을 이용할 경우 스타일링이 적용되지 않은 레이아웃만을 볼 가능성이 있어요!
앞으로도 다양한 기술 스택 선정을 해보시면 좋을 것 같습니다.

},
"devDependencies": {
"@types/node": "^20.12.12",
"@types/react": "^18.2.66",
"@types/react-dom": "^18.2.22",
"@types/styled-components": "^5.1.34",
"@typescript-eslint/eslint-plugin": "^7.2.0",
"@typescript-eslint/parser": "^7.2.0",
"@vitejs/plugin-react": "^4.2.1",
"eslint": "^8.57.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.6",
"prettier": "^3.2.5",
"typescript": "^5.2.2",
"vite": "^5.2.0",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vite 번들러를 이용해서 리액트 프로젝트를 진행하셨네요. 기존의 cra은 내부적으로 webpack을 이용하여 번들링을 진행하는 반면에 vite는 esbuild라는 GO 언어를 통해 작성된 번들러를 개발환경에서, 배포환경에서는 rollup 을 이용해 HMR까지 지원하고 있다고 해요!
속도가 빠른 vite를 선택하신 점 좋아보여요! 다만 vite가 global 변수를 이용하려면 추가 설정을 해주어야 하고 webAPI의 사용이 일부 제한 된다는 점을 조심해서 사용하시면 좋을 것 같습니다.

"vite-plugin-svgr": "^4.2.0",
"vite-tsconfig-paths": "^4.3.2"
}
}
1 change: 1 addition & 0 deletions vote/public/vite.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions vote/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Suspense } from "react";
import { Router } from "router";
import { RouterProvider } from "react-router-dom";
import { ThemeProvider } from "styled-components";
import GlobalStyle from "@styles/globalStyle";
import theme from "@styles/theme";
import { QueryClient, QueryClientProvider } from "react-query";

const queryClient = new QueryClient();

function App() {
return (
<QueryClientProvider client={queryClient}>
<Suspense fallback="..loading">
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suspense가 제대로 동작..하고 있는건가요?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

음... Suspense 컴포넌트를 이용해서 데이터를 로딩 중일 때 대체 UI를 보여주려면 fallback 속성에는 컴포넌트가 들어와야 하는 것 아닌가요?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

그냥 "..loading" 텍스트가 뜨게끔 해두었습니다..

<ThemeProvider theme={theme}>
<RouterProvider router={Router} />
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

router를 사용해 훨씬 깔끔한 코드가 된 거 같아요.

<GlobalStyle />
</ThemeProvider>
</Suspense>
</QueryClientProvider>
);
}

export default App;
19 changes: 19 additions & 0 deletions vote/src/api/cookie.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Cookies } from "react-cookie";

const cookies = new Cookies();

export function setCookie(
name: string,
value: string | undefined,
options: object,
) {
return cookies.set(name, value, { ...options });
}

export function getCookie(name: string) {
return cookies.get(name);
}

export function removeCookie(name: string) {
return cookies.remove(name);
}
Comment on lines +5 to +19

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cookie에 여러 값들을 저장하고, 조회하고, 삭제하는 기능의 함수들을 만들어주셨네요! 다만 이는 백엔드 단의 로직에서 set-cookie 헤더를 통해 요청을 response로 받는 시점에 바로 넣어줄 수도 있어요. 뿐만 아니라 httpOnly 같은 속성을 이용하면 Javascript로 cookie에 접근하는 것도 막아줄 수 있고요!
document.cookie 처럼 JS를 통해 쿠키에 바로 접근할 수 있게 만든다면 보안적으로 이슈가 될 수도 있다고 생각합니다.

19 changes: 19 additions & 0 deletions vote/src/api/customAxios.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// import axios from "axios";

// export const customAxios = axios.create({
// baseURL: `${import.meta.env.VITE_APP_BASE_URL}`,
// headers: {
// "Content-Type": "application/json",
// "Access-Control-Allow-Origin": "*",
// },
// });

import axios, { AxiosInstance } from "axios";

export const customAxios: AxiosInstance = axios.create({
baseURL: `${import.meta.env.VITE_APP_BASE_URL}`,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 헤더는 preflight 요청 시에 본 요청에 대한 cors 이슈를 해결해주기 위해서 백엔드 단에서 진행하는 헤더 설정으로 알고 있어요! 프론트엔드의 출처(프로토콜 + 도메인 주소 + 포트번호)를 여기에 명시해주면, 해당 출처로부터의 요청은 브라우저가 막지 않게 되는 것이지요!

따라서 러비 팀에서 axios 인스턴스를 만들어 쓸때 필요한 설정이 아니라 백엔드에서 진행해야 하는 것으로 생각하는데, 이렇게 코드를 작성하신 이유가 따로 있나 궁금합니다.

},
});
24 changes: 24 additions & 0 deletions vote/src/api/getFinalResult.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { AxiosResponse } from "axios";
import { customAxios } from "./customAxios";

export interface ResponseTypes {
votingOptionCount: number;
votingOptionName: string;
votingOptionId: number;
}

interface GetFinalResultTypes {
success: boolean;
response: ResponseTypes[];
}

export async function getFinalResult(
topicID: number,
): Promise<ResponseTypes[]> {
const { data }: AxiosResponse<GetFinalResultTypes> = await customAxios.get(
`/api/topics/${topicID}/results`,
);

const { response } = data;
return response;
}
28 changes: 28 additions & 0 deletions vote/src/api/getTopicsById.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { AxiosResponse } from "axios";
import { customAxios } from "./customAxios";

export interface VotingOptionDtoTypes {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

src/api에 선언되어있는 type들은 types안으로 몰아주면 좋을 거 같아요!

id: number;
name: string;
}

export interface ResponseTypes {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getFinalResults.ts 파일에서도 동일한 이름의 인터페이스가 있는데, 좀더 semantic하게 작명하시면 좋을 것 같습니다.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 한 파일에 하나의 api 함수만 존재한다면 여기서 type 정의 후 사용해도 괜찮을 거 같아요~ 다만 어떤 api들에 대한 type은 분리되어 있어서 파트너 간 정한 규칙으로 일관성을 유지했다면 더 좋을 거 같네요. 그리고 승완님 말씀처럼 타입을 export 해서 다른 파일에서도 사용한다면 일반적인 네이밍보다는 특수한 네이밍이 나을 거 같아요. GetTopicByIdRes 이런 식으로요~

id: number;
name: string;
minimumVotesRequired: number;
votingOptionDto: VotingOptionDtoTypes[];
}

interface GetTopicsByIdTypes {
success: boolean;
response: ResponseTypes;
}

export async function getTopicsById(topicID: number): Promise<ResponseTypes> {
const { data }: AxiosResponse<GetTopicsByIdTypes> = await customAxios.get(
`/api/topics/${topicID}`,
);

const { response } = data;
return response;
}
23 changes: 23 additions & 0 deletions vote/src/api/getVotingOptionsById.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { AxiosResponse } from "axios";
import { customAxios } from "./customAxios";

export interface ResponseTypes {
id: number;
name: string;
voteCount: number;
}

interface GetVotingOptionsByIdTypes {
success: boolean;
response: ResponseTypes[];
}

export async function getVotingOptionsById(
topicID: number,
): Promise<ResponseTypes[]> {
const { data }: AxiosResponse<GetVotingOptionsByIdTypes> =
await customAxios.get(`/api/votingoptions/topics/${topicID}`);

const { response } = data;
return response;
}
11 changes: 11 additions & 0 deletions vote/src/api/postEmail.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { postEmailTypes } from "types/postEmailTypes";
import { customAxios } from "./customAxios";

export async function postEmail(props: postEmailTypes) {
const { email } = props;
const response = await customAxios.post("/api/users/verify", {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이메일 인증 방식까지 거치신 부분 너무 좋습니다 👍

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

맞아요 최고입니다....👍

email: email,
});

return response;
}
30 changes: 30 additions & 0 deletions vote/src/api/postSignIn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { postSignInTypes } from "types/postSignInTypes";
import { customAxios } from "./customAxios";
import { AxiosResponse } from "axios";

export interface SignInResponse {
accessToken: string;
refreshToken: string;
message: string;
}

interface FullResponse {
success: boolean;
response: SignInResponse;
success_or_error_code: {
status: number;
message: string;
};
}

export async function postSignIn(
props: postSignInTypes,
): Promise<AxiosResponse<FullResponse>> {
const { username, password } = props;
const response = await customAxios.post<FullResponse>("/api/users/login", {
username,
password,
});

return response;
}
17 changes: 17 additions & 0 deletions vote/src/api/postSignUp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { postSignUpTypes } from "types/postSignUpTypes";
import { customAxios } from "./customAxios";

export async function postSignUp(props: postSignUpTypes) {
const { username, password, email, part, team, name, role } = props;
const response = await customAxios.post("/api/users/signup", {
username: username,
password: password,
email: email,
part: part,
team: team,
role: role,
name: name,
});

return response;
}
12 changes: 12 additions & 0 deletions vote/src/api/postVote.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { postVoteTypes } from "types/postVoteTypes";
import { customAxios } from "./customAxios";

export async function postVote(props: postVoteTypes) {
const { topicId, votingOptionId } = props;
const response = await customAxios.post("/api/votes", {
topicId: topicId,
votingOptionId: votingOptionId,
});

return response?.data.data;
}
Loading