Skip to content

Commit

Permalink
[소켓모듈] 소켓 연결, 실시간 입장 화면
Browse files Browse the repository at this point in the history
🚀 feat: 소켓 연결, 실시간 입장 화면 #16
  • Loading branch information
ImNM authored Aug 7, 2022
2 parents b11eb15 + deb934b commit 4e0c550
Show file tree
Hide file tree
Showing 11 changed files with 3,984 additions and 5,271 deletions.
8,964 changes: 3,695 additions & 5,269 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@ant-design/icons": "^4.7.0",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^13.5.0",
"add": "^2.0.6",
"antd": "^4.21.6",
"axios": "^0.27.2",
"moment": "^2.29.4",
Expand All @@ -16,6 +18,9 @@
"react-scripts": "5.0.1",
"redux": "^4.2.0",
"redux-thunk": "^2.4.1",
"socket.io": "^4.5.1",
"socket.io-client": "^4.5.1",
"styled-components": "^5.3.5",
"web-vitals": "^2.1.4"
},
"scripts": {
Expand Down
77 changes: 77 additions & 0 deletions src/components/Tickets/EnterPage/EnterList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { CheckCircleOutlined, CloseCircleOutlined } from '@ant-design/icons';
import { Avatar, List, Tag, Col, Row } from 'antd';
import moment from 'moment';
import VirtualList from 'rc-virtual-list';
import React from 'react';
import { useSelector } from 'react-redux';
import RecentEnter from './RecentEnter';

const ContainerHeight = 800;

function EnterList() {
const { ticketList } = useSelector(state => state.enterPage);

const onScroll = e => {
if (
e.currentTarget.scrollHeight - e.currentTarget.scrollTop ===
ContainerHeight
) {
}
};

return (
<>
<div className="site-card-wrapper">
<Row gutter={16}>
<Col span={8}>
<div>
<RecentEnter />
</div>
</Col>
<Col span={16}>
<List>
<VirtualList
data={ticketList}
height={ContainerHeight}
itemHeight={47}
itemKey="email"
onScroll={onScroll}
>
{item => (
<List.Item key={item.ticketData.uuid}>
<List.Item.Meta
avatar={
<Avatar
style={{
backgroundColor: '#a5a6a8'
}}
>
{item.ticketData.name}
</Avatar>
}
title={`${moment(item.enterTime)
.utc(true)
.format('HH:mm')} ${item.ticketData.name}`}
description={`[${item.ticketData.date}] ${item.ticketData.uuid}, ${item.ticketData.phoneNumber}`}
/>
{item.ticketData.success === true ? (
<Tag icon={<CheckCircleOutlined />} color="#89cc8a">
입장완료
</Tag>
) : (
<Tag icon={<CloseCircleOutlined />} color="#cc8989">
입장실패
</Tag>
)}
</List.Item>
)}
</VirtualList>
</List>
</Col>
</Row>
</div>
</>
);
}

export default EnterList;
11 changes: 9 additions & 2 deletions src/components/Tickets/EnterPage/EnterPage.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import React from "react";
import React from 'react';
import EnterList from './EnterList';
import SocketConnect from './SocketConnect';

function EnterPage() {
return <div>EnterPage</div>;
return (
<div>
<SocketConnect />
<EnterList />
</div>
);
}

export default EnterPage;
73 changes: 73 additions & 0 deletions src/components/Tickets/EnterPage/RecentEnter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import {
CheckCircleOutlined,
CloseCircleOutlined,
LoadingOutlined
} from '@ant-design/icons';
import { Card, Tag, Space } from 'antd';
import moment from 'moment';
import React from 'react';
import { useSelector } from 'react-redux';
import styled from 'styled-components';

styled(Card)`
display: flex;
height: 100%;
justify-content: center;
position: relative;
`;

function RecentEnter() {
const { enterData } = useSelector(state => state.enterPage);

return (
<>
{enterData.ticketData ? (
<div>
<div>
<Card
title={`${enterData.ticketData.name}`}
bordered={false}
style={{
textAlign: 'center'
}}
>
{enterData.ticketData.success === true ? (
<Tag icon={<CheckCircleOutlined />} color="#89cc8a">
입장완료
</Tag>
) : (
<Tag icon={<CloseCircleOutlined />} color="#cc8989">
입장실패
</Tag>
)}
<br /> <br />
<p>
입장시간:{' '}
{moment(enterData.enterTime).utc(true).format('HH:mm')}
</p>
<p>전화번호: {enterData.ticketData.phoneNumber}</p>
<p>공연날짜: {enterData.ticketData.date}</p>
<p>uuid: {enterData.ticketData.uuid}</p>
</Card>
</div>
</div>
) : (
<div>
<Card
title="입장 대기 중"
bordered={false}
style={{
textAlign: 'center'
}}
>
<Space>
<LoadingOutlined />
</Space>
</Card>
</div>
)}
</>
);
}

export default RecentEnter;
48 changes: 48 additions & 0 deletions src/components/Tickets/EnterPage/SocketConnect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { io } from 'socket.io-client';
import { enterPage } from '../../../state/actions-creators/enterPage';

function SocketConnect() {
const dispatch = useDispatch();
const { accessToken } = useSelector(state => state.auth);
const { ticketData, ticketList } = useSelector(state => state.enterPage);

console.log('accessToken', accessToken);

const socket = io('https://api.gosrock.band/socket/admin', {
auth: {
token: accessToken
}
});

useEffect(() => {
socket.on('connect', data => {
console.log('connection server', data);
});
socket.on('enter', data => {
console.log('enter', data);
dispatch(
enterPage({
data: data,
enterTime: new Date()
})
);
});

console.log('ticketData', ticketData);
console.log('ticketList', ticketList);

return () => {
socket.close();
};
}, [dispatch, ticketData]);

socket.on('connect_error', err => {
console.log(err instanceof Error); // true
console.log(err.message); // not authorized
console.log(err.data); // { content: "Please retry later" }
});
}

export default SocketConnect;
3 changes: 3 additions & 0 deletions src/state/action-types/enterPage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const ENTER_PAGE_PENDING = 'ENTER_PAGE_PENDING';
export const ENTER_PAGE_SUCCESS = 'ENTER_PAGE_SUCCESS';
export const ENTER_PAGE_ERROR = 'ENTER_PAGE_ERROR';
1 change: 1 addition & 0 deletions src/state/action-types/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export * from './logout';
export * from './examplePagination';
export * from './ticketPagination';
export * from './usersPage';
export * from './enterPage';
export * from './LandingPage';
24 changes: 24 additions & 0 deletions src/state/actions-creators/enterPage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {
ENTER_PAGE_PENDING,
ENTER_PAGE_SUCCESS,
ENTER_PAGE_ERROR
} from '../action-types';

export const enterPage =
({ data, enterTime }, callback) =>
async dispatch => {
try {
dispatch({ type: ENTER_PAGE_PENDING });

const enterData = {
ticketData: data,
enterTime: enterTime
};

dispatch({ type: ENTER_PAGE_SUCCESS, payload: enterData });

console.log('enterPage data', data);
} catch (e) {
dispatch({ type: ENTER_PAGE_ERROR, payload: '입장실패' });
}
};
47 changes: 47 additions & 0 deletions src/state/reducers/enterPage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import {
ENTER_PAGE_PENDING,
ENTER_PAGE_SUCCESS,
ENTER_PAGE_ERROR
} from '../action-types';

// eslint-disable-next-line import/no-anonymous-default-export
export default function (
state = {
enterData: {
ticketData: null,
enterTime: null
},
ticketList: [],
pending: false,
errorMessage: null
},
action
) {
switch (action.type) {
case ENTER_PAGE_PENDING:
return {
...state,
enterData: action.payload,
error: null,
pending: true
};
case ENTER_PAGE_SUCCESS:
return {
...state,
enterData: action.payload,
ticketList: state.ticketList.concat(action.payload),
error: null,
pending: false
};
case ENTER_PAGE_ERROR:
return {
...state,
enterData: null,
error: action.payload,
pending: false
};

default:
return state;
}
}
2 changes: 2 additions & 0 deletions src/state/reducers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import ticketPagination from './ticketPagination';
import LandingPage from './LandingPage';
import slackMessage from './slackMessage';
import usersPage from './usersPage';
import enterPage from './enterPage';

export default combineReducers({
slackMessage: slackMessage,
auth: auth,
examplePagination: examplePagination,
usersPage: usersPage,
ticketPagination: ticketPagination,
enterPage: enterPage,
LandingPage: LandingPage
});

0 comments on commit 4e0c550

Please sign in to comment.