Skip to content

Commit 4408dbc

Browse files
committed
그룹 내 투표 조회 구현
1 parent 92b09fe commit 4408dbc

File tree

6 files changed

+150
-93
lines changed

6 files changed

+150
-93
lines changed

polling-app-client/src/app/App.js

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import HomeDashboard from '../components/Dashboard/HomeDashboard';
2-
2+
import GroupPollList from '../components/Dashboard/GroupPollList';
33
import React, { Component } from 'react';
44
import './App.css';
55
import {
@@ -121,7 +121,12 @@ class App extends Component {
121121
render={(props) => <Profile isAuthenticated={this.state.isAuthenticated} currentUser={this.state.currentUser} {...props} />}>
122122
</Route>
123123
<PrivateRoute authenticated={this.state.isAuthenticated} path="/poll/new" component={NewPoll} handleLogout={this.handleLogout}></PrivateRoute>
124-
<Route component={NotFound}></Route>
124+
<PrivateRoute
125+
path="/groups/:groupId/polls"
126+
component={GroupPollList}
127+
authenticated={this.state.isAuthenticated}
128+
/> <Route component={NotFound}></Route>
129+
125130
</Switch>
126131
</div>
127132
</Content>
Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,22 @@
11
import React from 'react';
2-
import {
3-
Route,
4-
Redirect
5-
} from "react-router-dom";
6-
7-
8-
const PrivateRoute = ({ component: Component, authenticated, ...rest }) => (
9-
<Route
10-
{...rest}
11-
render={props =>
12-
authenticated ? (
13-
<Component {...rest} {...props} />
14-
) : (
15-
<Redirect
16-
to={{
17-
pathname: '/login',
18-
state: { from: props.location }
19-
}}
20-
/>
21-
)
22-
}
23-
/>
2+
import { Route, Redirect } from "react-router-dom";
3+
4+
const PrivateRoute = ({ component: Component, render, authenticated, ...rest }) => (
5+
<Route
6+
{...rest}
7+
render={props =>
8+
authenticated ? (
9+
render ? render(props) : <Component {...props} />
10+
) : (
11+
<Redirect
12+
to={{
13+
pathname: '/login',
14+
state: { from: props.location }
15+
}}
16+
/>
17+
)
18+
}
19+
/>
2420
);
25-
26-
export default PrivateRoute
21+
22+
export default PrivateRoute;
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import React, { Component } from 'react';
2+
import { getPollsByGroupId, castVote } from '../../util/APIUtils';
3+
import Poll from '../../poll/Poll';
4+
import LoadingIndicator from '../../common/LoadingIndicator';
5+
import { notification } from 'antd';
6+
7+
class GroupPollList extends Component {
8+
constructor(props) {
9+
super(props);
10+
this.state = {
11+
polls: [],
12+
currentVotes: [],
13+
isLoading: false
14+
};
15+
}
16+
17+
componentDidMount() {
18+
const groupId = this.props.match.params.groupId;
19+
this.setState({ isLoading: true });
20+
getPollsByGroupId(groupId)
21+
.then(response => {
22+
this.setState({
23+
polls: response.content, // ✅ content만 꺼내기
24+
currentVotes: Array(response.content.length).fill(null),
25+
isLoading: false
26+
});
27+
})
28+
.catch(error => {
29+
console.error("Error fetching polls:", error);
30+
this.setState({ isLoading: false });
31+
});
32+
}
33+
34+
handleVoteChange = (event, index) => {
35+
const newVotes = [...this.state.currentVotes];
36+
newVotes[index] = event.target.value;
37+
this.setState({ currentVotes: newVotes });
38+
};
39+
40+
handleVoteSubmit = (event, index) => {
41+
event.preventDefault();
42+
if (!this.props.isAuthenticated) {
43+
this.props.history.push("/login");
44+
notification.info({ message: 'Polling App', description: 'Please login to vote.' });
45+
return;
46+
}
47+
48+
const voteData = {
49+
pollId: this.state.polls[index].id,
50+
choiceId: this.state.currentVotes[index]
51+
};
52+
53+
castVote(voteData)
54+
.then(response => {
55+
const updated = [...this.state.polls];
56+
updated[index] = response;
57+
this.setState({ polls: updated });
58+
})
59+
.catch(error => {
60+
if (error.status === 401) {
61+
this.props.handleLogout('/login', 'error', 'You have been logged out.');
62+
} else {
63+
notification.error({ message: 'Polling App', description: error.message });
64+
}
65+
});
66+
};
67+
68+
render() {
69+
const { polls, isLoading, currentVotes } = this.state;
70+
71+
return (
72+
<div className="polls-container">
73+
{polls.map((poll, index) => (
74+
<Poll
75+
key={poll.id}
76+
poll={poll}
77+
currentVote={currentVotes[index]}
78+
handleVoteChange={e => this.handleVoteChange(e, index)}
79+
handleVoteSubmit={e => this.handleVoteSubmit(e, index)}
80+
/>
81+
))}
82+
{!isLoading && polls.length === 0 && <div>No Polls Found.</div>}
83+
{isLoading && <LoadingIndicator />}
84+
</div>
85+
);
86+
}
87+
}
88+
89+
export default GroupPollList;

polling-app-client/src/components/MyGroups/MyGroupSlider.jsx

Lines changed: 0 additions & 52 deletions
This file was deleted.

polling-app-client/src/components/MyGroups/MyGroups.jsx

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import React, { Component } from "react";
22
import "./MyGroups.css";
3+
import { withRouter } from 'react-router-dom';
34
import { getMyGroups } from '../../util/APIUtils';
5+
import "slick-carousel/slick/slick.css";
6+
import "slick-carousel/slick/slick-theme.css";
47

58

69
class MyGroups extends Component {
@@ -25,8 +28,13 @@ class MyGroups extends Component {
2528

2629
}
2730

31+
handleGroupClick = (groupId) => {
32+
this.props.history.push(`/groups/${groupId}/polls`);
33+
};
34+
2835
render() {
2936
const { groups, loading, error } = this.state;
37+
3038

3139
return (
3240
<div className="my-groups-container">
@@ -38,24 +46,28 @@ class MyGroups extends Component {
3846
) : groups.length === 0 ? (
3947
<p>참여한 그룹이 없습니다.</p>
4048
) : (
41-
<div className="group-card-list">
49+
<div className="group-list">
4250
{groups.map((group) => (
43-
<div key={group.id} className="group-card">
44-
<div className="group-avatar">
45-
<img src={group.imageUrl} alt="Group Avatar" />
51+
<div key={group.id}>
52+
<div className="group-card"
53+
onClick={() => this.handleGroupClick(group.id)}
54+
style={{ cursor: "pointer" }}>
55+
<div className="group-avatar">
56+
<img src={group.imageUrl} alt="Group Avatar" />
57+
</div>
58+
<div className="group-info">
59+
<div className="group-name">{group.name}</div>
60+
<div className="group-count">
61+
멤버 {group.memberCount != null ? group.memberCount : 0}
4662
</div>
47-
48-
<div className="group-info">
49-
<div className="group-name">{group.name}</div>
50-
<div className="group-count">멤버 {group.memberCount}</div>
51-
</div>
52-
</div>
53-
))}
54-
</div>
63+
</div>
64+
</div>
65+
</div>
66+
))}
67+
</div>
5568
)}
5669
</div>
5770
);
5871
}
5972
}
60-
61-
export default MyGroups;
73+
export default withRouter(MyGroups);

polling-app-client/src/util/APIUtils.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,4 +152,11 @@ export function joinGroupByCode(joinCode) {
152152
method: "POST",
153153
body: JSON.stringify({ joinCode: String(joinCode) }) // ✅ 필드 이름 수정
154154
});
155-
}
155+
}
156+
157+
export function getPollsByGroupId(groupId) {
158+
return request({
159+
url: API_BASE_URL + `/groups/${groupId}/polls`,
160+
method: 'GET'
161+
});
162+
}

0 commit comments

Comments
 (0)