Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 10 additions & 0 deletions apps/client/src/app/apolloClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// src/apolloClient.ts

import { ApolloClient, InMemoryCache } from "@apollo/client";

const client = new ApolloClient({
uri: process.env.NEXT_PUBLIC_BACKEND_URL, // GraphQL API 엔드포인트
cache: new InMemoryCache(),
});

export default client;
102 changes: 80 additions & 22 deletions apps/client/src/app/component/votepage.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"use client";

import client from "../apolloClient";
import { useState, useEffect } from "react";

import Votemenu from "../votemenu/page";

import {
Container,
Card,
Expand All @@ -12,33 +12,91 @@ import {
DateText,
InfoWrapper,
TitleText,
MenuWrapper

MenuWrapper,
ALERDYTitleText,
ALERDYCard
} from "../style/votepage";

import { useQuery } from "@apollo/client";
import { GET_ALL_VOTES, HAS_VOTED } from "../queries";

export default function Votepage() {
const category = "재미질문";
const title = "학교에서 가장 무서운것은?";
const date = "2025-05-23";
const { loading: loadingVotes, error: errorVotes, data: dataVotes } = useQuery(GET_ALL_VOTES);
const [hasUserVotedResults, setHasUserVotedResults] = useState<boolean[]>([]);

// 비동기적으로 투표 여부를 확인하여 상태 업데이트
useEffect(() => {
if (dataVotes?.vote?.getAllVotes?.length) {
const fetchVoteStatuses = async () => {
const results: boolean[] = [];
for (const vote of dataVotes.vote.getAllVotes) {
if (vote?.id) {
try {
const response = await client.query({
query: HAS_VOTED,
variables: {
votedId: vote.id,
},
});
results.push(response.data.voteResponse.hasUserVoted);
} catch (error) {


}
} else {
console.warn(`Invalid vote object detected:`, vote);
// 유효하지 않은 객체에 기본 값 추가
}
}
setHasUserVotedResults(results); // 모든 결과를 한 번에 상태 업데이트
};

fetchVoteStatuses();
}
}, [dataVotes]);

if (loadingVotes) return <p>로딩 중...</p>;
if (errorVotes) return <p>에러 발생: {errorVotes.message}</p>;
if (!dataVotes?.vote?.getAllVotes) return <p>투표 데이터 없음</p>;




return (
<Container>
<Card>
<InfoWrapper>
<CategoryText>{category}</CategoryText>
<TitleWrapper>
<TitleText>{title}</TitleText>
<DateWrapper>
<DateText>{date} 투표마감</DateText>
</DateWrapper>
</TitleWrapper>
</InfoWrapper>
</Card>

<MenuWrapper>
<Votemenu />
</MenuWrapper>
{dataVotes.vote.getAllVotes.map((vote: any, i: number) => (
hasUserVotedResults[i++] === false ? (
// 투표하지 않은 경우
<div key={vote.id}>
<Card>
<InfoWrapper>
<CategoryText>{vote.category}</CategoryText>
<TitleWrapper>
<TitleText>{vote.title}</TitleText>
<DateWrapper>
<DateText>{vote.finishedAt} 투표마감</DateText>
</DateWrapper>
</TitleWrapper>
</InfoWrapper>
</Card>

<MenuWrapper>
<Votemenu
options={Array.isArray(vote.options) ? vote.options : []}
voteid={vote.id}
votefihishedAt={vote.finishedAt}
/>
</MenuWrapper>
</div>
) : (
// 이미 투표한 경우
<div key={vote.id}>
<ALERDYCard>
<ALERDYTitleText>이미 투표를 완료했습니다.</ALERDYTitleText>
</ALERDYCard>
</div>
)
))}
</Container>
);
}
3 changes: 3 additions & 0 deletions apps/client/src/app/images/arrow4.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions apps/client/src/app/images/arrow5.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 14 additions & 0 deletions apps/client/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

import "./globals.css";
import Sidebar from "./component/sidebar";
import {
ApolloClient,
InMemoryCache,
ApolloProvider as Provider,
} from '@apollo/client';


const client = new ApolloClient({
uri: process.env.NEXT_PUBLIC_BACKEND_URL,
cache: new InMemoryCache(),
});


export default function RootLayout({
children,
Expand All @@ -11,6 +23,7 @@ export default function RootLayout({
return (
<html lang="en">
<body>
<Provider client={client}>
<div className="flex flex-row">
<div className="fixed">
<Sidebar />
Expand All @@ -20,6 +33,7 @@ export default function RootLayout({
{children}
</div>
</div>
</Provider>
</body>
</html>
);
Expand Down
27 changes: 27 additions & 0 deletions apps/client/src/app/mutations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { gql } from '@apollo/client';
export const POST_VOTE = gql`
mutation MyMutation($title: String!, $category: String!, $options: [String!]!) {
vote {
createVote(input: { title: $title, category: $category, options: $options }) {
id
}
}
}
`;


export const POST_VOTERESUlT = gql`
mutation MyMutation($voteId : ID!,$optionId : ID!) {
voteResponse {
createVoteResponse(input: {voteId: $voteId, optionId: $optionId}) {
id
optionContent
optionId
userId
voteTitle
voteId
createdAt
}
}
}
`;
20 changes: 18 additions & 2 deletions apps/client/src/app/mypage/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import React from "react";
import arrow from "@/app/images/arrow3.svg";
import { useRouter } from "next/navigation";
import {
Container,
Title,
Expand All @@ -22,7 +23,22 @@ import {
const name = "1134박기주";
const email = "[email protected]";



export default function Mypage() {

const router = useRouter() ;


function Goreport(){
router.push("/report");
}

function Gomyvote(){
router.push("/myvote");
}


return (
<Container>
<Title>마이페이지</Title>
Expand All @@ -35,7 +51,7 @@ export default function Mypage() {
</NameForm>
<ButtonForm>
<Button>
<ButtonContent>
<ButtonContent onClick={() => Gomyvote()}>
<ButtonSection>
<Buttonp>내가쓴 투표조회</Buttonp>
<StyledArrowImage src={arrow} alt="checkimg" width={30} height={30}/>
Expand All @@ -44,7 +60,7 @@ export default function Mypage() {
</ButtonContent>
</Button>
<Button>
<ButtonContent>
<ButtonContent onClick={() => Goreport()}>
<ButtonSection>
<Buttonp>신고조회</Buttonp>
<StyledArrowImage src={arrow} alt="checkimg" width={30} height={30}/>
Expand Down
113 changes: 113 additions & 0 deletions apps/client/src/app/myvote/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
"use client";

import React, { useState } from "react";
import arrow from "@/app/images/arrow4.svg";
import Image from "next/image";
import { useRouter } from "next/navigation";


import {
Container,
Title,
Sub,
ContentBox,
ListBox,
ListItem,
ListItemInner,
ListTitle,
ListInfo,
} from "../style/myvote";

const name = "1134박기주";
const email = "[email protected]";

type Post = {
id: string;
title: string;
writer: string;
date: string;
content: string;
};

const posts: Post[] = [
{
id: "001",
title: "차수민쌤이랑 데이트 박제현쌤이랑 데이트",
writer: "오주현",
date: "2025.06.22",
content: "부산소프트웨어 마이스터고등학교는 총 64명이 한 학년에 있으며 곽상미 선생님이 참 귀여우시다 ㅎㅎ 그리고 짜장이가 참귀엽다 진짜 카와이하다 뽀뽀하고싶다,,ㅠㅠ"
},
{
id: "002",
title: "오늘 점심 뭐 먹지?",
writer: "김예은",
date: "2025.06.21",
content: "오늘 점심은 김치볶음밥 먹을까? 아니면 짜장면?"
},
{
id: "003",
title: "React 훅 정리 노트 공유합니다!",
writer: "이정환",
date: "2025.06.20",
content: "useState, useEffect, useMemo 등 정리해둔 노트 공유할게요."
},
{
id: "004",
title: "Next.js 서버 컴포넌트 사용기",
writer: "정은지",
date: "2025.06.19",
content: "서버 컴포넌트를 사용해서 SSR 성능이 향상됨."
},
{
id: "005",
title: "스타벅스 쿠폰 나눔해요~",
writer: "박지민",
date: "2025.06.18",
content: "쿠폰 유효기간 7월 15일까지! 필요하신 분 댓글 주세요~"
}
];



export default function Mypage() {
const [selectedPost, setSelectedPost] = useState<Post | null>(null);
const router = useRouter() ;

function gotoback(){
router.push("/mypage")
}

return (
<Container>
<div className="flex items-center gap-[3vh]">
<Image src={arrow} alt="arrow" className="relative top-[-1vh]" onClick={gotoback}/>
<Title>마이페이지</Title>
</div>
<Sub>내가 쓴 투표 게시물</Sub>
<ContentBox>
<ListBox>
{posts.map((post) => (
<ListItem
key={post.id}
onClick={() =>
selectedPost?.id === post.id
? setSelectedPost(null)
: setSelectedPost(post)
}
selected={selectedPost?.id === post.id}
>
<ListItemInner>
<ListTitle>{post.title}</ListTitle>
<ListInfo>
<p>{post.writer}</p>
<p>{post.date}</p>
<p>{post.id}</p>
</ListInfo>
</ListItemInner>
</ListItem>
))}
</ListBox>
</ContentBox>
</Container>
);
}
Loading
Loading