init
3
.env.dev
Normal file
@@ -0,0 +1,3 @@
|
||||
# .env stage
|
||||
REACT_APP_API_URL=http://10.20.20.23:8080
|
||||
REACT_APP_ENV=dev
|
||||
3
.env.live
Normal file
@@ -0,0 +1,3 @@
|
||||
# .env live
|
||||
REACT_APP_API_URL=http://live-admintool.caliverse.io:8080
|
||||
REACT_APP_ENV=live
|
||||
3
.env.qa
Normal file
@@ -0,0 +1,3 @@
|
||||
# .env stage
|
||||
REACT_APP_API_URL=http://qa-admintool.caliverse.io:8080
|
||||
REACT_APP_ENV=qa
|
||||
3
.env.stage
Normal file
@@ -0,0 +1,3 @@
|
||||
# .env stage
|
||||
REACT_APP_API_URL=http://stage-admintool.caliverse.io:8080
|
||||
REACT_APP_ENV=stage
|
||||
34
.gitignore
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.env.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
#.env
|
||||
.env
|
||||
/.idea/codeStyles/codeStyleConfig.xml
|
||||
/.idea/codeStyles/Project.xml
|
||||
/.idea/inspectionProfiles/Project_Default.xml
|
||||
/.idea/.gitignore
|
||||
/.idea/backofficefront.iml
|
||||
/.idea/misc.xml
|
||||
/.idea/modules.xml
|
||||
/.idea/vcs.xml
|
||||
39
.gitlab-ci.yml
Normal file
@@ -0,0 +1,39 @@
|
||||
stages:
|
||||
- build
|
||||
- notify
|
||||
before_script:
|
||||
- apt-get update -qq && apt-get install
|
||||
|
||||
Build:
|
||||
stage: build
|
||||
cache:
|
||||
paths:
|
||||
- node_modules/
|
||||
- .yarn/
|
||||
policy: pull-push
|
||||
tags:
|
||||
- backoffice-front
|
||||
before_script:
|
||||
- export REACT_APP_API_URL="$REACT_APP_API_URL"
|
||||
- env
|
||||
- yarn config set cache-folder .yarn
|
||||
- yarn install
|
||||
|
||||
script:
|
||||
- pwd
|
||||
- git config --global credential.helper cache
|
||||
- git clone http://ci.cd_account:glpat-xmZekX15LbLQQdfYG2xD@44.227.18.113/ngle.dev/backofficefront.git
|
||||
- CI='' yarn build
|
||||
- rm -rf /application/backofficefront/build
|
||||
- mv build/ /application/backofficefront/
|
||||
- ls -al /application/backofficefront/
|
||||
|
||||
artifacts:
|
||||
name: build
|
||||
when: on_success
|
||||
expire_in: 1 week
|
||||
paths:
|
||||
- build
|
||||
|
||||
only:
|
||||
- dev
|
||||
12
.prettierrc.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"printWidth": 200,
|
||||
"tabWidth": 4,
|
||||
"useTabs": true,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all",
|
||||
"bracketSpacing": true,
|
||||
"jsxBracketSameLine": true,
|
||||
"arrowParens": "avoid",
|
||||
"endOfLine": "auto"
|
||||
}
|
||||
15
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
// IntelliSense를 사용하여 가능한 특성에 대해 알아보세요.
|
||||
// 기존 특성에 대한 설명을 보려면 가리킵니다.
|
||||
// 자세한 내용을 보려면 https://go.microsoft.com/fwlink/?linkid=830387을(를) 방문하세요.
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"name": "localhost에 대해 Chrome 시작",
|
||||
"url": "http://localhost:3000",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
}
|
||||
16
Dockerfile.dev
Normal file
@@ -0,0 +1,16 @@
|
||||
FROM node:20.11.0 as build
|
||||
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm install
|
||||
COPY . .
|
||||
RUN npm run build:dev
|
||||
|
||||
FROM nginx:alpine
|
||||
COPY nginx_dev.conf /etc/nginx/conf.d/default.conf
|
||||
COPY --from=build /app/build /usr/share/nginx/admintool
|
||||
|
||||
# port 8080
|
||||
EXPOSE 8080
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
16
Dockerfile.live
Normal file
@@ -0,0 +1,16 @@
|
||||
FROM node:20.11.0 as build
|
||||
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm install
|
||||
COPY . .
|
||||
RUN npm run build:live
|
||||
|
||||
FROM nginx:alpine
|
||||
COPY nginx_live.conf /etc/nginx/conf.d/default.conf
|
||||
COPY --from=build /app/build /usr/share/nginx/admintool
|
||||
|
||||
# port 8080
|
||||
EXPOSE 8080
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
16
Dockerfile.qa
Normal file
@@ -0,0 +1,16 @@
|
||||
FROM node:20.11.0 as build
|
||||
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm install
|
||||
COPY . .
|
||||
RUN npm run build:qa
|
||||
|
||||
FROM nginx:alpine
|
||||
COPY nginx_qa.conf /etc/nginx/conf.d/default.conf
|
||||
COPY --from=build /app/build /usr/share/nginx/admintool
|
||||
|
||||
# port 8080
|
||||
EXPOSE 8080
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
16
Dockerfile.stage
Normal file
@@ -0,0 +1,16 @@
|
||||
FROM node:20.11.0 as build
|
||||
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
RUN npm install
|
||||
COPY . .
|
||||
RUN npm run build:stage
|
||||
|
||||
FROM nginx:alpine
|
||||
COPY nginx_stage.conf /etc/nginx/conf.d/default.conf
|
||||
COPY --from=build /app/build /usr/share/nginx/admintool
|
||||
|
||||
# port 8080
|
||||
EXPOSE 8080
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
34
Jenkinsfile.dev
Normal file
@@ -0,0 +1,34 @@
|
||||
pipeline {
|
||||
agent any
|
||||
|
||||
environment {
|
||||
DOCKER_IMAGE = "caliverse/admintool-front-dev"
|
||||
DOCKER_TAG = "1.0.0"
|
||||
DOCKER_TAG_PRE = "1.0.0"
|
||||
FILE_NAME = 'admintool_front-dev.tar'
|
||||
DOCKER_NAME = 'admintool-front-dev'
|
||||
DOCKER_PORT = '8080'
|
||||
DOCKERFILE_NAME = 'Dockerfile.dev'
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Docker Build & Deploy') {
|
||||
steps {
|
||||
sh 'docker stop $DOCKER_NAME || true'
|
||||
sh 'docker rm $DOCKER_NAME || true'
|
||||
sh 'docker rmi $DOCKER_IMAGE:$DOCKER_TAG_PRE || true' //이전 이미지 삭제
|
||||
sh 'docker rmi $DOCKER_IMAGE:$DOCKER_TAG || true'
|
||||
echo 'Docker Image Create'
|
||||
sh 'docker build -f $DOCKERFILE_NAME -t $DOCKER_IMAGE:$DOCKER_TAG .' //Dockerfile 기준으로 이미지 생성
|
||||
sh 'docker run -d \
|
||||
-p $DOCKER_PORT:$DOCKER_PORT\
|
||||
--name $DOCKER_NAME \
|
||||
--restart=always \
|
||||
-v /home/admintool/admintool-front/log:/var/log/nginx \
|
||||
-e TZ=\${TZ:-Asia/Seoul} \
|
||||
$DOCKER_IMAGE:$DOCKER_TAG'
|
||||
echo 'Docker Container Create Complete'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
88
Jenkinsfile.live
Normal file
@@ -0,0 +1,88 @@
|
||||
pipeline {
|
||||
agent any
|
||||
|
||||
environment {
|
||||
DOCKER_IMAGE = "caliverse/admintool-front-live"
|
||||
DOCKER_TAG = "1.0.0"
|
||||
DOCKER_TAG_PRE = "1.0.0"
|
||||
FILE_NAME = 'admintool_front_live.tar'
|
||||
DOCKER_NAME = 'admintool-front-live'
|
||||
DOCKER_PORT = '8080'
|
||||
DOCKERFILE_NAME = 'Dockerfile.live'
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Docker Build') {
|
||||
steps {
|
||||
sh 'docker rmi $DOCKER_IMAGE:$DOCKER_TAG_PRE || true' //이전 이미지 삭제
|
||||
sh 'docker build -f $DOCKERFILE_NAME -t $DOCKER_IMAGE:$DOCKER_TAG .' //Dockerfile 기준으로 이미지 생성
|
||||
echo 'Docker Image Create'
|
||||
sh 'docker save -o $FILE_NAME $DOCKER_IMAGE:$DOCKER_TAG' //이미지 .tar 로 생성
|
||||
echo 'Docker Image > .tar File Create'
|
||||
script {
|
||||
def todayDate = sh(script: "date +%Y-%m-%d", returnStdout: true).trim()
|
||||
def fileName = "${FILE_NAME}_${todayDate}.tar"
|
||||
sh "cp ${FILE_NAME} ${fileName}" // 이름 변경
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Transfer Docker Image') {
|
||||
steps {
|
||||
// aws .tar transfer
|
||||
sshPublisher(
|
||||
publishers: [
|
||||
sshPublisherDesc(
|
||||
configName: 'live-frontend',
|
||||
transfers: [
|
||||
sshTransfer(
|
||||
sourceFiles: "${FILE_NAME}",
|
||||
remoteDirectory: '',
|
||||
execCommand: """
|
||||
echo '.tar Transfer Complete'
|
||||
""",
|
||||
execTimeout: 120000
|
||||
)
|
||||
],
|
||||
usePromotionTimestamp: false,
|
||||
verbose: true
|
||||
)
|
||||
]
|
||||
)
|
||||
}
|
||||
}
|
||||
stage('Deploy to Remote'){
|
||||
steps{
|
||||
// aws command
|
||||
sshPublisher(
|
||||
publishers: [
|
||||
sshPublisherDesc(
|
||||
configName: 'live-frontend',
|
||||
transfers: [
|
||||
sshTransfer(
|
||||
execCommand: """
|
||||
docker stop ${DOCKER_NAME} || true &&
|
||||
docker rm ${DOCKER_NAME} || true &&
|
||||
docker rmi ${DOCKER_IMAGE}:${DOCKER_TAG_PRE} || true &&
|
||||
docker load -i ${FILE_NAME} &&
|
||||
docker run -d \
|
||||
-p ${DOCKER_PORT}:${DOCKER_PORT} \
|
||||
--name ${DOCKER_NAME} \
|
||||
--restart=always \
|
||||
-v ./admintool/log:/var/log/nginx \
|
||||
-e TZ=\${TZ:-Asia/Seoul} \
|
||||
${DOCKER_IMAGE}:${DOCKER_TAG} &&
|
||||
rm ${FILE_NAME}
|
||||
echo 'Docker Container Create Complete'
|
||||
""",
|
||||
execTimeout: 120000
|
||||
)
|
||||
],
|
||||
usePromotionTimestamp: false,
|
||||
verbose: true
|
||||
)
|
||||
]
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
83
Jenkinsfile.qa
Normal file
@@ -0,0 +1,83 @@
|
||||
pipeline {
|
||||
agent any
|
||||
|
||||
environment {
|
||||
DOCKER_IMAGE = "caliverse/admintool-front-qa"
|
||||
DOCKER_TAG = "1.0.0"
|
||||
DOCKER_TAG_PRE = "1.0.0"
|
||||
FILE_NAME = 'admintool_front-qa.tar'
|
||||
DOCKER_NAME = 'admintool-front-qa'
|
||||
DOCKER_PORT = '8080'
|
||||
DOCKERFILE_NAME = 'Dockerfile.qa'
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Docker Build') {
|
||||
steps {
|
||||
sh 'docker rmi $DOCKER_IMAGE:$DOCKER_TAG_PRE || true' //이전 이미지 삭제
|
||||
sh 'docker build -f $DOCKERFILE_NAME -t $DOCKER_IMAGE:$DOCKER_TAG .' //Dockerfile 기준으로 이미지 생성
|
||||
echo 'Docker Image Create'
|
||||
sh 'docker save -o $FILE_NAME $DOCKER_IMAGE:$DOCKER_TAG' //이미지 .tar 로 생성
|
||||
echo 'Docker Image > .tar File Create'
|
||||
}
|
||||
}
|
||||
stage('Transfer Docker Image') {
|
||||
steps {
|
||||
// aws .tar transfer
|
||||
sshPublisher(
|
||||
publishers: [
|
||||
sshPublisherDesc(
|
||||
configName: 'qa-frontend',
|
||||
transfers: [
|
||||
sshTransfer(
|
||||
sourceFiles: "${FILE_NAME}",
|
||||
remoteDirectory: '',
|
||||
execCommand: """
|
||||
echo '.tar Transfer Complete'
|
||||
""",
|
||||
execTimeout: 120000
|
||||
)
|
||||
],
|
||||
usePromotionTimestamp: false,
|
||||
verbose: true
|
||||
)
|
||||
]
|
||||
)
|
||||
}
|
||||
}
|
||||
stage('Deploy to Remote'){
|
||||
steps{
|
||||
// aws command
|
||||
sshPublisher(
|
||||
publishers: [
|
||||
sshPublisherDesc(
|
||||
configName: 'qa-frontend',
|
||||
transfers: [
|
||||
sshTransfer(
|
||||
execCommand: """
|
||||
docker stop ${DOCKER_NAME} || true &&
|
||||
docker rm ${DOCKER_NAME} || true &&
|
||||
docker rmi ${DOCKER_IMAGE}:${DOCKER_TAG_PRE} || true &&
|
||||
docker load -i ${FILE_NAME} &&
|
||||
docker run -d \
|
||||
-p ${DOCKER_PORT}:${DOCKER_PORT} \
|
||||
--name ${DOCKER_NAME} \
|
||||
--restart=always \
|
||||
-v ./admintool/log:/var/log/nginx \
|
||||
-e TZ=\${TZ:-Asia/Seoul} \
|
||||
${DOCKER_IMAGE}:${DOCKER_TAG} &&
|
||||
rm ${FILE_NAME}
|
||||
echo 'Docker Container Create Complete'
|
||||
""",
|
||||
execTimeout: 120000
|
||||
)
|
||||
],
|
||||
usePromotionTimestamp: false,
|
||||
verbose: true
|
||||
)
|
||||
]
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
88
Jenkinsfile.stage
Normal file
@@ -0,0 +1,88 @@
|
||||
pipeline {
|
||||
agent any
|
||||
|
||||
environment {
|
||||
DOCKER_IMAGE = "caliverse/admintool-front-stage"
|
||||
DOCKER_TAG = "1.0.0"
|
||||
DOCKER_TAG_PRE = "1.0.0"
|
||||
FILE_NAME = 'admintool_front-stage.tar'
|
||||
DOCKER_NAME = 'admintool-front-stage'
|
||||
DOCKER_PORT = '8080'
|
||||
DOCKERFILE_NAME = 'Dockerfile.stage'
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Docker Build') {
|
||||
steps {
|
||||
sh 'docker rmi $DOCKER_IMAGE:$DOCKER_TAG_PRE || true' //이전 이미지 삭제
|
||||
sh 'docker build -f $DOCKERFILE_NAME -t $DOCKER_IMAGE:$DOCKER_TAG .' //Dockerfile 기준으로 이미지 생성
|
||||
echo 'Docker Image Create'
|
||||
sh 'docker save -o $FILE_NAME $DOCKER_IMAGE:$DOCKER_TAG' //이미지 .tar 로 생성
|
||||
echo 'Docker Image > .tar File Create'
|
||||
script {
|
||||
def todayDate = sh(script: "date +%Y-%m-%d", returnStdout: true).trim()
|
||||
def fileName = "${FILE_NAME}_${todayDate}.tar"
|
||||
sh "cp ${FILE_NAME} ${fileName}" // 이름 변경
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Transfer Docker Image') {
|
||||
steps {
|
||||
// aws .tar transfer
|
||||
sshPublisher(
|
||||
publishers: [
|
||||
sshPublisherDesc(
|
||||
configName: 'stage-frontend',
|
||||
transfers: [
|
||||
sshTransfer(
|
||||
sourceFiles: "${FILE_NAME}",
|
||||
remoteDirectory: '',
|
||||
execCommand: """
|
||||
echo '.tar Transfer Complete'
|
||||
""",
|
||||
execTimeout: 120000
|
||||
)
|
||||
],
|
||||
usePromotionTimestamp: false,
|
||||
verbose: true
|
||||
)
|
||||
]
|
||||
)
|
||||
}
|
||||
}
|
||||
stage('Deploy to Remote'){
|
||||
steps{
|
||||
// aws command
|
||||
sshPublisher(
|
||||
publishers: [
|
||||
sshPublisherDesc(
|
||||
configName: 'stage-frontend',
|
||||
transfers: [
|
||||
sshTransfer(
|
||||
execCommand: """
|
||||
docker stop ${DOCKER_NAME} || true &&
|
||||
docker rm ${DOCKER_NAME} || true &&
|
||||
docker rmi ${DOCKER_IMAGE}:${DOCKER_TAG_PRE} || true &&
|
||||
docker load -i ${FILE_NAME} &&
|
||||
docker run -d \
|
||||
-p ${DOCKER_PORT}:${DOCKER_PORT} \
|
||||
--name ${DOCKER_NAME} \
|
||||
--restart=always \
|
||||
-v ./admintool/log:/var/log/nginx \
|
||||
-e TZ=\${TZ:-Asia/Seoul} \
|
||||
${DOCKER_IMAGE}:${DOCKER_TAG} &&
|
||||
rm ${FILE_NAME}
|
||||
echo 'Docker Container Create Complete'
|
||||
""",
|
||||
execTimeout: 120000
|
||||
)
|
||||
],
|
||||
usePromotionTimestamp: false,
|
||||
verbose: true
|
||||
)
|
||||
]
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
70
README.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# Getting Started with Create React App
|
||||
|
||||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
||||
|
||||
## Available Scripts
|
||||
|
||||
In the project directory, you can run:
|
||||
|
||||
### `yarn start`
|
||||
|
||||
Runs the app in the development mode.\
|
||||
Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
|
||||
|
||||
The page will reload when you make changes.\
|
||||
You may also see any lint errors in the console.
|
||||
|
||||
### `yarn test`
|
||||
|
||||
Launches the test runner in the interactive watch mode.\
|
||||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
||||
|
||||
### `yarn build`
|
||||
|
||||
Builds the app for production to the `build` folder.\
|
||||
It correctly bundles React in production mode and optimizes the build for the best performance.
|
||||
|
||||
The build is minified and the filenames include the hashes.\
|
||||
Your app is ready to be deployed!
|
||||
|
||||
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
||||
|
||||
### `yarn eject`
|
||||
|
||||
**Note: this is a one-way operation. Once you `eject`, you can't go back!**
|
||||
|
||||
If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
|
||||
|
||||
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
|
||||
|
||||
You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
|
||||
|
||||
## Learn More
|
||||
|
||||
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
|
||||
|
||||
To learn React, check out the [React documentation](https://reactjs.org/).
|
||||
|
||||
### Code Splitting
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
|
||||
|
||||
### Analyzing the Bundle Size
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
|
||||
|
||||
### Making a Progressive Web App
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
|
||||
|
||||
### Advanced Configuration
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
|
||||
|
||||
### Deployment
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
|
||||
|
||||
### `yarn build` fails to minify
|
||||
|
||||
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
|
||||
25
nginx_dev.conf
Normal file
@@ -0,0 +1,25 @@
|
||||
server {
|
||||
listen 8080;
|
||||
listen [::]:8080;
|
||||
server_name localhost;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/admintool;
|
||||
index index.html index.htm;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# api reverse proxy
|
||||
location /api/ {
|
||||
proxy_pass http://10.20.20.23:23450;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/admintool;
|
||||
}
|
||||
}
|
||||
25
nginx_live.conf
Normal file
@@ -0,0 +1,25 @@
|
||||
server {
|
||||
listen 8080;
|
||||
listen [::]:8080;
|
||||
server_name localhost;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/admintool;
|
||||
index index.html index.htm;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# api reverse proxy
|
||||
location /api/ {
|
||||
proxy_pass http://172.20.168.216:23450;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/admintool;
|
||||
}
|
||||
}
|
||||
25
nginx_qa.conf
Normal file
@@ -0,0 +1,25 @@
|
||||
server {
|
||||
listen 8080;
|
||||
listen [::]:8080;
|
||||
server_name localhost;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/admintool;
|
||||
index index.html index.htm;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# api reverse proxy
|
||||
location /api/ {
|
||||
proxy_pass http://172.40.129.180:23450;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/admintool;
|
||||
}
|
||||
}
|
||||
25
nginx_stage.conf
Normal file
@@ -0,0 +1,25 @@
|
||||
server {
|
||||
listen 8080;
|
||||
listen [::]:8080;
|
||||
server_name localhost;
|
||||
|
||||
location / {
|
||||
root /usr/share/nginx/admintool;
|
||||
index index.html index.htm;
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# api reverse proxy
|
||||
location /api/ {
|
||||
proxy_pass http://172.30.148.164:23450;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root /usr/share/nginx/admintool;
|
||||
}
|
||||
}
|
||||
34857
package-lock.json
generated
Normal file
62
package.json
Normal file
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"name": "backofficefront",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@hookform/resolvers": "^3.2.0",
|
||||
"@testing-library/jest-dom": "^5.14.1",
|
||||
"@testing-library/react": "^13.0.0",
|
||||
"@testing-library/user-event": "^13.2.1",
|
||||
"axios": "^1.4.0",
|
||||
"date-fns": "^2.30.0",
|
||||
"dotenv-cli": "^7.4.2",
|
||||
"i18next": "^23.15.1",
|
||||
"lodash": "^4.17.21",
|
||||
"react": "^18.2.0",
|
||||
"react-calendar": "^4.4.0",
|
||||
"react-datepicker": "^4.16.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-hook-form": "^7.45.4",
|
||||
"react-i18next": "^15.0.2",
|
||||
"react-router-dom": "^6.14.1",
|
||||
"react-scripts": "5.0.1",
|
||||
"react-table": "^7.8.0",
|
||||
"recoil": "^0.7.7",
|
||||
"styled-components": "^6.0.4",
|
||||
"styled-reset": "^4.5.1",
|
||||
"web-vitals": "^2.1.0",
|
||||
"xlsx": "^0.18.5",
|
||||
"xlsx-js-style": "^1.2.0",
|
||||
"yup": "^1.2.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "dotenv -e .env.local react-scripts start",
|
||||
"build:stage": "dotenv -e .env.stage react-scripts build",
|
||||
"build:live": "dotenv -e .env.live react-scripts build",
|
||||
"build:dev": "dotenv -e .env.dev react-scripts build",
|
||||
"build:qa": "dotenv -e .env.qa react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"react-app",
|
||||
"react-app/jest"
|
||||
]
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11"
|
||||
}
|
||||
}
|
||||
BIN
public/favicon.ico
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
29
public/index.html
Normal file
@@ -0,0 +1,29 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta name="description" content="Web site created using create-react-app" />
|
||||
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>CALIVERSE</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
BIN
public/loading.gif
Normal file
|
After Width: | Height: | Size: 176 KiB |
BIN
public/logo192.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
public/logo512.png
Normal file
|
After Width: | Height: | Size: 9.4 KiB |
25
public/manifest.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"short_name": "React App",
|
||||
"name": "Create React App Sample",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
3
public/robots.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
# https://www.robotstxt.org/robotstxt.html
|
||||
User-agent: *
|
||||
Disallow:
|
||||
38
src/App.css
Normal file
@@ -0,0 +1,38 @@
|
||||
.App {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.App-logo {
|
||||
height: 40vmin;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
.App-logo {
|
||||
animation: App-logo-spin infinite 20s linear;
|
||||
}
|
||||
}
|
||||
|
||||
.App-header {
|
||||
background-color: #282c34;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: calc(10px + 2vmin);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.App-link {
|
||||
color: #61dafb;
|
||||
}
|
||||
|
||||
@keyframes App-logo-spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
25
src/App.js
Normal file
@@ -0,0 +1,25 @@
|
||||
import { BrowserRouter, Link } from 'react-router-dom';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import GlobalStyles from './styles/GlobalStyles';
|
||||
import RouteInfo from './RouteInfo';
|
||||
|
||||
import './i18n';
|
||||
|
||||
function App() {
|
||||
const isToken = sessionStorage.getItem('token') ? true : false;
|
||||
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<GlobalStyles />
|
||||
<ControllLink>{isToken ? <Link to="/main" /> : <Link to="/fail" />}</ControllLink>
|
||||
<RouteInfo />
|
||||
</BrowserRouter>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
||||
const ControllLink = styled.div`
|
||||
position: absolute;
|
||||
`;
|
||||
8
src/App.test.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import App from './App';
|
||||
|
||||
test('renders learn react link', () => {
|
||||
render(<App />);
|
||||
const linkElement = screen.getByText(/learn react/i);
|
||||
expect(linkElement).toBeInTheDocument();
|
||||
});
|
||||
82
src/RouteInfo.js
Normal file
@@ -0,0 +1,82 @@
|
||||
import { Route, Routes } from 'react-router-dom';
|
||||
import { Layout, LoginLayout, MainLayout } from './components/common/Layout';
|
||||
import LoginBg from './assets/img/login-bg.png';
|
||||
import { Login } from './pages/Login';
|
||||
import LoginFail from './pages/LoginFail';
|
||||
import { AccountEdit, AccountRegist, PasswordReset } from './pages/Account';
|
||||
import Main from './pages/Main';
|
||||
import {
|
||||
AdminView,
|
||||
AuthSetting,
|
||||
AuthSettingUpdate,
|
||||
CaliumRequest,
|
||||
LogView,
|
||||
} from './pages/UserManage';
|
||||
import { EconomicIndex, UserIndex } from './pages/IndexManage';
|
||||
import { LandView, CryptView, GameLogView, UserView } from './pages/DataManage';
|
||||
import {
|
||||
Board,
|
||||
Event,
|
||||
EventRegist,
|
||||
Items,
|
||||
Mail,
|
||||
MailRegist,
|
||||
ReportList,
|
||||
UserBlock,
|
||||
UserBlockRegist,
|
||||
WhiteList,
|
||||
LandAuction,
|
||||
BattleEvent
|
||||
} from './pages/ServiceManage';
|
||||
|
||||
const RouteInfo = () => {
|
||||
return (
|
||||
<Routes>
|
||||
<Route element={<LoginLayout $bgimg={LoginBg} $padding="50px" />}>
|
||||
<Route path="/" element={<Login />} />
|
||||
<Route path="/fail" element={<LoginFail />} />
|
||||
<Route path="/account/regist" element={<AccountRegist />} />
|
||||
<Route path="/account/pwdreset" element={<PasswordReset />} />
|
||||
<Route path="/account/edit" element={<AccountEdit />} />
|
||||
</Route>
|
||||
<Route element={<MainLayout />}>
|
||||
<Route path="/main" element={<Main />} />
|
||||
</Route>
|
||||
<Route element={<Layout />}>
|
||||
<Route path="/usermanage/">
|
||||
<Route path="adminview" element={<AdminView />} />
|
||||
<Route path="logview" element={<LogView />} />
|
||||
<Route path="authsetting" element={<AuthSetting />} />
|
||||
<Route path="authsetting/:id" element={<AuthSettingUpdate />} />
|
||||
<Route path="caliumrequest" element={<CaliumRequest />} />
|
||||
</Route>
|
||||
<Route path="/indexmanage">
|
||||
<Route path="userindex" element={<UserIndex />} />
|
||||
<Route path="economicindex" element={<EconomicIndex />} />
|
||||
</Route>
|
||||
<Route path="/datamanage">
|
||||
<Route path="userview" element={<UserView />} />
|
||||
<Route path="landview" element={<LandView />} />
|
||||
<Route path="gamelogview" element={<GameLogView />} />
|
||||
<Route path="cryptview" element={<CryptView />} />
|
||||
</Route>
|
||||
<Route path="/servicemanage">
|
||||
<Route path="board" element={<Board />} />
|
||||
<Route path="whitelist" element={<WhiteList />} />
|
||||
<Route path="mail" element={<Mail />} />
|
||||
<Route path="mail/mailregist" element={<MailRegist />} />
|
||||
<Route path="userblock" element={<UserBlock />} />
|
||||
<Route path="userblock/userblockregist" element={<UserBlockRegist />} />
|
||||
<Route path="reportlist" element={<ReportList />} />
|
||||
<Route path="items" element={<Items />} />
|
||||
<Route path="event" element={<Event />} />
|
||||
<Route path="event/eventregist" element={<EventRegist />} />
|
||||
<Route path="landauction" element={<LandAuction />} />
|
||||
<Route path="battleevent" element={<BattleEvent />} />
|
||||
</Route>
|
||||
</Route>
|
||||
</Routes>
|
||||
)
|
||||
}
|
||||
|
||||
export default RouteInfo;
|
||||
79
src/RouteInfo.js.bak
Normal file
@@ -0,0 +1,79 @@
|
||||
import { Route, Routes } from 'react-router-dom';
|
||||
import { Layout, LoginLayout, MainLayout } from './components/common/Layout';
|
||||
import LoginBg from './assets/img/login-bg.png';
|
||||
import { Login } from './pages/Login';
|
||||
import LoginFail from './pages/LoginFail';
|
||||
import { AccountEdit, AccountRegist, PasswordReset } from './pages/Account';
|
||||
import Main from './pages/Main';
|
||||
import {
|
||||
AdminView,
|
||||
AuthSetting,
|
||||
AuthSettingUpdate,
|
||||
CaliumRequest,
|
||||
CaliumRequestRegist,
|
||||
LogView,
|
||||
} from './pages/UserManage';
|
||||
import { EconomicIndex, UserIndex } from './pages/IndexManage';
|
||||
import { ContentsView, CryptView, GameLogView, UserView } from './pages/DataManage';
|
||||
import {
|
||||
Board,
|
||||
Event,
|
||||
EventRegist,
|
||||
Items,
|
||||
Mail,
|
||||
MailRegist,
|
||||
ReportList,
|
||||
UserBlock,
|
||||
UserBlockRegist,
|
||||
WhiteList,
|
||||
} from './pages/ServiceManage';
|
||||
|
||||
const RouteInfo = () => {
|
||||
return (
|
||||
<Routes>
|
||||
<Route element={<LoginLayout $bgimg={LoginBg} $padding="50px" />}>
|
||||
<Route path="/" element={<Login />} />
|
||||
<Route path="/fail" element={<LoginFail />} />
|
||||
<Route path="/account/regist" element={<AccountRegist />} />
|
||||
<Route path="/account/pwdreset" element={<PasswordReset />} />
|
||||
<Route path="/account/edit" element={<AccountEdit />} />
|
||||
</Route>
|
||||
<Route element={<MainLayout />}>
|
||||
<Route path="/main" element={<Main />} />
|
||||
</Route>
|
||||
<Route element={<Layout />}>
|
||||
<Route path="/usermanage/">
|
||||
<Route path="adminview" element={<AdminView />} />
|
||||
<Route path="logview" element={<LogView />} />
|
||||
<Route path="authsetting" element={<AuthSetting />} />
|
||||
<Route path="authsetting/:id" element={<AuthSettingUpdate />} />
|
||||
<Route path="caliumrequest" element={<CaliumRequest />} />
|
||||
</Route>
|
||||
<Route path="/indexmanage">
|
||||
<Route path="userindex" element={<UserIndex />} />
|
||||
<Route path="economicindex" element={<EconomicIndex />} />
|
||||
</Route>
|
||||
<Route path="/datamanage">
|
||||
<Route path="userview" element={<UserView />} />
|
||||
<Route path="contentsview" element={<ContentsView />} />
|
||||
<Route path="gamelogview" element={<GameLogView />} />
|
||||
<Route path="cryptview" element={<CryptView />} />
|
||||
</Route>
|
||||
<Route path="/servicemanage">
|
||||
<Route path="board" element={<Board />} />
|
||||
<Route path="whitelist" element={<WhiteList />} />
|
||||
<Route path="mail" element={<Mail />} />
|
||||
<Route path="mail/mailregist" element={<MailRegist />} />
|
||||
<Route path="userblock" element={<UserBlock />} />
|
||||
<Route path="userblock/userblockregist" element={<UserBlockRegist />} />
|
||||
<Route path="reportlist" element={<ReportList />} />
|
||||
<Route path="items" element={<Items />} />
|
||||
<Route path="event" element={<Event />} />
|
||||
<Route path="event/eventregist" element={<EventRegist />} />
|
||||
</Route>
|
||||
</Route>
|
||||
</Routes>
|
||||
)
|
||||
}
|
||||
|
||||
export default RouteInfo;
|
||||
100
src/apis/Admin.js
Normal file
@@ -0,0 +1,100 @@
|
||||
//사용자 관리 - 사용자 조회 api 연결
|
||||
|
||||
import { Axios } from '../utils';
|
||||
|
||||
// 운영자 조회
|
||||
export const AdminViewList = async (token, searchType, searchKey, groupType, joinCheck, orderBy, size, currentPage) => {
|
||||
try {
|
||||
const res = await Axios.get(
|
||||
`/api/v1/admin/list?search_type=${searchType ? searchType : 'NAME'}&search_key=${searchKey ? searchKey : ''}&group_id=${groupType ? groupType : ''}&join_check=${joinCheck}&orderby=${
|
||||
orderBy ? orderBy : 'DESC'
|
||||
}&page_no=${currentPage}&page_size=${size}`,
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('AdminViewList Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const AdminViewGroupList = async token => {
|
||||
try {
|
||||
const res = await Axios.get('/api/v1/admin/group-list', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data.group_list;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('AdminViewGroupList Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const AdminLoginApprove = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.patch(
|
||||
'/api/v1/admin',
|
||||
{ list: params },
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
},
|
||||
);
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('AdminLoginApprove Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const AdminChangeGroup = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.put(
|
||||
'/api/v1/admin',
|
||||
{ list: params },
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
},
|
||||
);
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('AdminChangeGroup Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const AdminDeleteUser = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.delete('/api/v1/admin', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
data: { list: params },
|
||||
});
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('AdminDeleteUser Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const AdminChangePw = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.post('/api/v1/admin/init-password', params, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('AdminChangePw Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
79
src/apis/Auth.js
Normal file
@@ -0,0 +1,79 @@
|
||||
//인증 관련 api 연결
|
||||
|
||||
import { Axios } from '../utils';
|
||||
|
||||
export const AuthInfo = async token => {
|
||||
try {
|
||||
const res = await Axios.get('/api/v1/admin/info', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('AuthInfo', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const AuthLogin = async params => {
|
||||
try {
|
||||
const res = await Axios.post('/api/v1/auth/login', params);
|
||||
|
||||
return res.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('AuthLogin Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const AuthRegist = async data => {
|
||||
try {
|
||||
const res = await Axios.post('/api/v1/auth/register', {
|
||||
email: data.userid,
|
||||
name: data.username,
|
||||
password: data.password,
|
||||
});
|
||||
|
||||
return res.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
e.response.data.message.map(message => alert(message));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const AuthLogout = async token => {
|
||||
try {
|
||||
const res = await Axios.post('/api/v1/auth/logout', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('AuthLogout Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const AuthEdit = async (data, token) => {
|
||||
try {
|
||||
const res = await Axios.patch(
|
||||
'/api/v1/admin/change-password',
|
||||
{
|
||||
password: data.password,
|
||||
new_password: data.newPassword,
|
||||
},
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
},
|
||||
);
|
||||
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('AuthEdit Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
117
src/apis/Battle.js
Normal file
@@ -0,0 +1,117 @@
|
||||
//운영서비스 관리 - 전투시스템 api 연결
|
||||
|
||||
import { Axios } from '../utils';
|
||||
|
||||
// 전투시스템 리스트 조회
|
||||
export const BattleEventView = async (token, landType, landData, userType, userData, landSize, status, startDate, endDate, order, size, currentPage) => {
|
||||
try {
|
||||
const res = await Axios.get(
|
||||
`/api/v1/battle/event/list?land_type=${landType}&land_data=${landData}&user_type=${userType}&user_data=${userData}&land_size=${landSize}&status=${status}&start_dt=${startDate}&end_dt=${endDate}&orderby=${order}&page_no=${currentPage}
|
||||
&page_size=${size}`,
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
},
|
||||
);
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('BattleEventView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 전투시스템 상세보기
|
||||
export const BattleEventDetailView = async (token, id) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/battle/event/detail/${id}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('BattleEventDetailView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 전투시스템 등록
|
||||
export const BattleEventSingleRegist = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.post(`/api/v1/battle/event`, params, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('BattleEventSingleRegist Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 전투시스템 수정
|
||||
export const BattleEventModify = async (token, id, params) => {
|
||||
try {
|
||||
const res = await Axios.put(`/api/v1/battle/event/${id}`, params, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('BattleEventModify Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 전투시스템 삭제
|
||||
export const BattleEventDelete = async (token, params, id) => {
|
||||
try {
|
||||
const res = await Axios.delete(`/api/v1/battle/event/delete`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
data: { list: params },
|
||||
});
|
||||
|
||||
return res.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('BattleEventDelete Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const BattleConfigView = async (token) => {
|
||||
try {
|
||||
const res = await Axios.get(
|
||||
`/api/v1/battle/config/list`,
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
},
|
||||
);
|
||||
|
||||
return res.data.data.battle_config_list;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('BattleConfigView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const BattleRewardView = async (token) => {
|
||||
try {
|
||||
const res = await Axios.get(
|
||||
`/api/v1/battle/reward/list`,
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
},
|
||||
);
|
||||
|
||||
return res.data.data.battle_reward_list;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('BattleRewardView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
121
src/apis/BlackList.js
Normal file
@@ -0,0 +1,121 @@
|
||||
//운영서비스 관리 - 이용자 제재 리스트 api 연결
|
||||
|
||||
import { Axios } from '../utils';
|
||||
|
||||
// 블랙리스트 조회
|
||||
export const BlackListView = async (token, searchType, data, email, status, sanctions, period, order, size, currentPage) => {
|
||||
try {
|
||||
const res = await Axios.get(
|
||||
`/api/v1/black-list/list?search_type=${searchType ? searchType : ''}
|
||||
&search_key=${data ? data : ''}
|
||||
&email=${email ? email : ''}
|
||||
&status=${status ? status : ''}
|
||||
&sanctions=${sanctions ? sanctions : ''}
|
||||
&period=${period ? period : ''}
|
||||
&orderby=${order}
|
||||
&page_no=${currentPage}
|
||||
&page_size=${size}
|
||||
`,
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
},
|
||||
);
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 블랙 리스트 상세 조회
|
||||
export const BlackListDetail = async (token, id) => {
|
||||
try {
|
||||
const res = await Axios.get(`api/v1/black-list/detail/${id}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data.detail;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('BlackListDetail', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 제재 삭제
|
||||
export const BlackListDelete = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.delete(`api/v1/black-list`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
data: { list: params },
|
||||
});
|
||||
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('BlackListDelete', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 제재 등록
|
||||
export const BlackListRegist = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.post(`/api/v1/black-list`, params, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('BlacklistRegist', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// 엑셀 업로드
|
||||
export const BlackListMultipleUpload = async (token, file) => {
|
||||
const exelFile = new FormData()
|
||||
exelFile.append('file', file)
|
||||
try {
|
||||
const res = await Axios.post(`/api/v1/black-list/excel-upload`, exelFile, {
|
||||
headers: {
|
||||
"Content-Type": "multipart/form-data",
|
||||
Authorization: `Bearer ${token}`
|
||||
},
|
||||
});
|
||||
|
||||
return res.data.data.list;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('BlacklistRegist', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const BlackListExcelDown = async (token, filename) => {
|
||||
try {
|
||||
await Axios.get(`/api/v1/black-list/excel-down?file=${filename}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
responseType: 'blob',
|
||||
}).then(response => {
|
||||
const href = URL.createObjectURL(response.data);
|
||||
|
||||
const link = document.createElement('a');
|
||||
link.href = href;
|
||||
link.setAttribute('download', `${filename}`);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
|
||||
document.body.removeChild(link);
|
||||
URL.revokeObjectURL(href);
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('BlacklistExcelDown Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
82
src/apis/Calium.js
Normal file
@@ -0,0 +1,82 @@
|
||||
//운영자 관리 - 칼리움 api 연결
|
||||
|
||||
import { Axios } from '../utils';
|
||||
|
||||
// 칼리움 요청 리스트 조회
|
||||
export const CaliumRequestView = async (token, content, status, startDate, endDate, order, size, currentPage) => {
|
||||
try {
|
||||
const res = await Axios.get(
|
||||
`/api/v1/calium/list?content=${content}&status=${status}&start_dt=${startDate}&end_dt=${endDate}&orderby=${order}&page_no=${currentPage}
|
||||
&page_size=${size}`,
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
},
|
||||
);
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('CaliumRequestView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 칼리움 상세보기
|
||||
export const CaliumDetailView = async (token, id) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/calium/detail/${id}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data.detail;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('CaliumDetailView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 칼리움 요청 등록
|
||||
export const CaliumRequestRegist = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.post(`/api/v1/calium`, params, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('CaliumRequestRegist Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 칼리움 충적
|
||||
export const CaliumCharge = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.post(`/api/v1/calium/charge`, params, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('CaliumCharge Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 칼리움 인출 가능 수량
|
||||
export const CaliumLimitCount = async (token) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/calium/limit`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data.withdrawable_info;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('CaliumLimitCount Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
98
src/apis/Event.js
Normal file
@@ -0,0 +1,98 @@
|
||||
//운영서비스 관리 - 이벤트 api 연결
|
||||
|
||||
import { Axios } from '../utils';
|
||||
|
||||
// 이벤트 리스트 조회
|
||||
export const EventView = async (token, title, content, status, startDate, endDate, order, size, currentPage) => {
|
||||
try {
|
||||
const res = await Axios.get(
|
||||
`/api/v1/event/list?title=${title}&content=${content}&status=${status}&start_dt=${startDate}&end_dt=${endDate}&orderby=${order}&page_no=${currentPage}
|
||||
&page_size=${size}`,
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
},
|
||||
);
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('EventView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 이벤트 상세보기
|
||||
export const EventDetailView = async (token, id) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/event/detail/${id}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data.detail;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('EventDetailView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 이벤트 등록
|
||||
export const EventSingleRegist = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.post(`/api/v1/event`, params, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('EventSingleRegist Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 우편 수정
|
||||
export const EventModify = async (token, id, params) => {
|
||||
try {
|
||||
const res = await Axios.put(`/api/v1/event/${id}`, params, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data.list;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('EventModify Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 우편 삭제
|
||||
export const EventDelete = async (token, params, id) => {
|
||||
try {
|
||||
const res = await Axios.delete(`/api/v1/event/delete`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
data: { list: params },
|
||||
});
|
||||
|
||||
return res.data.data.list;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('EventDelete Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 이벤트 우편 아이템 확인
|
||||
export const EventIsItem = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.post(`/api/v1/event/item`, params, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('EventIsItem Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
82
src/apis/Group.js
Normal file
@@ -0,0 +1,82 @@
|
||||
//사용자 관리 - 그룹 조회 api 연결
|
||||
|
||||
import { Axios } from '../utils';
|
||||
|
||||
// 그룹 권한 조회
|
||||
export const GroupViewList = async (token, orderBy, size, currentPage) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/groups/list?orderby=${orderBy ? orderBy : 'DESC'}
|
||||
&page_no=${size}&page_size=${currentPage}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('GroupViewList Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 그룹 상세 권한 조회
|
||||
export const GroupDetailViewList = async (token, id) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/groups/detail/${id}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('GroupViewList Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 권한 그룹 등록
|
||||
export const GroupRegist = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.post(`/api/v1/groups`, params, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
// e.response.data.message.map(message => alert(message));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 권한 그룹 선택 삭제
|
||||
export const GroupDelete = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.delete('/api/v1/groups', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
data: { list: params },
|
||||
});
|
||||
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('GroupDelete', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 권한 수정
|
||||
export const GroupModify = async (token, id, params) => {
|
||||
try {
|
||||
const res = await Axios.put(
|
||||
`/api/v1/groups/${id}`,
|
||||
{ list: params },
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
},
|
||||
);
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('GroupModify Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
36
src/apis/History.js
Normal file
@@ -0,0 +1,36 @@
|
||||
//사용자 관리 - 로그조회 api 연결
|
||||
|
||||
import { Axios } from '../utils';
|
||||
|
||||
export const LogViewList = async (token, searchType, searchKey, historyType, startDt, endDt, orderBy, size, currentPage) => {
|
||||
try {
|
||||
const res = await Axios.get(
|
||||
`/api/v1/history/list?search_type=${searchType ? searchType : 'NAME'}&search_key=${searchKey ? searchKey : ''}&history_type=${historyType ? historyType : ''}&start_dt=${
|
||||
startDt ? startDt : ''
|
||||
}&end_dt=${endDt ? endDt : ''}&orderby=${orderBy ? orderBy : 'DESC'}&page_no=${currentPage}&page_size=${size}`,
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
},
|
||||
);
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('LogViewList Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const LogviewDetail = async (token, id) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/history/detail/${id}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data.content;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('LogViewDetail', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
456
src/apis/Indicators.js
Normal file
@@ -0,0 +1,456 @@
|
||||
//지표 관리 - 유저 지표, 경제 지표 api
|
||||
|
||||
import { Axios } from '../utils';
|
||||
|
||||
// 1. 유저 지표
|
||||
// 2. 경제 지표
|
||||
|
||||
// 1. 유저 지표
|
||||
|
||||
// 이용자 지표 조회
|
||||
export const userIndexView = async (token, sendDate, endDate) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/indicators/user/list?start_dt=${sendDate}&end_dt=${endDate}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data.user_statistics_list;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('MailView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 이용자 지표 총계
|
||||
export const userTotalIndex = async token => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/indicators/user/total`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('userTotalIndex', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 유저 지표 다운로드
|
||||
export const userIndexExport = async (token, filename, sendDate, endDate) => {
|
||||
try {
|
||||
await Axios.get(`/api/v1/indicators/user/excel-down?file=${filename}&start_dt=${sendDate}&end_dt=${endDate}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
responseType: 'blob',
|
||||
}).then(response => {
|
||||
const href = URL.createObjectURL(response.data);
|
||||
|
||||
const link = document.createElement('a');
|
||||
link.href = href;
|
||||
link.setAttribute('download', `${filename}`);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
|
||||
document.body.removeChild(link);
|
||||
URL.revokeObjectURL(href);
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('userIndexExport Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Retention
|
||||
export const RetentionIndexView = async (token, start_dt, end_dt) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/indicators/retention/list?start_dt=${start_dt}&end_dt=${end_dt}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('RetentionIndexView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Retention 다운로드
|
||||
export const RetentionIndexExport = async (token, filename, sendDate, endDate) => {
|
||||
try {
|
||||
await Axios.get(`/api/v1/indicators/retention/excel-down?${filename}&start_dt=${sendDate}&end_dt=${endDate}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
responseType: 'blob',
|
||||
}).then(response => {
|
||||
const href = URL.createObjectURL(response.data);
|
||||
|
||||
const link = document.createElement('a');
|
||||
link.href = href;
|
||||
link.setAttribute('download', `${filename}`);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
|
||||
document.body.removeChild(link);
|
||||
URL.revokeObjectURL(href);
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('RetentionIndexExport Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Segment
|
||||
export const SegmentIndexView = async (token, search_dt) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/indicators/segment/list?search_dt=${search_dt}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('SegmentIndexView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Segment 다운로드
|
||||
export const SegmentIndexExport = async (token, filename, endDate) => {
|
||||
try {
|
||||
await Axios.get(`/api/v1/indicators/segment/excel-down?${filename}&search_dt=${endDate}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
responseType: 'blob',
|
||||
}).then(response => {
|
||||
const href = URL.createObjectURL(response.data);
|
||||
|
||||
const link = document.createElement('a');
|
||||
link.href = href;
|
||||
link.setAttribute('download', `${filename}`);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
|
||||
document.body.removeChild(link);
|
||||
URL.revokeObjectURL(href);
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('SegmentIndexExport Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Playtime
|
||||
export const PlaytimeIndexView = async (token, start_dt, end_dt) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/indicators/playtime/list?start_dt=${start_dt}&end_dt=${end_dt}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('PlaytimeIndexView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Playtime 다운로드
|
||||
export const PlaytimeIndexExport = async (token, filename, sendDate, endDate) => {
|
||||
try {
|
||||
await Axios.get(`/api/v1/indicators/playtime/excel-down?file=${filename}&start_dt=${sendDate}&end_dt=${endDate}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
responseType: 'blob',
|
||||
}).then(response => {
|
||||
const href = URL.createObjectURL(response.data);
|
||||
|
||||
const link = document.createElement('a');
|
||||
link.href = href;
|
||||
link.setAttribute('download', `${filename}`);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
|
||||
document.body.removeChild(link);
|
||||
URL.revokeObjectURL(href);
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('PlaytimeIndexExport Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 2. 경제 지표
|
||||
|
||||
// 재화 조회 (currency)
|
||||
export const CurrencyIndexView = async (token, start_dt, end_dt, currency_type) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/indicators/currency/use?start_dt=${start_dt}&end_dt=${end_dt}¤cy_type=${currency_type}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('currencyIndexView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 재화 지표 다운로드
|
||||
export const CurrencyIndexExport = async (token, filename, sendDate, endDate, currencyType) => {
|
||||
try {
|
||||
await Axios.get(`/api/v1/indicators/currency/excel-down?file=${filename}&start_dt=${sendDate}&end_dt=${endDate}¤cy_type=${currencyType}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
responseType: 'blob',
|
||||
}).then(response => {
|
||||
const href = URL.createObjectURL(response.data);
|
||||
|
||||
const link = document.createElement('a');
|
||||
link.href = href;
|
||||
link.setAttribute('download', `${filename}`);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
|
||||
document.body.removeChild(link);
|
||||
URL.revokeObjectURL(href);
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('CurrencyIndexExport Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// VBP
|
||||
export const VbpIndexView = async (token, start_dt, end_dt) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/indicators/currency/vbp?start_dt=${start_dt}&end_dt=${end_dt}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('VbpIndexView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// VBP 다운로드
|
||||
export const VBPIndexExport = async (token, filename, sendDate, endDate) => {
|
||||
try {
|
||||
await Axios.get(`/api/v1/indicators/currency/excel-down?file=${filename}&start_dt=${sendDate}&end_dt=${endDate}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
responseType: 'blob',
|
||||
}).then(response => {
|
||||
const href = URL.createObjectURL(response.data);
|
||||
|
||||
const link = document.createElement('a');
|
||||
link.href = href;
|
||||
link.setAttribute('download', `${filename}`);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
|
||||
document.body.removeChild(link);
|
||||
URL.revokeObjectURL(href);
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('VBPIndexExport Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Item
|
||||
export const ItemIndexView = async (token, start_dt, end_dt) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/indicators/currency/item?start_dt=${start_dt}&end_dt=${end_dt}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('ItemIndexView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Item 다운로드
|
||||
export const ItemIndexExport = async (token, filename, sendDate, endDate) => {
|
||||
try {
|
||||
await Axios.get(`/api/v1/indicators/currency/excel-down?file=${filename}&start_dt=${sendDate}&end_dt=${endDate}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
responseType: 'blob',
|
||||
}).then(response => {
|
||||
const href = URL.createObjectURL(response.data);
|
||||
|
||||
const link = document.createElement('a');
|
||||
link.href = href;
|
||||
link.setAttribute('download', `${filename}`);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
|
||||
document.body.removeChild(link);
|
||||
URL.revokeObjectURL(href);
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('ItemIndexExport Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Instance
|
||||
export const InstanceIndexView = async (token, data, start_dt, end_dt) => {
|
||||
try {
|
||||
const res = await Axios.get(
|
||||
`/api/v1/indicators/currency/instance?search_key=${data ? data : ''}
|
||||
&start_dt=${start_dt}&end_dt=${end_dt}`,
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
},
|
||||
);
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('InstanceIndexView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Instance 다운로드
|
||||
export const InstanceIndexExport = async (token, filename, data, sendDate, endDate) => {
|
||||
try {
|
||||
await Axios.get(
|
||||
`/api/v1/indicators/currency/excel-down?file=${filename}&search_key=${data ? data : ''}
|
||||
&start_dt=${sendDate}&end_dt=${endDate}`,
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
responseType: 'blob',
|
||||
},
|
||||
).then(response => {
|
||||
const href = URL.createObjectURL(response.data);
|
||||
|
||||
const link = document.createElement('a');
|
||||
link.href = href;
|
||||
link.setAttribute('download', `${filename}`);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
|
||||
document.body.removeChild(link);
|
||||
URL.revokeObjectURL(href);
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('InstanceIndexExport Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Clothes
|
||||
export const ClothesIndexView = async (token, data, start_dt, end_dt) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/indicators/currency/clothes?search_key=${data ? data : ''}&start_dt=${start_dt}&end_dt=${end_dt}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('ClothesIndexView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Clothes 다운로드
|
||||
export const ClothesIndexExport = async (token, filename, data, sendDate, endDate) => {
|
||||
try {
|
||||
await Axios.get(
|
||||
`/api/v1/indicators/currency/excel-down?file=${filename}&search_key=${data ? data : ''}
|
||||
&start_dt=${sendDate}&end_dt=${endDate}`,
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
responseType: 'blob',
|
||||
},
|
||||
).then(response => {
|
||||
const href = URL.createObjectURL(response.data);
|
||||
|
||||
const link = document.createElement('a');
|
||||
link.href = href;
|
||||
link.setAttribute('download', `${filename}`);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
|
||||
document.body.removeChild(link);
|
||||
URL.revokeObjectURL(href);
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('ClothesIndexExport Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// DAU
|
||||
export const DailyActiveUserView = async (token, start_dt, end_dt) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/indicators/dau/list?start_dt=${start_dt}&end_dt=${end_dt}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data.dau_list;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('DailyActiveUserView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// DAU 다운로드
|
||||
export const DailyActiveUserExport = async (token, filename, sendDate, endDate) => {
|
||||
try {
|
||||
await Axios.get(`/api/v1/indicators/dau/excel-down?file=${filename}&start_dt=${sendDate}&end_dt=${endDate}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
responseType: 'blob',
|
||||
}).then(response => {
|
||||
const href = URL.createObjectURL(response.data);
|
||||
|
||||
const link = document.createElement('a');
|
||||
link.href = href;
|
||||
link.setAttribute('download', `${filename}`);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
|
||||
document.body.removeChild(link);
|
||||
URL.revokeObjectURL(href);
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('PlaytimeIndexExport Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Daily Medal
|
||||
export const DailyMedalView = async (token, start_dt, end_dt) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/indicators/daily-medal/list?start_dt=${start_dt}&end_dt=${end_dt}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data.daily_medal_list;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('DailyMedalView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
27
src/apis/Item.js
Normal file
@@ -0,0 +1,27 @@
|
||||
//운영서비스 관리 - 아이템 리스트 api 연결
|
||||
|
||||
import { Axios } from '../utils';
|
||||
|
||||
//아이템 리스트 조회
|
||||
export const ItemListView = async (token, searchType, data, status, restore, order, size, currentPage) => {
|
||||
try {
|
||||
const res = await Axios.get(
|
||||
`/api/v1/items/list?search_type=${searchType ? searchType : ''}
|
||||
&search_key=${data ? data : ''}
|
||||
&orderby=${order}
|
||||
&page_no=${currentPage}
|
||||
&page_size=${size}
|
||||
`,
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
},
|
||||
);
|
||||
// console.log(res.data.data);
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
131
src/apis/Land.js
Normal file
@@ -0,0 +1,131 @@
|
||||
//운영서비스 관리 - 랜드 경매 api 연결
|
||||
|
||||
import { Axios } from '../utils';
|
||||
|
||||
// 랜드 경매 리스트 조회
|
||||
export const LandAuctionView = async (token, landType, landData, userType, userData, landSize, status, startDate, endDate, order, size, currentPage) => {
|
||||
try {
|
||||
const res = await Axios.get(
|
||||
`/api/v1/land/auction/list?land_type=${landType}&land_data=${landData}&user_type=${userType}&user_data=${userData}&land_size=${landSize}&status=${status}&start_dt=${startDate}&end_dt=${endDate}&orderby=${order}&page_no=${currentPage}
|
||||
&page_size=${size}`,
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
},
|
||||
);
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('LandAuctionView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 랜드 경매 상세보기
|
||||
export const LandAuctionDetailView = async (token, id) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/land/auction/detail/${id}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('LandAuctionDetailView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 랜드 경매 등록
|
||||
export const LandAuctionSingleRegist = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.post(`/api/v1/land/auction`, params, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('LandAuctionSingleRegist Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 랜드 경매 수정
|
||||
export const LandAuctionModify = async (token, id, params) => {
|
||||
try {
|
||||
const res = await Axios.put(`/api/v1/land/auction/${id}`, params, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('LandAuctionModify Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 랜드 경매 삭제
|
||||
export const LandAuctionDelete = async (token, params, id) => {
|
||||
try {
|
||||
const res = await Axios.delete(`/api/v1/land/auction/delete`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
data: { list: params },
|
||||
});
|
||||
|
||||
return res.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('LandAuctionDelete Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const LandView = async (token) => {
|
||||
try {
|
||||
const res = await Axios.get(
|
||||
`/api/v1/land/list`,
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
},
|
||||
);
|
||||
|
||||
return res.data.data.land_list;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('LandView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const BuildingView = async (token) => {
|
||||
try {
|
||||
const res = await Axios.get(
|
||||
`/api/v1/land/building/list`,
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
},
|
||||
);
|
||||
|
||||
return res.data.data.building_list;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('LandView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const LandDetailView = async (token, id) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/land/detail/${id}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data.detail;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('LandDetailView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
142
src/apis/Mail.js
Normal file
@@ -0,0 +1,142 @@
|
||||
//운영서비스 관리 - 메일 api 연결
|
||||
|
||||
import { Axios } from '../utils';
|
||||
|
||||
// 메일 리스트 조회
|
||||
export const MailView = async (token, mailTitle, content, sendType, sendStatus, mailType, receiveType, sendDate, endDate, order, size, currentPage) => {
|
||||
try {
|
||||
const res = await Axios.get(
|
||||
`/api/v1/mail/list?mail_title=${mailTitle}&content=${content}&send_type=${sendType}&send_status=${sendStatus}&mail_type=${mailType}&receive_type=${receiveType}&start_dt=${sendDate}&end_dt=${endDate}&orderby=${order}&page_no=${currentPage}
|
||||
&page_size=${size}`,
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
},
|
||||
);
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('MailView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 메일 상세보기
|
||||
export const MailDetailView = async (token, id) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/mail/detail/${id}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data.detail;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('MailDetailView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 우편 단일 등록
|
||||
export const MailSingleRegist = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.post(`/api/v1/mail`, params, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('MailRegist Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 우편 수정
|
||||
export const MailModify = async (token, id, params) => {
|
||||
try {
|
||||
const res = await Axios.put(`/api/v1/mail/${id}`, params, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data.list;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('MailModify Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 우편 삭제
|
||||
export const MailDelete = async (token, params, id) => {
|
||||
try {
|
||||
const res = await Axios.delete(`/api/v1/mail/delete`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
data: { list: params },
|
||||
});
|
||||
|
||||
return res.data.data.list;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('MailDelete Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 우편 다운로드
|
||||
export const MailExcelDown = async (token, filename) => {
|
||||
try {
|
||||
await Axios.get(`/api/v1/mail/excel-down?file=${filename}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
responseType: 'blob',
|
||||
}).then(response => {
|
||||
const href = URL.createObjectURL(response.data);
|
||||
|
||||
const link = document.createElement('a');
|
||||
link.href = href;
|
||||
link.setAttribute('download', `${filename}`);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
|
||||
document.body.removeChild(link);
|
||||
URL.revokeObjectURL(href);
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('MailExcelDown Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 우편 업로드
|
||||
export const MailMultiRegsit = async (token, file) => {
|
||||
const exelFile = new FormData();
|
||||
exelFile.append('file', file);
|
||||
try {
|
||||
const res = await Axios.post(`/api/v1/mail/excel-upload`, exelFile, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('MailMultiRegsit', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 우편 아이템 확인
|
||||
export const MailIsItem = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.post(`/api/v1/mail/item`, params, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('MailItemCheck Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
69
src/apis/Notice.js
Normal file
@@ -0,0 +1,69 @@
|
||||
//운영 서비스 관리 - 인게임 메세지 api 연결
|
||||
|
||||
import { Axios } from '../utils';
|
||||
|
||||
export const NoticeListView = async token => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/notice/list`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
return res.data.data.list;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('NoticeList', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const NoticeDetailView = async (token, id) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/notice/detail/${id}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('NoticeDetailView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const NoticeRegist = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.post('/api/v1/notice', params, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('NoticeRegist Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const NoticeModify = async (token, id, params) => {
|
||||
try {
|
||||
const res = await Axios.put(`/api/v1/notice/${id}`, params, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('NoticeModify Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const NoticeDelete = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.delete('/api/v1/notice', {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
data: { list: params },
|
||||
});
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('NoticeDelete Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
75
src/apis/Report.js
Normal file
@@ -0,0 +1,75 @@
|
||||
//운영 서비스 관리 - 신고내역 api 연결
|
||||
|
||||
import { Axios } from '../utils';
|
||||
|
||||
// 신고내역 전체 조회
|
||||
export const ReportTotalView = async (token, startDate, endDate) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/report/total?start_dt=${startDate}&end_dt=${endDate}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('ReportTotalView', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 신고내역 리스트 조회
|
||||
export const ReportListView = async (token, startDate, endDate, reportType, status, searchType, searchKey, order, size, currentPage) => {
|
||||
try {
|
||||
const res = await Axios.get(
|
||||
`/api/v1/report/list?start_dt=${startDate}&end_dt=${endDate}&report_type=${reportType}&orderby=${order}&page_no=${currentPage}&page_size=${size}&status=${status}&search_type=${searchType}&search_key=${searchKey}`,
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
},
|
||||
);
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('ReportListView', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
// 신고내역 상세조회
|
||||
export const ReportListDetailView = async (token, pk, sk) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/report/report-detail?pk=${pk}&sk=${sk}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
return res.data.data.report;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('ReportListDetailView', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 신고내역 답변 작성
|
||||
export const RepostReplyMessage = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.post('/api/v1/report/reply', params, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('RepostReplyMessage Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 신고내역 답변 조회
|
||||
export const ReportReplyDetail = async (token, pk, sk) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/report/reply-detail?pk=${pk}&sk=${sk}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
return res.data.data.reply;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('ReportReplyDetail', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
264
src/apis/Users.js
Normal file
@@ -0,0 +1,264 @@
|
||||
//운영 정보 관리 - 유저 조회 api 연결
|
||||
|
||||
import { Axios } from '../utils';
|
||||
|
||||
// 유저 조회
|
||||
export const UserView = async (token, searchType, searchKey) => {
|
||||
try {
|
||||
const res = await Axios.get(
|
||||
`/api/v1/users/find-users?
|
||||
search_type=${searchType ? searchType : 'NAME'}
|
||||
&search_key=${searchKey ? searchKey : ''}`,
|
||||
{ headers: { Authorization: `Bearer ${token}` } },
|
||||
);
|
||||
|
||||
return res.data.data.result;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('UserView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 기본 정보 조회
|
||||
export const UserInfoView = async (token, guid) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/users/basicinfo?guid=${guid}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('UserInfoView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 닉네임 변경
|
||||
export const UserChangeNickName = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.put('/api/v1/users/change-nickname', params, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('UserChangeNickName Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// GM 권한 변경
|
||||
export const UserChangeAdminLevel = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.put('/api/v1/users/change-level', params, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('UserChangeGMType Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 아바타 조회
|
||||
export const UserAvatarView = async (token, guid) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/users/avatarinfo?guid=${guid}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('UserAvatarView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 의상 조회
|
||||
export const UserClothView = async (token, guid) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/users/clothinfo?guid=${guid}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('UserClothView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 도구 조회
|
||||
export const UserToolView = async (token, guid) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/users/toolslot?guid=${guid}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('UserToolView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 인벤토리 조회
|
||||
export const UserInventoryView = async (token, guid) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/users/inventory?guid=${guid}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('UserInventoryView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 인벤토리 아이템 삭제
|
||||
export const UserInventoryItemDelete = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.delete(`/api/v1/users/inventory/delete/item`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
data: params,
|
||||
});
|
||||
|
||||
return res.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('UserInventoryItemDelete Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 타투 조회
|
||||
export const UserTattooView = async (token, guid) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/users/tattoo?guid=${guid}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('UserTattooView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 퀘스트 조회
|
||||
export const UserQuestView = async (token, guid) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/users/quest?guid=${guid}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('UserQuestView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 친구목록 조회
|
||||
export const UserFriendListView = async (token, guid) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/users/friendlist?guid=${guid}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('UserFriendListView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 우편 조회
|
||||
export const UserMailView = async (token, guid, option) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/users/mail?guid=${guid}&type=${option}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('UserMailView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 우편 삭제
|
||||
export const UserMailDelete = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.delete(`/api/v1/users/mail/delete`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
data: params,
|
||||
});
|
||||
|
||||
return res.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('UserMailView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 우편 아이템 삭제
|
||||
export const UserMailItemDelete = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.delete(`/api/v1/users/mail/delete/item`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
data: params,
|
||||
});
|
||||
|
||||
return res.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('UserMailItemDelete Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 유저 우편 상세 정보 조회
|
||||
export const UserMailDetailView = async (token, id) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/users/mail/${id}}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('UserMailDetailView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 마이홈 조회
|
||||
export const UserMyhomeView = async (token, guid) => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/users/myhome?guid=${guid}`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('UserMyhomeView Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
134
src/apis/WhiteList.js
Normal file
@@ -0,0 +1,134 @@
|
||||
//운영서비스 관리 - 화이트 리스트 api 연결
|
||||
|
||||
import { Axios } from '../utils';
|
||||
|
||||
export const WhiteListData = async token => {
|
||||
try {
|
||||
const res = await Axios.get(`/api/v1/white-list/list`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
|
||||
return res.data.data.list;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('whiteList Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 선택 삭제
|
||||
export const WhiteListDelete = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.delete(`/api/v1/white-list`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
data: { list: params },
|
||||
});
|
||||
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('WhiteListDelete', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 선택 승인
|
||||
export const WhiteListAllow = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.patch(
|
||||
`/api/v1/white-list`,
|
||||
{ list: params },
|
||||
{
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
},
|
||||
);
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('WhiteListAllow', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 화이트 리스트 등록 (단일)
|
||||
export const WhiteListRegist = async (token, params) => {
|
||||
try {
|
||||
const res = await Axios.post(`/api/v1/white-list`, params, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('WhiteListRegist', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 화이트리스트 엑셀 업로더
|
||||
export const WhiteListExelUpload = async (token, file) => {
|
||||
const exelFile = new FormData();
|
||||
exelFile.append('file', file);
|
||||
try {
|
||||
const res = await Axios.post(`/api/v1/white-list/excel-upload`, exelFile, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('WhiteListExelUpload', e);
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 화이트 리스트 등록(복수) -> 등록하는 것임
|
||||
export const WhiteListMultiRegsit = async (token, file) => {
|
||||
const exelFile = new FormData();
|
||||
exelFile.append('file', file);
|
||||
try {
|
||||
const res = await Axios.post(`/api/v1/white-list/multiPost`, exelFile, {
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data',
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
throw new Error('WhiteListMultiRegsit', e);
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 엑셀 다운로드
|
||||
export const WhiteListExport = async (token, fileName) => {
|
||||
try{
|
||||
await Axios.get(`/api/v1/white-list/excelDownLoad`, {
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
responseType: 'blob',
|
||||
}).then(response => {
|
||||
const href = URL.createObjectURL(response.data);
|
||||
|
||||
const link = document.createElement('a');
|
||||
const fileName = 'Caliverse_whitelist.xlsx';
|
||||
link.href = href;
|
||||
link.setAttribute('download', `${fileName}`);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
|
||||
document.body.removeChild(link);
|
||||
URL.revokeObjectURL(href);
|
||||
})
|
||||
|
||||
}catch(e) {
|
||||
if(e instanceof Error) {
|
||||
throw new Error('WhiteListExport Error', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
14
src/apis/index.js
Normal file
@@ -0,0 +1,14 @@
|
||||
export * from './Admin';
|
||||
export * from './Auth';
|
||||
export * from './Group';
|
||||
export * from './History';
|
||||
export * from './Mail';
|
||||
export * from './Notice';
|
||||
export * from './WhiteList';
|
||||
export * from './BlackList';
|
||||
export * from './Users';
|
||||
export * from './Indicators';
|
||||
export * from './Item';
|
||||
export * from './Event';
|
||||
export * from './Calium';
|
||||
export * from './Land';
|
||||
1
src/assets/data/HourList.js
Normal file
@@ -0,0 +1 @@
|
||||
export const HourList = ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23'];
|
||||
62
src/assets/data/MinuteList.js
Normal file
@@ -0,0 +1,62 @@
|
||||
export const MinuteList = [
|
||||
'00',
|
||||
'01',
|
||||
'02',
|
||||
'03',
|
||||
'04',
|
||||
'05',
|
||||
'06',
|
||||
'07',
|
||||
'08',
|
||||
'09',
|
||||
'10',
|
||||
'11',
|
||||
'12',
|
||||
'13',
|
||||
'14',
|
||||
'15',
|
||||
'16',
|
||||
'17',
|
||||
'18',
|
||||
'19',
|
||||
'20',
|
||||
'21',
|
||||
'22',
|
||||
'23',
|
||||
'24',
|
||||
'25',
|
||||
'26',
|
||||
'27',
|
||||
'28',
|
||||
'29',
|
||||
'30',
|
||||
'31',
|
||||
'32',
|
||||
'33',
|
||||
'34',
|
||||
'35',
|
||||
'36',
|
||||
'37',
|
||||
'38',
|
||||
'39',
|
||||
'40',
|
||||
'41',
|
||||
'42',
|
||||
'43',
|
||||
'44',
|
||||
'45',
|
||||
'46',
|
||||
'47',
|
||||
'48',
|
||||
'49',
|
||||
'50',
|
||||
'51',
|
||||
'52',
|
||||
'53',
|
||||
'54',
|
||||
'55',
|
||||
'56',
|
||||
'57',
|
||||
'58',
|
||||
'59',
|
||||
];
|
||||
8
src/assets/data/adminConstants.js
Normal file
@@ -0,0 +1,8 @@
|
||||
const INITIAL_PAGE_SIZE = 50;
|
||||
const INITIAL_CURRENT_PAGE = 1;
|
||||
const INITIAL_PAGE_LIMIT = 10;
|
||||
export const TYPE_REGISTRY = 'regist';
|
||||
export const TYPE_MODIFY = 'modify';
|
||||
export const NONE = 'NONE';
|
||||
|
||||
export { INITIAL_PAGE_SIZE, INITIAL_CURRENT_PAGE, INITIAL_PAGE_LIMIT };
|
||||
53
src/assets/data/applicator.json
Normal file
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2019-09/schema",
|
||||
"$id": "https://json-schema.org/draft/2019-09/meta/applicator",
|
||||
"$vocabulary": {
|
||||
"https://json-schema.org/draft/2019-09/vocab/applicator": true
|
||||
},
|
||||
"$recursiveAnchor": true,
|
||||
|
||||
"title": "Applicator vocabulary meta-schema",
|
||||
"type": ["object", "boolean"],
|
||||
"properties": {
|
||||
"additionalItems": {"$recursiveRef": "#"},
|
||||
"unevaluatedItems": {"$recursiveRef": "#"},
|
||||
"items": {
|
||||
"anyOf": [{"$recursiveRef": "#"}, {"$ref": "#/$defs/schemaArray"}]
|
||||
},
|
||||
"contains": {"$recursiveRef": "#"},
|
||||
"additionalProperties": {"$recursiveRef": "#"},
|
||||
"unevaluatedProperties": {"$recursiveRef": "#"},
|
||||
"properties": {
|
||||
"type": "object",
|
||||
"additionalProperties": {"$recursiveRef": "#"},
|
||||
"default": {}
|
||||
},
|
||||
"patternProperties": {
|
||||
"type": "object",
|
||||
"additionalProperties": {"$recursiveRef": "#"},
|
||||
"propertyNames": {"format": "regex"},
|
||||
"default": {}
|
||||
},
|
||||
"dependentSchemas": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$recursiveRef": "#"
|
||||
}
|
||||
},
|
||||
"propertyNames": {"$recursiveRef": "#"},
|
||||
"if": {"$recursiveRef": "#"},
|
||||
"then": {"$recursiveRef": "#"},
|
||||
"else": {"$recursiveRef": "#"},
|
||||
"allOf": {"$ref": "#/$defs/schemaArray"},
|
||||
"anyOf": {"$ref": "#/$defs/schemaArray"},
|
||||
"oneOf": {"$ref": "#/$defs/schemaArray"},
|
||||
"not": {"$recursiveRef": "#"}
|
||||
},
|
||||
"$defs": {
|
||||
"schemaArray": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {"$recursiveRef": "#"}
|
||||
}
|
||||
}
|
||||
}
|
||||
64
src/assets/data/data.js
Normal file
@@ -0,0 +1,64 @@
|
||||
export const benItems = [
|
||||
"19010003",
|
||||
"19010001",
|
||||
"19010002",
|
||||
"19010005"
|
||||
];
|
||||
|
||||
export const HourList = ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23'];
|
||||
|
||||
export const MinuteList = [
|
||||
'00', '01', '02', '03', '04', '05', '06', '07', '08', '09',
|
||||
'10', '11', '12', '13', '14', '15', '16', '17', '18', '19',
|
||||
'20', '21', '22', '23', '24', '25', '26', '27', '28', '29',
|
||||
'30', '31', '32', '33', '34', '35', '36', '37', '38', '39',
|
||||
'40', '41', '42', '43', '44', '45', '46', '47', '48', '49',
|
||||
'50', '51', '52', '53', '54', '55', '56', '57', '58', '59',
|
||||
];
|
||||
|
||||
export const months = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'];
|
||||
|
||||
export const caliumRequestInitData = {
|
||||
dept: '',
|
||||
count: 0,
|
||||
content: '',
|
||||
}
|
||||
|
||||
export const STATUS_STYLES = {
|
||||
COMPLETE: {
|
||||
background: '#58AB62',
|
||||
color: 'white'
|
||||
},
|
||||
WAIT: {
|
||||
background: '#DEBB46',
|
||||
color: 'black'
|
||||
},
|
||||
FAIL: {
|
||||
background: '#D33B27',
|
||||
color: 'white'
|
||||
},
|
||||
FINISH: {
|
||||
background: '#D9D9D9',
|
||||
color: 'black'
|
||||
},
|
||||
REJECT: {
|
||||
background: '#D33B27',
|
||||
color: 'white'
|
||||
},
|
||||
CANCEL: {
|
||||
background: '#D33B27',
|
||||
color: 'white'
|
||||
},
|
||||
RESV_START: {
|
||||
background: '#58AB62',
|
||||
color: 'white'
|
||||
},
|
||||
AUCTION_START: {
|
||||
background: '#4287f5',
|
||||
color: 'white'
|
||||
},
|
||||
AUCTION_END: {
|
||||
background: '#A37FB8',
|
||||
color: 'white'
|
||||
},
|
||||
};
|
||||
23
src/assets/data/index.js
Normal file
@@ -0,0 +1,23 @@
|
||||
export {authType, ivenTabType, modalTypes, TabList, tattooSlot, commonStatus, ViewTitleCountType, landAuctionStatusType} from './types'
|
||||
export {
|
||||
mailSendType,
|
||||
mailType,
|
||||
mailSendStatus,
|
||||
mailReceiveType,
|
||||
adminLevelType,
|
||||
logOption,
|
||||
eventStatus,
|
||||
wellType,
|
||||
blockStatus,
|
||||
blockSanctions,
|
||||
blockPeriod,
|
||||
blockType,
|
||||
caliumStatus,
|
||||
landSize,
|
||||
userSearchType,
|
||||
landAuctionStatus,
|
||||
landSearchType,
|
||||
CurrencyType,
|
||||
languageType
|
||||
} from './options'
|
||||
export {benItems, MinuteList, HourList, caliumRequestInitData, STATUS_STYLES, months} from './data'
|
||||
150
src/assets/data/menuConfig.js
Normal file
@@ -0,0 +1,150 @@
|
||||
import { authType } from './types';
|
||||
|
||||
export const menuConfig = {
|
||||
usermanage: {
|
||||
title: '운영자 관리',
|
||||
items: {
|
||||
adminview: {
|
||||
title: '운영자 조회',
|
||||
permissions: {
|
||||
read: authType.adminSearchRead,
|
||||
confirm: authType.adminSearchConfirm,
|
||||
update: authType.adminSearchUpdate,
|
||||
delete: authType.adminSearchDelete
|
||||
}
|
||||
},
|
||||
logview: {
|
||||
title: '사용 이력 조회',
|
||||
permissions: {
|
||||
read: authType.adminLogSearchRead
|
||||
}
|
||||
},
|
||||
authsetting: {
|
||||
title: '권한 설정',
|
||||
permissions: {
|
||||
read: authType.authoritySettingRead,
|
||||
update: authType.authoritySettingUpdate,
|
||||
delete: authType.authoritySettingDelete
|
||||
}
|
||||
},
|
||||
caliumrequest: {
|
||||
title: '칼리움 요청',
|
||||
permissions: {
|
||||
read: authType.caliumRequestRead,
|
||||
update: authType.caliumRequestUpdate
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
indexmanage: {
|
||||
title: '지표 관리',
|
||||
items: {
|
||||
userindex: {
|
||||
title: '유저 지표',
|
||||
permissions: {
|
||||
read: authType.userIndicatorsRead
|
||||
}
|
||||
},
|
||||
economicindex: {
|
||||
title: '경제 지표',
|
||||
permissions: {
|
||||
read: authType.economicIndicatorsRead
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
datamanage: {
|
||||
title: '운영 정보 관리',
|
||||
items: {
|
||||
userview: {
|
||||
title: '유저 조회',
|
||||
permissions: {
|
||||
read: authType.userSearchRead,
|
||||
update: authType.userSearchUpdate,
|
||||
delete: authType.userSearchDelete
|
||||
}
|
||||
},
|
||||
landview: {
|
||||
title: '랜드 조회',
|
||||
permissions: {
|
||||
read: authType.landRead,
|
||||
update: authType.landUpdate,
|
||||
delete: authType.landDelete
|
||||
}
|
||||
},
|
||||
gamelogview: {
|
||||
title: '게임 로그 조회',
|
||||
permissions: {
|
||||
read: authType.gameLogRead
|
||||
}
|
||||
},
|
||||
cryptview: {
|
||||
title: '크립토 조회',
|
||||
permissions: {
|
||||
read: authType.cryptoRead
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
servicemanage: {
|
||||
title: '운영 서비스 관리',
|
||||
items: {
|
||||
board: {
|
||||
title: '인게임 메시지',
|
||||
permissions: {
|
||||
read: authType.inGameRead,
|
||||
update: authType.inGameUpdate,
|
||||
delete: authType.inGameDelete
|
||||
}
|
||||
},
|
||||
mail: {
|
||||
title: '우편',
|
||||
permissions: {
|
||||
read: authType.mailRead,
|
||||
update: authType.mailUpdate,
|
||||
delete: authType.mailDelete
|
||||
}
|
||||
},
|
||||
userblock: {
|
||||
title: '이용자 제재',
|
||||
permissions: {
|
||||
read: authType.blackListRead,
|
||||
update: authType.blackListUpdate,
|
||||
delete: authType.blackListDelete
|
||||
}
|
||||
},
|
||||
reportlist: {
|
||||
title: '신고내역',
|
||||
permissions: {
|
||||
read: authType.reportRead,
|
||||
update: authType.reportUpdate,
|
||||
delete: authType.reportDelete
|
||||
}
|
||||
},
|
||||
event: {
|
||||
title: '보상 이벤트 관리',
|
||||
permissions: {
|
||||
read: authType.eventRead,
|
||||
update: authType.eventUpdate,
|
||||
delete: authType.eventDelete
|
||||
}
|
||||
},
|
||||
landauction: {
|
||||
title: '랜드 경매 관리',
|
||||
permissions: {
|
||||
read: authType.landAuctionRead,
|
||||
update: authType.landAuctionUpdate,
|
||||
delete: authType.landAuctionDelete
|
||||
}
|
||||
},
|
||||
battleevent: {
|
||||
title: '전투시스템 타입 스케줄러',
|
||||
permissions: {
|
||||
read: authType.battleEventRead,
|
||||
update: authType.battleEventUpdate,
|
||||
delete: authType.battleEventDelete
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
198
src/assets/data/options.js
Normal file
@@ -0,0 +1,198 @@
|
||||
export const languageType = [
|
||||
{ value: 'KO', name: '한국어' },
|
||||
{ value: 'EN', name: '영어' },
|
||||
{ value: 'JA', name: '일본어' },
|
||||
];
|
||||
|
||||
export const mailSendType = [
|
||||
{ value: 'ALL', name: '전체' },
|
||||
{ value: 'RESERVE_SEND', name: '예약 발송' },
|
||||
{ value: 'DIRECT_SEND', name: '즉시 발송' },
|
||||
];
|
||||
|
||||
export const mailSendStatus = [
|
||||
{ value: 'ALL', name: '전체' },
|
||||
{ value: 'WAIT', name: '대기' },
|
||||
{ value: 'FINISH', name: '완료' },
|
||||
{ value: 'FAIL', name: '실패' },
|
||||
{ value: 'RUNNING', name: '전송중' },
|
||||
];
|
||||
|
||||
export const mailType = [
|
||||
{ value: 'ALL', name: '전체' },
|
||||
{ value: 'SYSTEM_GUID', name: '시스템 안내' },
|
||||
{ value: 'INSPECTION_COMPENSATION', name: '점검 보상' },
|
||||
{ value: 'RECOVER_COMPENSATION', name: '복구 보상' },
|
||||
{ value: 'EVENT_COMPENSATION', name: '이벤트 보상' },
|
||||
];
|
||||
|
||||
export const mailReceiveType = [
|
||||
{ value: 'ALL', name: '전체' },
|
||||
{ value: 'SINGLE', name: '단일' },
|
||||
{ value: 'MULTIPLE', name: '복수' },
|
||||
];
|
||||
|
||||
export const adminLevelType = [
|
||||
{ value: '0', name: '없음' },
|
||||
{ value: '1', name: 'GM' },
|
||||
{ value: '2', name: 'Super GM' },
|
||||
{ value: '3', name: 'Developer' },
|
||||
]
|
||||
|
||||
export const eventStatus = [
|
||||
{ value: 'ALL', name: '전체' },
|
||||
{ value: 'RUNNING', name: '진행중' },
|
||||
{ value: 'WAIT', name: '대기' },
|
||||
{ value: 'FINISH', name: '완료' },
|
||||
{ value: 'FAIL', name: '실패' },
|
||||
{ value: 'DELETE', name: '삭제' },
|
||||
];
|
||||
|
||||
export const caliumStatus = [
|
||||
{ value: 'ALL', name: '전체' },
|
||||
{ value: 'WAIT', name: '대기중' },
|
||||
{ value: 'COMPLETE', name: '승인완료' },
|
||||
{ value: 'FINISH', name: '충전완료' },
|
||||
{ value: 'REJECT', name: '반려' },
|
||||
{ value: 'FAIL', name: '실패' },
|
||||
];
|
||||
|
||||
export const landAuctionStatus = [
|
||||
{ value: 'ALL', name: '전체' },
|
||||
{ value: 'WAIT', name: '등록완료' },
|
||||
{ value: 'RESV_START', name: '예약시작' },
|
||||
{ value: 'AUCTION_START', name: '경매시작' },
|
||||
{ value: 'AUCTION_END', name: '경매완료' },
|
||||
{ value: 'STL_START', name: '정산시작' },
|
||||
{ value: 'STL_END', name: '정산완료' },
|
||||
{ value: 'CANCEL', name: '취소' },
|
||||
{ value: 'FAIL', name: '실패' },
|
||||
];
|
||||
|
||||
export const wellType = [
|
||||
{ value: '19010001', name: '골드' },
|
||||
{ value: '19010002', name: '사파이어' },
|
||||
{ value: '19010005', name: '루비' },
|
||||
];
|
||||
|
||||
export const logOption = [
|
||||
{ value: 'LOGIN_PERMITTED', name: '로그인 승인' },
|
||||
{ value: 'ADMIN_INFO_UPDATE', name: '운영자 정보 수정' },
|
||||
{ value: 'ADMIN_INFO_DELETE', name: '운영자 정보 삭제' },
|
||||
{ value: 'PASSWORD_INIT', name: '비밀번호 초기화' },
|
||||
{ value: 'USER_INFO_UPDATE', name: '유저 정보 변경' },
|
||||
{ value: 'GROUP_AUTH_UPDATE', name: '그룹 권한 수정' },
|
||||
{ value: 'GROUP_DELETE', name: '그룹 삭제' },
|
||||
{ value: 'NOTICE_DELETE', name: '인게임 메시지 삭제' },
|
||||
{ value: 'MAIL_ADD', name: '우편 등록' },
|
||||
{ value: 'MAIL_UPDATE', name: '우편 수정' },
|
||||
{ value: 'MAIL_DELETE', name: '우편 삭제' },
|
||||
{ value: 'MAIL_SEND_FAIL', name: '우편 전송 실패' },
|
||||
{ value: 'MAIL_SEND', name: '우편 전송' },
|
||||
{ value: 'NOTICE_ADD', name: '공지사항 등록' },
|
||||
{ value: 'NOTICE_UPDATE', name: '공지사항 수정' },
|
||||
{ value: 'NOTICE_DELETE', name: '공지사항 삭제' },
|
||||
{ value: 'NOTICE_SEND_FAIL', name: '공지사항 전송 실패' },
|
||||
{ value: 'WHITELIST_DELETE', name: '화이트리스트 삭제' },
|
||||
{ value: 'BLACKLIST_DELETE', name: '유저 제재 삭제' },
|
||||
{ value: 'REPORT_DELETE', name: '신고내역 삭제' },
|
||||
{ value: 'SCHEDULE_MAIL_FAIL', name: '메일 스케줄 실패' },
|
||||
{ value: 'SCHEDULE_NOTICE_FAIL', name: '공지 스케줄 실패' },
|
||||
{ value: 'USER_MAIL_DELETE', name: '유저 메일 삭제' },
|
||||
{ value: 'USER_ITEM_DELETE', name: '유저 아이템 삭제' },
|
||||
{ value: 'ITEM_DELETE', name: '아이템 삭제' },
|
||||
{ value: 'MAIL_ITEM_DELETE', name: '아이템 삭제' },
|
||||
{ value: 'MAIL_ITEM_UPDATE', name: '아이템 삭제' },
|
||||
{ value: 'INVENTORY_ITEM_DELETE', name: '우편 아이템 삭제' },
|
||||
{ value: 'INVENTORY_ITEM_UPDATE', name: '우편 아이템 수정' },
|
||||
{ value: 'EVENT_ADD', name: '이벤트 등록' },
|
||||
{ value: 'EVENT_UPDATE', name: '이벤트 수정' },
|
||||
{ value: 'EVENT_DELETE', name: '이벤트 삭제' },
|
||||
];
|
||||
|
||||
export const blockStatus = [
|
||||
{ value: 'ALL', name: '전체' },
|
||||
{ value: 'INPROGRESS', name: '제재중' },
|
||||
{ value: 'EXPIRATION', name: '기간만료' },
|
||||
{ value: 'WAIT', name: '대기 중' },
|
||||
{ value: 'FAIL', name: '실패' },
|
||||
];
|
||||
|
||||
export const blockSanctions = [
|
||||
{ value: 'ALL', name: '전체' },
|
||||
{ value: 'Bad_Behavior', name: '비매너 행위' },
|
||||
{ value: 'Inappropriate_Name', name: '불건전 이름 사용' },
|
||||
{ value: 'Cash_Transaction', name: '현금거래 행위' },
|
||||
{ value: 'Game_Interference', name: '게임 진행 방해' },
|
||||
{ value: 'Service_Interference', name: '운영서비스 방해' },
|
||||
{ value: 'Account_Impersonation', name: '계정도용' },
|
||||
{ value: 'Bug_Abuse', name: '버그/어뷰징' },
|
||||
{ value: 'Illegal_Program', name: '불법프로그램 사용' },
|
||||
{ value: 'Personal_Info_Leak', name: '개인정보 유출' },
|
||||
{ value: 'Admin_Impersonation', name: '운영자 사칭' },
|
||||
];
|
||||
|
||||
export const blockPeriod = [
|
||||
{ value: 'ALL', name: '전체' },
|
||||
// { value: 'WARNING', name: '경고' },
|
||||
{ value: 'D1', name: '1일' },
|
||||
{ value: 'D3', name: '3일' },
|
||||
{ value: 'D7', name: '7일' },
|
||||
{ value: 'D15', name: '15일' },
|
||||
{ value: 'D30', name: '30일' },
|
||||
{ value: 'PERMANENT', name: '영구정지' },
|
||||
];
|
||||
|
||||
export const userSearchType = [
|
||||
{ value: 'GUID', name: 'GUID' },
|
||||
{ value: 'NAME', name: '닉네임' },
|
||||
];
|
||||
|
||||
export const landSearchType = [
|
||||
{ value: 'ID', name: '랜드ID' },
|
||||
{ value: 'NAME', name: '랜드명' },
|
||||
];
|
||||
|
||||
export const blockType = [
|
||||
{ value: '', name: '선택' },
|
||||
{ value: 'Access_Restrictions', name: '접근 제한' },
|
||||
// { value: 'Chatting_Restrictions', name: '채팅 제한' },
|
||||
];
|
||||
|
||||
export const landSize = [
|
||||
{ value: 'ALL', name: '전체' },
|
||||
{value: 'SMALL', name: '소형'},
|
||||
{value: 'MEDIUM', name: '중형'},
|
||||
{value: 'LARGE', name: '대형'},
|
||||
{value: 'GIANT', name: '초대형'},
|
||||
]
|
||||
|
||||
export const CurrencyType = [
|
||||
{value: 'Gold', name: '골드' },
|
||||
{value: 'Sapphire', name: '사파이어' },
|
||||
{value: 'Calium', name: '칼리움' },
|
||||
{value: 'Beam', name: 'Beam' },
|
||||
{value: 'Ruby', name: '루비' }
|
||||
]
|
||||
|
||||
export const battleEventStatus = [
|
||||
{ value: 'ALL', name: '전체' },
|
||||
{ value: 'WAIT', name: '중단' },
|
||||
{ value: 'REGISTER', name: '예약완료' },
|
||||
{ value: 'CANCEL', name: '예약취소' },
|
||||
{ value: 'END', name: '종료' },
|
||||
{ value: 'RUNNING', name: '진행중' },
|
||||
{ value: 'FAIL', name: '실패' },
|
||||
];
|
||||
|
||||
export const battleRepeatType = [
|
||||
{ value: 'NONE', name: '없음' },
|
||||
{ value: 'DAY', name: 'Day' },
|
||||
{ value: 'SUNDAY', name: 'Week-일' },
|
||||
{ value: 'MONDAY', name: 'Week-월' },
|
||||
{ value: 'TUESDAY', name: 'Week-화' },
|
||||
{ value: 'WEDNESDAY', name: 'Week-수' },
|
||||
{ value: 'THURSDAY', name: 'Week-목' },
|
||||
{ value: 'FRIDAY', name: 'Week-금' },
|
||||
{ value: 'SATURDAY', name: 'Week-토' },
|
||||
];
|
||||
119
src/assets/data/types.js
Normal file
@@ -0,0 +1,119 @@
|
||||
export const authType = {
|
||||
adminSearchRead: 1,
|
||||
adminSearchConfirm: 2,
|
||||
adminSearchUpdate: 3,
|
||||
adminSearchDelete: 4,
|
||||
adminLogSearchRead: 5,
|
||||
authoritySettingRead: 6,
|
||||
authoritySettingUpdate: 7,
|
||||
authoritySettingDelete: 8,
|
||||
userIndicatorsRead: 9,
|
||||
economicIndicatorsRead: 10,
|
||||
userSearchRead: 11,
|
||||
userSearchUpdate: 12,
|
||||
landRead: 13,
|
||||
gameLogRead: 14,
|
||||
cryptoRead: 15,
|
||||
inGameRead: 16,
|
||||
inGameUpdate: 17,
|
||||
inGameDelete: 18,
|
||||
whiteListRead: 19,
|
||||
whiteListConfirm: 20,
|
||||
whiteListUpdate: 21,
|
||||
mailRead: 22,
|
||||
mailUpdate: 23,
|
||||
blackListRead: 24,
|
||||
blackListUpdate: 25,
|
||||
reportRead: 26,
|
||||
reportUpdate: 27,
|
||||
whiteListDelete: 28,
|
||||
mailDelete: 29,
|
||||
blackListDelete: 30,
|
||||
reportDelete: 31,
|
||||
itemRead: 32,
|
||||
itemUpdate: 33,
|
||||
itemDelete: 34,
|
||||
userSearchDelete: 35,
|
||||
eventRead: 36,
|
||||
eventUpdate: 37,
|
||||
eventDelete: 38,
|
||||
caliumRequestRead: 39,
|
||||
caliumRequestUpdate: 40,
|
||||
landAuctionRead: 41,
|
||||
landAuctionUpdate: 42,
|
||||
landAuctionDelete: 43,
|
||||
landUpdate: 44,
|
||||
landDelete: 45,
|
||||
battleEventRead: 46,
|
||||
battleEventUpdate: 47,
|
||||
battleEventDelete: 48
|
||||
};
|
||||
|
||||
export const TabList = [
|
||||
{ title: '기본정보' },
|
||||
{ title: '아바타' },
|
||||
{ title: '의상' },
|
||||
{ title: '도구' },
|
||||
{ title: '인벤토리' },
|
||||
{ title: '우편' },
|
||||
{ title: '마이홈' },
|
||||
{ title: '친구목록' },
|
||||
{ title: '타투' },
|
||||
{ title: '퀘스트' },
|
||||
// { title: '클레임' },
|
||||
];
|
||||
|
||||
export const ivenTabType = {
|
||||
CLOTH: "cloth",
|
||||
PROP: "prop",
|
||||
BEAUTY: "beauty",
|
||||
TATTOO: "tattoo",
|
||||
CURRENCY: "currency",
|
||||
ETC: "etc"
|
||||
};
|
||||
|
||||
export const modalTypes = {
|
||||
confirmOkCancel: "confirmOkCancel",
|
||||
completed: "completed",
|
||||
childOkCancel: "childOkCancel",
|
||||
}
|
||||
|
||||
export const tattooSlot = {
|
||||
0: "미장착",
|
||||
1: "가슴",
|
||||
2: "왼팔",
|
||||
3: "오른팔"
|
||||
}
|
||||
|
||||
export const commonStatus = {
|
||||
running: "RUNNING",
|
||||
wait: "WAIT",
|
||||
finish: "FINISH",
|
||||
fail: "FAIL",
|
||||
delete: "DELETE",
|
||||
reject: "REJECT",
|
||||
complete: "COMPLETE",
|
||||
}
|
||||
|
||||
export const ViewTitleCountType = {
|
||||
total: "total",
|
||||
calium: "calium",
|
||||
}
|
||||
|
||||
export const landAuctionStatusType = {
|
||||
wait: "WAIT",
|
||||
resv_start: "RESV_START",
|
||||
auction_start: "AUCTION_START",
|
||||
auction_end: "AUCTION_END",
|
||||
stl_end: "STL_END",
|
||||
fail: "FAIL",
|
||||
cancel: "CANCEL",
|
||||
}
|
||||
|
||||
export const battleEventStatusType = {
|
||||
wait: "WAIT",
|
||||
register: "REGISTER",
|
||||
end: "END",
|
||||
fail: "FAIL",
|
||||
cancel: "CANCEL",
|
||||
}
|
||||
BIN
src/assets/img/datamanage/img-profile.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
src/assets/img/icon/icon-add.png
Normal file
|
After Width: | Height: | Size: 366 B |
BIN
src/assets/img/icon/icon-arrow.png
Normal file
|
After Width: | Height: | Size: 221 B |
BIN
src/assets/img/icon/icon-chk.png
Normal file
|
After Width: | Height: | Size: 523 B |
BIN
src/assets/img/icon/icon-close.png
Normal file
|
After Width: | Height: | Size: 248 B |
BIN
src/assets/img/icon/icon-date.png
Normal file
|
After Width: | Height: | Size: 479 B |
BIN
src/assets/img/icon/icon-delete.png
Normal file
|
After Width: | Height: | Size: 232 B |
BIN
src/assets/img/icon/icon-down.png
Normal file
|
After Width: | Height: | Size: 243 B |
BIN
src/assets/img/icon/icon-edit.png
Normal file
|
After Width: | Height: | Size: 381 B |
BIN
src/assets/img/icon/icon-pagination.png
Normal file
|
After Width: | Height: | Size: 941 B |
BIN
src/assets/img/icon/icon-profile.png
Normal file
|
After Width: | Height: | Size: 679 B |
BIN
src/assets/img/icon/icon-radio.png
Normal file
|
After Width: | Height: | Size: 410 B |
BIN
src/assets/img/icon/icon-reset.png
Normal file
|
After Width: | Height: | Size: 419 B |
BIN
src/assets/img/icon/icon-select.png
Normal file
|
After Width: | Height: | Size: 260 B |
BIN
src/assets/img/icon/icon-select2.png
Normal file
|
After Width: | Height: | Size: 252 B |
BIN
src/assets/img/icon/icon-tab.png
Normal file
|
After Width: | Height: | Size: 244 B |
BIN
src/assets/img/icon/icon-title.png
Normal file
|
After Width: | Height: | Size: 249 B |
BIN
src/assets/img/icon/icon-up.png
Normal file
|
After Width: | Height: | Size: 218 B |
1
src/assets/img/img.js
Normal file
@@ -0,0 +1 @@
|
||||
// 이미지 및 기타 common 파일을 관리하는 폴더입니다. 이 파일은 삭제하셔도 됩니다.
|
||||
BIN
src/assets/img/login-bg.png
Normal file
|
After Width: | Height: | Size: 1002 KiB |
BIN
src/assets/img/logo-main.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
54
src/assets/img/logo-white.svg
Normal file
@@ -0,0 +1,54 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="205.252" height="18.971" viewBox="0 0 205.252 18.971">
|
||||
<defs>
|
||||
<clipPath id="clip-path">
|
||||
<rect id="사각형_21" data-name="사각형 21" width="205.252" height="18.97" fill="none"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip-path-2">
|
||||
<rect id="사각형_20" data-name="사각형 20" width="205.252" height="18.971" fill="none"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip-path-3">
|
||||
<rect id="사각형_15" data-name="사각형 15" height="0.018" fill="none"/>
|
||||
</clipPath>
|
||||
<clipPath id="clip-path-4">
|
||||
<rect id="사각형_18" data-name="사각형 18" width="0.014" fill="none"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g id="logo" clip-path="url(#clip-path)">
|
||||
<g id="그룹_26" data-name="그룹 26">
|
||||
<g id="그룹_25" data-name="그룹 25" clip-path="url(#clip-path-2)">
|
||||
<g id="그룹_18" data-name="그룹 18" transform="translate(52.923 14.805)" opacity="0.49">
|
||||
<g id="그룹_17" data-name="그룹 17">
|
||||
<g id="그룹_16" data-name="그룹 16" clip-path="url(#clip-path-3)">
|
||||
<path id="패스_33" data-name="패스 33" d="M124.094,34.722h0" transform="translate(-124.094 -34.713)" fill="#fff"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<path id="패스_34" data-name="패스 34" d="M437.325,34.705a.138.138,0,0,0,0,.014s0,.009,0,.013Z" transform="translate(-250.815 -19.903)" fill="#fff"/>
|
||||
<path id="패스_35" data-name="패스 35" d="M3.253,4.727v6.247a1.561,1.561,0,0,0,1.561,1.539H18.87v3.145H4.815A4.812,4.812,0,0,1,0,10.974V4.727A4.8,4.8,0,0,1,4.815.043H18.87V3.166H4.815A1.581,1.581,0,0,0,3.253,4.727" transform="translate(0 -0.025)" fill="#fff"/>
|
||||
<path id="패스_36" data-name="패스 36" d="M79.687,15.659H76.449L73.78,10.974H63.228l-2.666,4.685h-3.24L65.35,1.56A2.483,2.483,0,0,1,67.6.043H69.41A2.483,2.483,0,0,1,71.66,1.56ZM72,7.851,69.5,3.444a.507.507,0,0,0-.452-.277H67.963a.508.508,0,0,0-.452.277L65,7.851Z" transform="translate(-32.875 -0.025)" fill="#fff"/>
|
||||
<rect id="사각형_17" data-name="사각형 17" width="3.111" height="15.591" transform="translate(76.816 0.036)" fill="#fff"/>
|
||||
<g id="그룹_21" data-name="그룹 21" transform="translate(56.501 15.634)" opacity="0.49">
|
||||
<g id="그룹_20" data-name="그룹 20">
|
||||
<g id="그룹_19" data-name="그룹 19" clip-path="url(#clip-path-4)">
|
||||
<path id="패스_37" data-name="패스 37" d="M132.489,36.657h0" transform="translate(-132.483 -36.657)" fill="#fff"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g id="그룹_24" data-name="그룹 24" transform="translate(52.923 12.04)" opacity="0.49">
|
||||
<g id="그룹_23" data-name="그룹 23">
|
||||
<g id="그룹_22" data-name="그룹 22" clip-path="url(#clip-path-3)">
|
||||
<path id="패스_38" data-name="패스 38" d="M124.094,28.238h0" transform="translate(-124.094 -28.229)" fill="#fff"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<path id="패스_39" data-name="패스 39" d="M130,12.428h-2.691a1.211,1.211,0,0,1-1.211-1.211V.071h-3.245V12.1a3.584,3.584,0,0,0,3.578,3.575h15.264V12.427Z" transform="translate(-70.455 -0.041)" fill="#fff"/>
|
||||
<line id="선_1" data-name="선 1" x1="3.227" transform="translate(153.249 15.622)" fill="#fff"/>
|
||||
<path id="패스_40" data-name="패스 40" d="M338.858,10.089a3.566,3.566,0,0,0,2.6-3.2V3.4A3.584,3.584,0,0,0,337.979.053H322.564v15.6h3.11V10.233h10.019l.427.75,2.668,4.683h3.245ZM325.675,7.1V3.18h10.951A1.578,1.578,0,0,1,338.2,4.758v.775a1.577,1.577,0,0,1-1.577,1.578H325.675Z" transform="translate(-184.998 -0.03)" fill="#fff"/>
|
||||
<path id="패스_41" data-name="패스 41" d="M395.4,6.291H384.737a1.551,1.551,0,1,1,.039-3.1h14.062V.053H383.419A3.583,3.583,0,0,0,379.937,3.4V6.075a1.688,1.688,0,0,0,.026.213,3.575,3.575,0,0,0,3.416,3.132h10.663a1.551,1.551,0,1,1-.039,3.1H379.941v3.127h15.415a3.584,3.584,0,0,0,3.482-3.344V9.632a1.688,1.688,0,0,0-.026-.213A3.575,3.575,0,0,0,395.4,6.291" transform="translate(-217.903 -0.03)" fill="#fff"/>
|
||||
<path id="패스_42" data-name="패스 42" d="M270.271,3.164H284.3V3.132h0V0H269.09a3.523,3.523,0,0,0-3.5,3.132h.01a3.622,3.622,0,0,0-.035.47V12.02a3.622,3.622,0,0,0,.035.47h-.01a3.523,3.523,0,0,0,3.5,3.132h15.216V12.491h0V12.46H270.271a1.6,1.6,0,0,1-1.6-1.6V9.328h15.631V6.292H268.675V4.76a1.6,1.6,0,0,1,1.6-1.6" transform="translate(-152.307)" fill="#fff"/>
|
||||
<path id="패스_43" data-name="패스 43" d="M219.551,0h0L211.6,1.839,203.665,0h-3.143V8.638A1.8,1.8,0,0,0,201.15,10l10.457,8.966L222.065,10a1.8,1.8,0,0,0,.628-1.366V0ZM203.665.332l7.783,1.8V14.79l-7.783-6.672Zm8.1,14.458V2.131l7.783-1.8V8.118Z" transform="translate(-115.003 0.001)" fill="#fff"/>
|
||||
<path id="패스_44" data-name="패스 44" d="M442.031,3.164h14.032V3.132h0V0H440.85a3.523,3.523,0,0,0-3.5,3.132h.01a3.622,3.622,0,0,0-.035.47V12.02a3.633,3.633,0,0,0,.035.47h-.01a3.523,3.523,0,0,0,3.5,3.132h15.216V12.491h0V12.46H442.031a1.6,1.6,0,0,1-1.6-1.6V9.328h15.631V6.292H440.435V4.76a1.6,1.6,0,0,1,1.6-1.6" transform="translate(-250.815)" fill="#fff"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.1 KiB |
BIN
src/assets/img/logo.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
198
src/components/DataManage/CreditLogSearchBar.js
Normal file
@@ -0,0 +1,198 @@
|
||||
import { styled } from 'styled-components';
|
||||
import { useState } from 'react';
|
||||
|
||||
import Button from '../../components/common/button/Button';
|
||||
|
||||
import DatePicker, { registerLocale } from 'react-datepicker';
|
||||
import 'react-datepicker/dist/react-datepicker.css';
|
||||
import { getMonth, getYear } from 'date-fns';
|
||||
import range from 'lodash/range';
|
||||
|
||||
import { TextInput, SelectInput, DatePickerWrapper, InputLabel, BtnWrapper } from '../../styles/Components';
|
||||
|
||||
const GoodsLogSearchBar = () => {
|
||||
const [startDate, setStartDate] = useState(new Date());
|
||||
const [endDate, setEndDate] = useState(new Date());
|
||||
const [selectData, setSelectData] = useState('default');
|
||||
const years = range(1990, getYear(new Date()) + 1, 1);
|
||||
const months = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'];
|
||||
|
||||
const handleChange = e => {
|
||||
setSelectData(e.target.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchbarStyle2>
|
||||
<SearchRow>
|
||||
<SearchItem>
|
||||
<InputLabel>조회 기간</InputLabel>
|
||||
<DatePickerWrapper>
|
||||
<InputGroup>
|
||||
<DatePicker
|
||||
selected={startDate}
|
||||
onChange={date => setStartDate(date)}
|
||||
className="datepicker"
|
||||
placeholderText="검색기간 선택"
|
||||
calendarClassName="calendar"
|
||||
dateFormat="yyyy - MM - dd"
|
||||
locale="ko"
|
||||
renderCustomHeader={({ date, changeYear, changeMonth, decreaseMonth, increaseMonth, prevMonthButtonDisabled, nextMonthButtonDisabled }) => (
|
||||
<div className="calendar-top">
|
||||
<button
|
||||
className="btn-prev"
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
decreaseMonth();
|
||||
}}
|
||||
disabled={prevMonthButtonDisabled}></button>
|
||||
<select value={getYear(date)} onChange={({ target: { value } }) => changeYear(value)}>
|
||||
{years.map(option => (
|
||||
<option key={option} value={option}>
|
||||
{option}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
.
|
||||
<select value={months[getMonth(date)]} onChange={({ target: { value } }) => changeMonth(months.indexOf(value))}>
|
||||
{months.map(option => (
|
||||
<option key={option} value={option}>
|
||||
{option}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<button
|
||||
className="btn-next"
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
increaseMonth();
|
||||
}}
|
||||
disabled={nextMonthButtonDisabled}></button>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<SelectInput>
|
||||
<option value="">00</option>
|
||||
<option value="">01</option>
|
||||
</SelectInput>
|
||||
<SelectInput>
|
||||
<option value="">00</option>
|
||||
<option value="">01</option>
|
||||
</SelectInput>
|
||||
</InputGroup>
|
||||
<span>~</span>
|
||||
<InputGroup>
|
||||
<DatePicker
|
||||
selected={endDate}
|
||||
onChange={date => setEndDate(date)}
|
||||
className="datepicker"
|
||||
placeholderText="검색기간 선택"
|
||||
calendarClassName="calendar"
|
||||
dateFormat="yyyy - MM - dd"
|
||||
minDate = {startDate}
|
||||
locale="ko"
|
||||
renderCustomHeader={({ date, changeYear, changeMonth, decreaseMonth, increaseMonth, prevMonthButtonDisabled, nextMonthButtonDisabled }) => (
|
||||
<div className="calendar-top">
|
||||
<button
|
||||
className="btn-prev"
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
decreaseMonth();
|
||||
}}
|
||||
disabled={prevMonthButtonDisabled}></button>
|
||||
<select value={getYear(date)} onChange={({ target: { value } }) => changeYear(value)}>
|
||||
{years.map(option => (
|
||||
<option key={option} value={option}>
|
||||
{option}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
.
|
||||
<select value={months[getMonth(date)]} onChange={({ target: { value } }) => changeMonth(months.indexOf(value))}>
|
||||
{months.map(option => (
|
||||
<option key={option} value={option}>
|
||||
{option}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<button
|
||||
className="btn-next"
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
increaseMonth();
|
||||
}}
|
||||
disabled={nextMonthButtonDisabled}></button>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<SelectInput>
|
||||
<option value="">00</option>
|
||||
<option value="">01</option>
|
||||
</SelectInput>
|
||||
<SelectInput>
|
||||
<option value="">00</option>
|
||||
<option value="">01</option>
|
||||
</SelectInput>
|
||||
</InputGroup>
|
||||
</DatePickerWrapper>
|
||||
</SearchItem>
|
||||
</SearchRow>
|
||||
<SearchRow>
|
||||
<SearchItem>
|
||||
<InputLabel>조회 대상</InputLabel>
|
||||
<TextInput type="text" placeholder="조회 대상 유저의 GUID를 입력하세요." width="600px" />
|
||||
</SearchItem>
|
||||
<BtnWrapper $gap="8px">
|
||||
<Button theme="reset" />
|
||||
<Button theme="gray" text="검색" />
|
||||
</BtnWrapper>
|
||||
</SearchRow>
|
||||
</SearchbarStyle2>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default GoodsLogSearchBar;
|
||||
|
||||
const SearchbarStyle = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20px 0;
|
||||
font-size: 14px;
|
||||
padding: 20px;
|
||||
border-top: 1px solid #000;
|
||||
border-bottom: 1px solid #000;
|
||||
margin-bottom: 40px;
|
||||
`;
|
||||
const SearchbarStyle2 = styled(SearchbarStyle)`
|
||||
flex-flow: column;
|
||||
gap: 20px;
|
||||
`;
|
||||
|
||||
const SearchRow = styled.div`
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20px 0;
|
||||
`;
|
||||
|
||||
const InputGroup = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
`;
|
||||
|
||||
const SearchItem = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
margin-right: 50px;
|
||||
|
||||
${TextInput}, ${SelectInput} {
|
||||
height: 35px;
|
||||
}
|
||||
${TextInput} {
|
||||
padding: 0 10px;
|
||||
max-width: 400px;
|
||||
}
|
||||
`;
|
||||
219
src/components/DataManage/ItemLogSearchBar.js
Normal file
@@ -0,0 +1,219 @@
|
||||
import { useState } from 'react';
|
||||
import { styled } from 'styled-components';
|
||||
|
||||
import RadioInput from '../common/input/Radio';
|
||||
import Button from '../common/button/Button';
|
||||
|
||||
import DatePicker, { registerLocale } from 'react-datepicker';
|
||||
import { ko } from 'date-fns/esm/locale';
|
||||
import 'react-datepicker/dist/react-datepicker.css';
|
||||
import { getMonth, getYear } from 'date-fns';
|
||||
import range from 'lodash/range';
|
||||
|
||||
import { TextInput, SelectInput, DatePickerWrapper, InputLabel, BtnWrapper } from '../../styles/Components';
|
||||
|
||||
const ItemLogSearchBar = () => {
|
||||
const [startDate, setStartDate] = useState(new Date());
|
||||
const [endDate, setEndDate] = useState(new Date());
|
||||
const [selectData, setSelectData] = useState('default');
|
||||
const years = range(1990, getYear(new Date()) + 1, 1);
|
||||
const months = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'];
|
||||
|
||||
const handleChange = e => {
|
||||
setSelectData(e.target.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchbarStyle2>
|
||||
<SearchRow>
|
||||
<RadioGroup>
|
||||
<RadioInput label="기본 조회" id="single" name="receiver" value="default" fontWeight="600" checked={selectData === 'default'} handleChange={handleChange} />
|
||||
<RadioInput label="아이템 소유자 추적" id="multi" name="receiver" value="item" fontWeight="600" checked={selectData === 'item'} handleChange={handleChange} />
|
||||
</RadioGroup>
|
||||
</SearchRow>
|
||||
<SearchRow>
|
||||
<SearchItem>
|
||||
<InputLabel>조회 기간</InputLabel>
|
||||
<DatePickerWrapper>
|
||||
<InputGroup>
|
||||
<DatePicker
|
||||
selected={startDate}
|
||||
onChange={date => setStartDate(date)}
|
||||
className="datepicker"
|
||||
placeholderText="검색기간 선택"
|
||||
calendarClassName="calendar"
|
||||
dateFormat="yyyy - MM - dd"
|
||||
locale="ko"
|
||||
renderCustomHeader={({ date, changeYear, changeMonth, decreaseMonth, increaseMonth, prevMonthButtonDisabled, nextMonthButtonDisabled }) => (
|
||||
<div className="calendar-top">
|
||||
<button
|
||||
className="btn-prev"
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
decreaseMonth();
|
||||
}}
|
||||
disabled={prevMonthButtonDisabled}></button>
|
||||
<select value={getYear(date)} onChange={({ target: { value } }) => changeYear(value)}>
|
||||
{years.map(option => (
|
||||
<option key={option} value={option}>
|
||||
{option}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
.
|
||||
<select value={months[getMonth(date)]} onChange={({ target: { value } }) => changeMonth(months.indexOf(value))}>
|
||||
{months.map(option => (
|
||||
<option key={option} value={option}>
|
||||
{option}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<button
|
||||
className="btn-next"
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
increaseMonth();
|
||||
}}
|
||||
disabled={nextMonthButtonDisabled}></button>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<SelectInput>
|
||||
<option value="">00</option>
|
||||
<option value="">01</option>
|
||||
</SelectInput>
|
||||
<SelectInput>
|
||||
<option value="">00</option>
|
||||
<option value="">01</option>
|
||||
</SelectInput>
|
||||
</InputGroup>
|
||||
<span>~</span>
|
||||
<InputGroup>
|
||||
<DatePicker
|
||||
selected={endDate}
|
||||
onChange={date => setEndDate(date)}
|
||||
className="datepicker"
|
||||
placeholderText="검색기간 선택"
|
||||
calendarClassName="calendar"
|
||||
dateFormat="yyyy - MM - dd"
|
||||
minDate = {startDate}
|
||||
locale="ko"
|
||||
renderCustomHeader={({ date, changeYear, changeMonth, decreaseMonth, increaseMonth, prevMonthButtonDisabled, nextMonthButtonDisabled }) => (
|
||||
<div className="calendar-top">
|
||||
<button
|
||||
className="btn-prev"
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
decreaseMonth();
|
||||
}}
|
||||
disabled={prevMonthButtonDisabled}></button>
|
||||
<select value={getYear(date)} onChange={({ target: { value } }) => changeYear(value)}>
|
||||
{years.map(option => (
|
||||
<option key={option} value={option}>
|
||||
{option}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
.
|
||||
<select value={months[getMonth(date)]} onChange={({ target: { value } }) => changeMonth(months.indexOf(value))}>
|
||||
{months.map(option => (
|
||||
<option key={option} value={option}>
|
||||
{option}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<button
|
||||
className="btn-next"
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
increaseMonth();
|
||||
}}
|
||||
disabled={nextMonthButtonDisabled}></button>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<SelectInput>
|
||||
<option value="">00</option>
|
||||
<option value="">01</option>
|
||||
</SelectInput>
|
||||
<SelectInput>
|
||||
<option value="">00</option>
|
||||
<option value="">01</option>
|
||||
</SelectInput>
|
||||
</InputGroup>
|
||||
</DatePickerWrapper>
|
||||
</SearchItem>
|
||||
</SearchRow>
|
||||
<SearchRow>
|
||||
{selectData === 'default' ? (
|
||||
<SearchItem>
|
||||
<InputLabel>조회 대상</InputLabel>
|
||||
<TextInput type="text" placeholder="조회 대상 유저의 GUID를 입력하세요." width="600px" />
|
||||
</SearchItem>
|
||||
) : (
|
||||
<SearchItem>
|
||||
<InputLabel>아이템 ID</InputLabel>
|
||||
<TextInput type="text" placeholder="아이템의 GUID를 입력하세요." width="600px" />
|
||||
</SearchItem>
|
||||
)}
|
||||
|
||||
<BtnWrapper $gap="8px">
|
||||
<Button theme="reset" />
|
||||
<Button theme="gray" text="검색" />
|
||||
</BtnWrapper>
|
||||
</SearchRow>
|
||||
</SearchbarStyle2>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default ItemLogSearchBar;
|
||||
|
||||
const SearchbarStyle = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20px 0;
|
||||
font-size: 14px;
|
||||
padding: 20px;
|
||||
border-top: 1px solid #000;
|
||||
border-bottom: 1px solid #000;
|
||||
margin-bottom: 40px;
|
||||
`;
|
||||
const SearchbarStyle2 = styled(SearchbarStyle)`
|
||||
flex-flow: column;
|
||||
gap: 20px;
|
||||
`;
|
||||
|
||||
const SearchRow = styled.div`
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20px 0;
|
||||
`;
|
||||
|
||||
const InputGroup = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
`;
|
||||
|
||||
const RadioGroup = styled(InputGroup)`
|
||||
gap: 30px;
|
||||
height: 35px;
|
||||
`;
|
||||
|
||||
const SearchItem = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
margin-right: 50px;
|
||||
|
||||
${TextInput}, ${SelectInput} {
|
||||
height: 35px;
|
||||
}
|
||||
${TextInput} {
|
||||
padding: 0 10px;
|
||||
max-width: 400px;
|
||||
}
|
||||
`;
|
||||
79
src/components/DataManage/LandDetailModal.js
Normal file
@@ -0,0 +1,79 @@
|
||||
import { styled } from 'styled-components';
|
||||
|
||||
import { Title } from '../../styles/Components';
|
||||
import { BtnWrapper, TableStyle } from '../../styles/Components';
|
||||
import Button from '../../components/common/button/Button';
|
||||
import Modal from '../../components/common/modal/Modal';
|
||||
import { Fragment } from 'react';
|
||||
|
||||
const LandDetailModal = ({ detailPop, handleClick }) => {
|
||||
const landlist = [
|
||||
{ floor: '1', instanceId: 'ad31230001' },
|
||||
{ floor: '2', instanceId: 'ad31230001' },
|
||||
];
|
||||
return (
|
||||
<>
|
||||
<Modal $view={detailPop} min="480px">
|
||||
<Title $align="center">랜드 상세정보</Title>
|
||||
<TableWrapper>
|
||||
<TableStyle>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="100">층 정보</th>
|
||||
<th>인스턴스 연결 정보</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{landlist.map((el, index) => {
|
||||
return (
|
||||
<Fragment key={index}>
|
||||
<tr>
|
||||
<td>{el.floor}</td>
|
||||
<InstanceData>{el.instanceId}</InstanceData>
|
||||
</tr>
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</TableStyle>
|
||||
</TableWrapper>
|
||||
<BtnWrapper2 $justify="center">
|
||||
<Button
|
||||
theme="line"
|
||||
text="확인"
|
||||
handleClick={e => {
|
||||
e.preventDefault();
|
||||
handleClick();
|
||||
}}
|
||||
/>
|
||||
</BtnWrapper2>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default LandDetailModal;
|
||||
|
||||
const InstanceData = styled.td``;
|
||||
|
||||
const TableWrapper = styled.div`
|
||||
max-height: 50vh;
|
||||
max-width: 600px;
|
||||
overflow: auto;
|
||||
${InstanceData} {
|
||||
text-align: left;
|
||||
}
|
||||
&::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #666666;
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
background: #d9d9d9;
|
||||
}
|
||||
`;
|
||||
|
||||
const BtnWrapper2 = styled(BtnWrapper)`
|
||||
margin-top: 30px;
|
||||
`;
|
||||
57
src/components/DataManage/LandSearchBar.js
Normal file
@@ -0,0 +1,57 @@
|
||||
import { styled } from 'styled-components';
|
||||
import Button from '../../components/common/button/Button';
|
||||
|
||||
import { FormWrapper, InputLabel, TextInput, SelectInput, BtnWrapper } from '../../styles/Components';
|
||||
|
||||
const LandSearchBar = () => {
|
||||
return (
|
||||
<>
|
||||
<FormWrapper>
|
||||
<SearchbarStyle>
|
||||
<SearchItem>
|
||||
<InputLabel>랜드 조회</InputLabel>
|
||||
<TextInput type="text" width="300px" placeholder="랜드 ID를 입력하세요." />
|
||||
</SearchItem>
|
||||
<BtnWrapper $gap="8px">
|
||||
<Button theme="reset" />
|
||||
<Button
|
||||
theme="gray"
|
||||
text="검색"
|
||||
handleClick={e => {
|
||||
e.preventDefault();
|
||||
}}
|
||||
/>
|
||||
</BtnWrapper>
|
||||
</SearchbarStyle>
|
||||
</FormWrapper>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default LandSearchBar;
|
||||
|
||||
const SearchbarStyle = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20px 0;
|
||||
font-size: 14px;
|
||||
padding: 20px;
|
||||
border-top: 1px solid #000;
|
||||
border-bottom: 1px solid #000;
|
||||
margin-bottom: 40px;
|
||||
`;
|
||||
const SearchItem = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
margin-right: 50px;
|
||||
|
||||
${TextInput}, ${SelectInput} {
|
||||
height: 35px;
|
||||
}
|
||||
${TextInput} {
|
||||
padding: 0 10px;
|
||||
max-width: 400px;
|
||||
}
|
||||
`;
|
||||
141
src/components/DataManage/MailDetailModal.js
Normal file
@@ -0,0 +1,141 @@
|
||||
import { styled } from 'styled-components';
|
||||
import Button from '../../components/common/button/Button';
|
||||
import Modal from '../common/modal/Modal';
|
||||
|
||||
import { TextInput, BtnWrapper} from '../../styles/Components';
|
||||
import { Textarea, Title } from '../../styles/Components';
|
||||
import CDivider from '../common/CDivider';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import IconDelete from '../../assets/img/icon/icon-delete.png';
|
||||
|
||||
const MailDetailModal = ({ mailModal, handleClick, setDetail, content, handleDelete, handleItemDelete, authDelete }) => {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<>
|
||||
<Modal $view={mailModal}>
|
||||
<Title $align="center">우편 상세 정보</Title>
|
||||
<MailDetailTable>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th width="120">제목</th>
|
||||
<td>
|
||||
<TextInput defaultValue={content.title}></TextInput>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>내용</th>
|
||||
<td>
|
||||
<Textarea defaultValue={content.content}></Textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>아이템 첨부</th>
|
||||
<td>
|
||||
<div>
|
||||
{content.item_list && (
|
||||
<ItemList>
|
||||
{content &&
|
||||
content.item_list.map((data, index) => {
|
||||
return (
|
||||
<Item key={index}>
|
||||
<span>
|
||||
{data.item_name}({data.count})
|
||||
</span>
|
||||
<BtnDelete onClick={() => handleItemDelete(data)} disabled={!authDelete}></BtnDelete>
|
||||
{content && content.is_reserve === false}
|
||||
</Item>
|
||||
);
|
||||
})}
|
||||
</ItemList>
|
||||
)}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</MailDetailTable>
|
||||
<BtnWrapper $justify="center">
|
||||
<Button
|
||||
theme={authDelete ? "line" : "disable"}
|
||||
text="삭제"
|
||||
handleClick={handleDelete}
|
||||
disabled={!authDelete}
|
||||
/>
|
||||
<CDivider />
|
||||
<Button
|
||||
theme="line"
|
||||
text="확인"
|
||||
handleClick={e => {
|
||||
e.preventDefault();
|
||||
handleClick();
|
||||
setDetail({ title: '', content: '', item_list: [] });
|
||||
}}
|
||||
/>
|
||||
</BtnWrapper>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default MailDetailModal;
|
||||
|
||||
const MailDetailTable = styled.table`
|
||||
max-width: 800px;
|
||||
margin-bottom: 30px;
|
||||
tr:first-child {
|
||||
th,
|
||||
td {
|
||||
border-top: 1px solid #000;
|
||||
}
|
||||
}
|
||||
th {
|
||||
font-weight: 700;
|
||||
vertical-align: top;
|
||||
line-height: 30px;
|
||||
}
|
||||
th,
|
||||
td {
|
||||
padding: 15px;
|
||||
border-bottom: 1px solid #d9d9d9;
|
||||
}
|
||||
tr:last-child {
|
||||
th,
|
||||
td {
|
||||
border-bottom: 1px solid #000;
|
||||
}
|
||||
}
|
||||
td {
|
||||
textarea {
|
||||
border: 1px solid #e0e0e0;
|
||||
width: 100%;
|
||||
border-radius: 5px;
|
||||
min-height: 200px;
|
||||
&::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #666666;
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
background: #d9d9d9;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const ItemList = styled.ul`
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
padding: 10px;
|
||||
flex-wrap: wrap;
|
||||
`;
|
||||
|
||||
const Item = styled.li`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const BtnDelete = styled.button`
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
background: url(${IconDelete}) 50% 50% no-repeat;
|
||||
`;
|
||||
129
src/components/DataManage/NicknameChangeModal.js
Normal file
@@ -0,0 +1,129 @@
|
||||
import { styled } from 'styled-components';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { Title } from '../../styles/Components';
|
||||
import { TextInput, BtnWrapper, ButtonClose, ModalText } from '../../styles/Components';
|
||||
import Button from '../../components/common/button/Button';
|
||||
import Modal from '../../components/common/modal/Modal';
|
||||
import { UserChangeNickName } from '../../apis';
|
||||
|
||||
const NicknameChangeModal = ({ pwPop, handleClick, dataList }) => {
|
||||
let nickName = dataList.char_info && dataList.char_info.character_name;
|
||||
const [modifyModal, setModifyModal] = useState('hidden');
|
||||
const [completeModal, setCompleteModal] = useState('hidden');
|
||||
const [completeText, setCompleteText] = useState('');
|
||||
|
||||
const [resultData, setResultData] = useState({
|
||||
guid: '',
|
||||
nickname: '',
|
||||
new_nickname: '',
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setResultData({ ...resultData, guid: dataList.user_info && dataList.user_info.aid, nickname: dataList.char_info && dataList.char_info.character_name });
|
||||
}, [dataList]);
|
||||
|
||||
// 수정 모달창
|
||||
const handleModifyModal = () => {
|
||||
if (modifyModal === 'hidden') {
|
||||
setModifyModal('view');
|
||||
} else {
|
||||
setModifyModal('hidden');
|
||||
}
|
||||
};
|
||||
|
||||
// 완료 모달창
|
||||
const handleCompleteModal = () => {
|
||||
if (completeModal === 'hidden') {
|
||||
setCompleteModal('view');
|
||||
} else {
|
||||
setCompleteModal('hidden');
|
||||
|
||||
handleClick();
|
||||
completeText === '변경이 완료되었습니다.' && window.location.reload();
|
||||
}
|
||||
};
|
||||
|
||||
// 수정
|
||||
const handleModifyNotice = async () => {
|
||||
const token = sessionStorage.getItem('token');
|
||||
|
||||
const message = await UserChangeNickName(token, resultData);
|
||||
|
||||
// console.log(message);
|
||||
message.data.data.message !== '수정 하였습니다.' ? setCompleteText('변경 닉네임이 이미 존재합니다.\n다시 시도해주세요.') : setCompleteText('변경이 완료되었습니다.');
|
||||
|
||||
handleCompleteModal();
|
||||
handleModifyModal();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal $view={pwPop} min="480px">
|
||||
<Title $align="center">닉네임 변경</Title>
|
||||
<PwSetTable>
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>기존 닉네임</th>
|
||||
<td>{nickName}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>변경 닉네임</th>
|
||||
<td>
|
||||
<TextInput placeholder="닉네임을 입력하세요." onChange={e => setResultData({ ...resultData, new_nickname: e.target.value })} maxLength={12} />
|
||||
<ChangeNotice>* 최대 12글자까지 가능합니다.</ChangeNotice>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</PwSetTable>
|
||||
<BtnWrapper $justify="center" $gap="10px">
|
||||
<Button theme="line" text="취소" handleClick={handleClick} />
|
||||
<Button theme="primary" text="변경하기" handleClick={handleModifyModal} />
|
||||
</BtnWrapper>
|
||||
</Modal>
|
||||
|
||||
{/* 확인 모달 */}
|
||||
<Modal min="440px" $padding="40px" $bgcolor="transparent" $view={modifyModal}>
|
||||
<BtnWrapper $justify="flex-end">
|
||||
<ButtonClose onClick={handleModifyModal} />
|
||||
</BtnWrapper>
|
||||
<ModalText $align="center">닉네임을 변경하시겠습니까?</ModalText>
|
||||
<BtnWrapper $gap="10px">
|
||||
<Button text="취소" theme="line" size="large" width="100%" handleClick={handleModifyModal} />
|
||||
<Button text="확인" theme="primary" type="submit" size="large" width="100%" handleClick={handleModifyNotice} />
|
||||
</BtnWrapper>
|
||||
</Modal>
|
||||
{/* 완료 모달 */}
|
||||
<Modal min="440px" $padding="40px" $bgcolor="transparent" $view={completeModal}>
|
||||
<BtnWrapper $justify="flex-end">
|
||||
<ButtonClose onClick={handleCompleteModal} />
|
||||
</BtnWrapper>
|
||||
<ModalText $align="center">{completeText}</ModalText>
|
||||
<BtnWrapper $gap="10px">
|
||||
<Button text="확인" theme="primary" type="submit" size="large" width="100%" handleClick={handleCompleteModal} />
|
||||
</BtnWrapper>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default NicknameChangeModal;
|
||||
const PwSetTable = styled.table`
|
||||
width: 400px;
|
||||
margin: 30px 0;
|
||||
th,
|
||||
td {
|
||||
padding: 10px 0;
|
||||
}
|
||||
`;
|
||||
const ChangeNotice = styled.span`
|
||||
font-size: 12px;
|
||||
font-weight: 300;
|
||||
color: ${props => props.$color || '#999'};
|
||||
margin-top: 10px;
|
||||
display: block;
|
||||
`;
|
||||
80
src/components/DataManage/QuestDetailModal.js
Normal file
@@ -0,0 +1,80 @@
|
||||
import { styled } from 'styled-components';
|
||||
|
||||
import { Title } from '../../styles/Components';
|
||||
import { BtnWrapper, TableStyle } from '../../styles/Components';
|
||||
import Button from '../../components/common/button/Button';
|
||||
import Modal from '../../components/common/modal/Modal';
|
||||
import { useEffect, useState, Fragment } from 'react';
|
||||
|
||||
const QuestDetailModal = ({ detailPop, handleClick, detailQuest }) => {
|
||||
const [detailList, setDetailList] = useState([])
|
||||
|
||||
useEffect(() => {
|
||||
Array.isArray(detailQuest) && setDetailList(detailQuest)
|
||||
|
||||
}, [detailQuest])
|
||||
// const questlist = [{ taskNo: detailQuest.task_no, taskName: detailQuest.quest_name, counter: detailQuest.counter, state: detailQuest.status }];
|
||||
return (
|
||||
<>
|
||||
<Modal $view={detailPop} min="480px">
|
||||
<Title $align="center">퀘스트 상세정보</Title>
|
||||
<TableWrapper>
|
||||
<TableStyle>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="80">Task No</th>
|
||||
<th>Task Name</th>
|
||||
<th width="120">Counter</th>
|
||||
<th width="120">State</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{detailList && detailList.map((el, index) => {
|
||||
return (
|
||||
<Fragment key={index}>
|
||||
<tr>
|
||||
<td>{el.task_no}</td>
|
||||
<td>{el.quest_name}</td>
|
||||
<td>{el.counter}</td>
|
||||
<td>{el.status}</td>
|
||||
</tr>
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</TableStyle>
|
||||
</TableWrapper>
|
||||
<BtnWrapper2 $justify="center">
|
||||
<Button
|
||||
theme="line"
|
||||
text="확인"
|
||||
handleClick={e => {
|
||||
e.preventDefault();
|
||||
handleClick();
|
||||
}}
|
||||
/>
|
||||
</BtnWrapper2>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default QuestDetailModal;
|
||||
|
||||
const TableWrapper = styled.div`
|
||||
max-height: 50vh;
|
||||
overflow: auto;
|
||||
&::-webkit-scrollbar {
|
||||
width: 4px;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #666666;
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
background: #d9d9d9;
|
||||
}
|
||||
`;
|
||||
|
||||
const BtnWrapper2 = styled(BtnWrapper)`
|
||||
margin-top: 30px;
|
||||
`;
|
||||
198
src/components/DataManage/TradeLogSearchBar.js
Normal file
@@ -0,0 +1,198 @@
|
||||
import { styled } from 'styled-components';
|
||||
import { useState } from 'react';
|
||||
|
||||
import Button from '../../components/common/button/Button';
|
||||
|
||||
import DatePicker, { registerLocale } from 'react-datepicker';
|
||||
import 'react-datepicker/dist/react-datepicker.css';
|
||||
import { getMonth, getYear } from 'date-fns';
|
||||
import range from 'lodash/range';
|
||||
|
||||
import { TextInput, SelectInput, DatePickerWrapper, InputLabel, BtnWrapper } from '../../styles/Components';
|
||||
|
||||
const TradeLogSerchBar = () => {
|
||||
const [startDate, setStartDate] = useState(new Date());
|
||||
const [endDate, setEndDate] = useState(new Date());
|
||||
const [selectData, setSelectData] = useState('default');
|
||||
const years = range(1990, getYear(new Date()) + 1, 1);
|
||||
const months = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'];
|
||||
|
||||
const handleChange = e => {
|
||||
setSelectData(e.target.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<SearchbarStyle2>
|
||||
<SearchRow>
|
||||
<SearchItem>
|
||||
<InputLabel>조회 기간</InputLabel>
|
||||
<DatePickerWrapper>
|
||||
<InputGroup>
|
||||
<DatePicker
|
||||
selected={startDate}
|
||||
onChange={date => setStartDate(date)}
|
||||
className="datepicker"
|
||||
placeholderText="검색기간 선택"
|
||||
calendarClassName="calendar"
|
||||
dateFormat="yyyy - MM - dd"
|
||||
locale="ko"
|
||||
renderCustomHeader={({ date, changeYear, changeMonth, decreaseMonth, increaseMonth, prevMonthButtonDisabled, nextMonthButtonDisabled }) => (
|
||||
<div className="calendar-top">
|
||||
<button
|
||||
className="btn-prev"
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
decreaseMonth();
|
||||
}}
|
||||
disabled={prevMonthButtonDisabled}></button>
|
||||
<select value={getYear(date)} onChange={({ target: { value } }) => changeYear(value)}>
|
||||
{years.map(option => (
|
||||
<option key={option} value={option}>
|
||||
{option}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
.
|
||||
<select value={months[getMonth(date)]} onChange={({ target: { value } }) => changeMonth(months.indexOf(value))}>
|
||||
{months.map(option => (
|
||||
<option key={option} value={option}>
|
||||
{option}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<button
|
||||
className="btn-next"
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
increaseMonth();
|
||||
}}
|
||||
disabled={nextMonthButtonDisabled}></button>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<SelectInput>
|
||||
<option value="">00</option>
|
||||
<option value="">01</option>
|
||||
</SelectInput>
|
||||
<SelectInput>
|
||||
<option value="">00</option>
|
||||
<option value="">01</option>
|
||||
</SelectInput>
|
||||
</InputGroup>
|
||||
<span>~</span>
|
||||
<InputGroup>
|
||||
<DatePicker
|
||||
selected={endDate}
|
||||
onChange={date => setEndDate(date)}
|
||||
className="datepicker"
|
||||
placeholderText="검색기간 선택"
|
||||
calendarClassName="calendar"
|
||||
dateFormat="yyyy - MM - dd"
|
||||
minDate = {startDate}
|
||||
locale="ko"
|
||||
renderCustomHeader={({ date, changeYear, changeMonth, decreaseMonth, increaseMonth, prevMonthButtonDisabled, nextMonthButtonDisabled }) => (
|
||||
<div className="calendar-top">
|
||||
<button
|
||||
className="btn-prev"
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
decreaseMonth();
|
||||
}}
|
||||
disabled={prevMonthButtonDisabled}></button>
|
||||
<select value={getYear(date)} onChange={({ target: { value } }) => changeYear(value)}>
|
||||
{years.map(option => (
|
||||
<option key={option} value={option}>
|
||||
{option}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
.
|
||||
<select value={months[getMonth(date)]} onChange={({ target: { value } }) => changeMonth(months.indexOf(value))}>
|
||||
{months.map(option => (
|
||||
<option key={option} value={option}>
|
||||
{option}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<button
|
||||
className="btn-next"
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
increaseMonth();
|
||||
}}
|
||||
disabled={nextMonthButtonDisabled}></button>
|
||||
</div>
|
||||
)}
|
||||
/>
|
||||
<SelectInput>
|
||||
<option value="">00</option>
|
||||
<option value="">01</option>
|
||||
</SelectInput>
|
||||
<SelectInput>
|
||||
<option value="">00</option>
|
||||
<option value="">01</option>
|
||||
</SelectInput>
|
||||
</InputGroup>
|
||||
</DatePickerWrapper>
|
||||
</SearchItem>
|
||||
</SearchRow>
|
||||
<SearchRow>
|
||||
<SearchItem>
|
||||
<InputLabel>조회 대상</InputLabel>
|
||||
<TextInput type="text" placeholder="조회 대상 유저의 GUID를 입력하세요." width="600px" />
|
||||
</SearchItem>
|
||||
<BtnWrapper $gap="8px">
|
||||
<Button theme="reset" />
|
||||
<Button theme="gray" text="검색" />
|
||||
</BtnWrapper>
|
||||
</SearchRow>
|
||||
</SearchbarStyle2>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default TradeLogSerchBar;
|
||||
|
||||
const SearchbarStyle = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20px 0;
|
||||
font-size: 14px;
|
||||
padding: 20px;
|
||||
border-top: 1px solid #000;
|
||||
border-bottom: 1px solid #000;
|
||||
margin-bottom: 40px;
|
||||
`;
|
||||
const SearchbarStyle2 = styled(SearchbarStyle)`
|
||||
flex-flow: column;
|
||||
gap: 20px;
|
||||
`;
|
||||
|
||||
const SearchRow = styled.div`
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 20px 0;
|
||||
`;
|
||||
|
||||
const InputGroup = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
`;
|
||||
|
||||
const SearchItem = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
margin-right: 50px;
|
||||
|
||||
${TextInput}, ${SelectInput} {
|
||||
height: 35px;
|
||||
}
|
||||
${TextInput} {
|
||||
padding: 0 10px;
|
||||
max-width: 400px;
|
||||
}
|
||||
`;
|
||||
672
src/components/DataManage/UserAvatarInfo.js
Normal file
@@ -0,0 +1,672 @@
|
||||
import styled from 'styled-components';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { UserAvatarView } from '../../apis/Users';
|
||||
import { TableSkeleton } from '../Skeleton/TableSkeleton';
|
||||
|
||||
const UserAvatarInfo = ({ userInfo }) => {
|
||||
const [dataList, setDataList] = useState();
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
const fetchData = async () => {
|
||||
const token = sessionStorage.getItem('token');
|
||||
await UserAvatarView(token, userInfo.guid).then(data => {
|
||||
setDataList(data);
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
loading ? <TableSkeleton width='25%' count={20}/> :
|
||||
<>
|
||||
<Notice>* 아바타 항목의 모든 항목은 ID 및 코드로 노출됩니다.</Notice>
|
||||
<AvatarWrapper>
|
||||
<UserInfoTable $maxwidth="600px">
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="30%" />
|
||||
<col width="120" />
|
||||
<col width="30%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>아바타 ID</th>
|
||||
<td colSpan="3">{dataList && dataList.avatar_info.character_id}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>기본 외형</th>
|
||||
<td colSpan="3">{dataList && dataList.avatar_info.basicstyle}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>체형 타입</th>
|
||||
<td colSpan="3">{dataList && dataList.avatar_info.bodyshape}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>헤어스타일</th>
|
||||
<td>{dataList && dataList.avatar_info.hairstyle}</td>
|
||||
<th>헤어 컬러</th>
|
||||
<td>{dataList && dataList.avatar_info.haircolor}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>나이</th>
|
||||
<td colSpan="3">{dataList && dataList.avatar_info.age}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserInfoTable>
|
||||
|
||||
<UserFaceInfoTable $maxwidth="600px">
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>얼굴 윤곽</th>
|
||||
<td>
|
||||
<UserFaceDetailInfoTable>
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>얼굴 길이</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[0]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>이마 돌출</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[1]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>볼 라인</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[2]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>광대 좌우</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[3]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>광대 상하</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[4]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>광대 돌출</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[5]}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceDetailInfoTable>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceInfoTable>
|
||||
<UserFaceInfoTable $maxwidth="600px">
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>턱</th>
|
||||
<td>
|
||||
<UserFaceDetailInfoTable>
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>앞턱 넓이 좌우</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[6]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>앞턱 상하</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[7]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>앞턱 전후</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[8]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>뒷턱 돌출</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[9]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>뒷턱 상하</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[10]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>뒷턱 넓이 좌우</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[11]}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceDetailInfoTable>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceInfoTable>
|
||||
<UserFaceInfoTable $maxwidth="600px">
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>눈</th>
|
||||
<td>
|
||||
<UserFaceDetailInfoTable>
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>눈 사이 간격</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[12]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>눈 높이 상하</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[13]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>눈 각도</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[14]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>눈 크기</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[15]}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceDetailInfoTable>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceInfoTable>
|
||||
<UserFaceInfoTable $maxwidth="600px">
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>눈썹</th>
|
||||
<td>
|
||||
<UserFaceDetailInfoTable>
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>눈썹뼈 돌출</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[16]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>넓이</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[17]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>높이</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[18]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>각도</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[19]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>두께</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[20]}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceDetailInfoTable>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceInfoTable>
|
||||
<UserFaceInfoTable $maxwidth="600px">
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>코</th>
|
||||
<td>
|
||||
<UserFaceDetailInfoTable>
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>코 높이 상하</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[21]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>콧대 돌출</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[22]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>코볼</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[23]}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceDetailInfoTable>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceInfoTable>
|
||||
|
||||
<UserFaceInfoTable $maxwidth="600px">
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>입</th>
|
||||
<td>
|
||||
<UserFaceDetailInfoTable>
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>상하</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[24]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>넓이 좌우</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[25]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>윗입술 두께</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[26]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>아랫입술 두께</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[27]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>윗입술 넓이</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[28]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>아랫입술 넓이</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[29]}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceDetailInfoTable>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceInfoTable>
|
||||
<UserFaceInfoTable $maxwidth="600px">
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>귀</th>
|
||||
<td>
|
||||
<UserFaceDetailInfoTable>
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>뾰족귀(엘프귀)</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[30]}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>귓볼(부처귀)</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[31]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>귀 각도</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[32]}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceDetailInfoTable>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceInfoTable>
|
||||
<UserFaceInfoTable $maxwidth="600px">
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>헤어 루트컬러</th>
|
||||
<td>
|
||||
<UserFaceDetailInfoTable>
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>RED</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[33]}</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>GREEN</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[34]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>BLUE</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[35]}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceDetailInfoTable>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceInfoTable>
|
||||
<UserFaceInfoTable $maxwidth="600px">
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>헤어 팁 컬러</th>
|
||||
<td>
|
||||
<UserFaceDetailInfoTable>
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>RED</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[36]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>GREEN</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[37]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>BLUE</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[38]}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceDetailInfoTable>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceInfoTable>
|
||||
<UserFaceInfoTable $maxwidth="600px">
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>헤어 컬러</th>
|
||||
<td>
|
||||
<UserFaceDetailInfoTable>
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>RED</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[39]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>GREEN</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[40]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>BLUE</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[41]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>CONTRAST</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[42]}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceDetailInfoTable>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceInfoTable>
|
||||
<UserFaceInfoTable $maxwidth="600px">
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>눈썹 컬러</th>
|
||||
<td>
|
||||
<UserFaceDetailInfoTable>
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>RED</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[43]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>GREEN</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[44]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>BLUE</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[45]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>ALPHA</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[46]}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceDetailInfoTable>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceInfoTable>
|
||||
<UserFaceInfoTable $maxwidth="600px">
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>홍채 컬러</th>
|
||||
<td>
|
||||
<UserFaceDetailInfoTable>
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="100%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>RED</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[47]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>GREEN</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[48]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>BLUE</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[49]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>ALPHA</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[50]}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceDetailInfoTable>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceInfoTable>
|
||||
{/*
|
||||
|
||||
|
||||
|
||||
<UserFaceInfoTable $maxwidth="600">
|
||||
<colgroup>
|
||||
<col width="120" />
|
||||
<col width="40%" />
|
||||
<col width="60%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>홍채 컬러</th>
|
||||
<tr>
|
||||
<th>RED</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[47]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>GREEN</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[48]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>BLUE</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[49]}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>ALPHA</th>
|
||||
<td>{dataList && dataList.avatar_info.facesCustomizing[50]}</td>
|
||||
</tr>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserFaceInfoTable>
|
||||
*/}
|
||||
</AvatarWrapper>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserAvatarInfo;
|
||||
|
||||
const Notice = styled.span`
|
||||
font-size: 13px;
|
||||
font-weight: 300;
|
||||
margin-bottom: 10px;
|
||||
display: block;
|
||||
`;
|
||||
|
||||
const UserInfoTable = styled.table`
|
||||
width: 100%;
|
||||
max-width: ${props => props.$maxwidth || 'auto'};
|
||||
font-size: 13px;
|
||||
border-radius: 15px;
|
||||
overflow: hidden;
|
||||
tr:first-child {
|
||||
th,
|
||||
td {
|
||||
border-top: 0;
|
||||
}
|
||||
}
|
||||
th,
|
||||
td {
|
||||
height: 36px;
|
||||
vertical-align: middle;
|
||||
border-top: 1px solid #d9d9d9;
|
||||
}
|
||||
th {
|
||||
width: 120px;
|
||||
background: #888;
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
}
|
||||
td {
|
||||
background: #fff;
|
||||
padding: 0 20px;
|
||||
}
|
||||
`;
|
||||
|
||||
/*
|
||||
width: 100%;
|
||||
max-width: ${props => props.$maxwidth || 'auto'};
|
||||
*/
|
||||
|
||||
|
||||
const UserFaceInfoTable = styled.table`
|
||||
|
||||
max-width: ${props => props.$maxwidth || 'auto'};
|
||||
font-size: 13px;
|
||||
border-radius: 15px;
|
||||
overflow: hidden;
|
||||
tr:first-child {
|
||||
th,
|
||||
td {
|
||||
border-top: 0;
|
||||
}
|
||||
}
|
||||
th {
|
||||
height: 36px;
|
||||
vertical-align: middle;
|
||||
border-right: 1px solid #d9d9d9;
|
||||
border-bottom: 1px solid #d9d9d9;
|
||||
width: 120px;
|
||||
background: #888;
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
`;
|
||||
|
||||
const UserFaceDetailInfoTable = styled.table`
|
||||
|
||||
max-width: ${props => props.$maxwidth || 'auto'};
|
||||
font-size: 13px;
|
||||
border-right-radius: 15px;
|
||||
overflow: hidden;
|
||||
tr:first-child {
|
||||
th,
|
||||
td {
|
||||
border-top: 0;
|
||||
}
|
||||
}
|
||||
tr:last-child {
|
||||
td {
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
th {
|
||||
height: 36px;
|
||||
vertical-align: middle;
|
||||
border-right: 1px solid #d9d9d9;
|
||||
border-bottom: 1px solid #d9d9d9;
|
||||
width: 120px;
|
||||
background: #888;
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
}
|
||||
td {
|
||||
vertical-align: middle;
|
||||
border-bottom: 1px solid #d9d9d9;
|
||||
background: #fff;
|
||||
padding: 0 20px;
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
|
||||
const AvatarWrapper = styled.div`
|
||||
${UserInfoTable}:first-child {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
${UserFaceInfoTable} {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
`;
|
||||
130
src/components/DataManage/UserClaimInfo.js
Normal file
@@ -0,0 +1,130 @@
|
||||
import { Fragment } from 'react';
|
||||
|
||||
import styled from 'styled-components';
|
||||
|
||||
const UserClaimInfo = () => {
|
||||
const ListData = [
|
||||
{ count: '1', state1: '수령', receipt1: '2023-08-11 09:00', state2: '수령', receipt2: '2023-08-11 09:00' },
|
||||
{ count: '2', state1: '수령가능', receipt1: '', state2: '수령가능', receipt2: '' },
|
||||
{ count: '3', state1: '수령불가', receipt1: '', state2: '수령불가', receipt2: '' },
|
||||
];
|
||||
return (
|
||||
<>
|
||||
<NoContent>진행중인 클레임이 없습니다.</NoContent>
|
||||
<UserTableWrapper>
|
||||
<ClaimTable>
|
||||
<colgroup>
|
||||
<col width="80" />
|
||||
<col width="170" />
|
||||
<col width="170" />
|
||||
<col width="170" />
|
||||
<col width="170" />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>분류</th>
|
||||
<th colSpan="2">everyone</th>
|
||||
<th colSpan="2">member</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>회차</th>
|
||||
<th>상태</th>
|
||||
<th>수령시간</th>
|
||||
<th>상태</th>
|
||||
<th>수령시간</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{ListData.map((el, idx) => {
|
||||
return (
|
||||
<Fragment key={idx}>
|
||||
<tr>
|
||||
<td>{el.count}</td>
|
||||
<td>{el.state1}</td>
|
||||
<td>{el.receipt1}</td>
|
||||
<td>{el.state2}</td>
|
||||
<td>{el.receipt2}</td>
|
||||
</tr>
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</ClaimTable>
|
||||
</UserTableWrapper>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserClaimInfo;
|
||||
|
||||
const UserDefaultTable = styled.table`
|
||||
border: 1px solid #e8eaec;
|
||||
border-top: 1px solid #000;
|
||||
font-size: 14px;
|
||||
margin-bottom: 40px;
|
||||
th {
|
||||
background: #efefef;
|
||||
font-weight: 700;
|
||||
}
|
||||
th,
|
||||
td {
|
||||
padding: 12px;
|
||||
text-align: center;
|
||||
border-left: 1px solid #e8eaec;
|
||||
vertical-align: middle;
|
||||
}
|
||||
td {
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #e8eaec;
|
||||
word-break: break-all;
|
||||
}
|
||||
button {
|
||||
height: 24px;
|
||||
font-size: 13px;
|
||||
}
|
||||
`;
|
||||
|
||||
const QuestTable = styled(UserDefaultTable)`
|
||||
tbody {
|
||||
td {
|
||||
padding: 9px 12px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const UserTableWrapper = styled.div`
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
margin-bottom: 40px;
|
||||
${UserDefaultTable}, ${QuestTable} {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
&::-webkit-scrollbar {
|
||||
height: 4px;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #666666;
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
background: #d9d9d9;
|
||||
}
|
||||
`;
|
||||
|
||||
const NoContent = styled.div`
|
||||
padding: 70px;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
`;
|
||||
|
||||
const ClaimTable = styled(UserDefaultTable)`
|
||||
thead {
|
||||
th {
|
||||
padding: 9px 12px;
|
||||
}
|
||||
tr:first-child {
|
||||
th {
|
||||
background: #d9d9d9;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
186
src/components/DataManage/UserDefaultInfo.js
Normal file
@@ -0,0 +1,186 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import styled from 'styled-components';
|
||||
import Profile from '../../assets/img/datamanage/img-profile.png';
|
||||
import NicknameChangeModal from '../../components/DataManage/NicknameChangeModal';
|
||||
import EditIcon from '../../assets/img/icon/icon-edit.png';
|
||||
import { UserChangeAdminLevel, UserInfoView } from '../../apis/Users';
|
||||
import { SelectInput } from '../../styles/Components';
|
||||
import { adminLevelType, authType, modalTypes } from '../../assets/data';
|
||||
import DynamicModal from '../common/modal/DynamicModal';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { authList } from '../../store/authList';
|
||||
import { convertKTC } from '../../utils';
|
||||
import { EditButton, ProfileWrapper, UserDefault, UserInfoTable } from '../../styles/ModuleComponents';
|
||||
import { TableSkeleton } from '../Skeleton/TableSkeleton';
|
||||
import { UserInfoSkeleton } from '../Skeleton/UserInfoSkeleton';
|
||||
|
||||
const UserDefaultInfo = ({ userInfo }) => {
|
||||
const { t } = useTranslation();
|
||||
const authInfo = useRecoilValue(authList);
|
||||
|
||||
const [pwPop, setPwPop] = useState('hidden');
|
||||
const [gmModal, setGmModal] = useState('hidden');
|
||||
const [dataList, setDataList] = useState({});
|
||||
const [adminLevel, setAdminLevel] = useState('0');
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const handleClick = () => {
|
||||
if (pwPop === 'hidden') setPwPop('view');
|
||||
else setPwPop('hidden');
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, [userInfo]);
|
||||
|
||||
const fetchData = async () => {
|
||||
const token = sessionStorage.getItem('token');
|
||||
await UserInfoView(token, userInfo.guid).then(data => {
|
||||
setDataList(data);
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
const handleGMChange = (e) =>{
|
||||
setAdminLevel(e.target.value);
|
||||
setGmModal('view');
|
||||
}
|
||||
|
||||
const handleSubmit = async () => {
|
||||
const token = sessionStorage.getItem('token');
|
||||
let params = {};
|
||||
params.guid = userInfo.guid;
|
||||
params.admin_level = adminLevel;
|
||||
|
||||
await UserChangeAdminLevel(token, params);
|
||||
|
||||
handleCancel();
|
||||
await fetchData();
|
||||
}
|
||||
|
||||
const handleCancel = () => {
|
||||
setGmModal('hidden');
|
||||
}
|
||||
|
||||
return (
|
||||
loading ? <UserInfoSkeleton /> :
|
||||
<>
|
||||
<div>
|
||||
<UserDefault>
|
||||
<ProfileWrapper>
|
||||
<img src={Profile} alt="" />
|
||||
</ProfileWrapper>
|
||||
<UserInfoTable $maxwidth="530px">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>AID(GUID)</th>
|
||||
<td>{dataList.user_info && dataList.user_info.aid}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>계정 ID</th>
|
||||
<td>{dataList.user_info && dataList.user_info.user_id}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>국가</th>
|
||||
<td>{dataList.user_info && dataList.user_info.nation}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>멤버십</th>
|
||||
<td>{dataList.user_info && dataList.user_info.membership}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>친구 추천코드</th>
|
||||
<td>{dataList.user_info && dataList.user_info.friend_code}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>계정 생성일</th>
|
||||
<td>
|
||||
{dataList.user_info && convertKTC(dataList.user_info.create_dt)}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>최근 접속일자</th>
|
||||
<td>
|
||||
{/*{dataList.user_info && String(new Date(new Date(dataList.user_info.access_dt).setHours(new Date(dataList.user_info.access_dt).getHours() + 9)).toLocaleString())}*/}
|
||||
{dataList.user_info && convertKTC(dataList.user_info.access_dt)}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>최근 종료일자</th>
|
||||
<td>{dataList.user_info && convertKTC(dataList.user_info.end_dt)}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>전자지갑 URL</th>
|
||||
<td>
|
||||
<Link>{dataList.user_info && dataList.user_info.wallet_url}</Link>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>GM권한</th>
|
||||
<td>
|
||||
<SelectInput value={dataList.user_info && dataList.user_info.admin_level} onChange={(e) => handleGMChange(e)} disabled={authInfo.auth_list && !authInfo.auth_list.some(auth => auth.id === authType.userSearchUpdate)} >
|
||||
{adminLevelType.map((data, index) => (
|
||||
<option key={index} value={data.value}>
|
||||
{data.name}
|
||||
</option>
|
||||
))}
|
||||
</SelectInput>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserInfoTable>
|
||||
</UserDefault>
|
||||
<UserInfoTable $maxwidth="720px">
|
||||
<colgroup>
|
||||
<col />
|
||||
<col />
|
||||
<col width="120" />
|
||||
<col />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>캐릭터 아바타명</th>
|
||||
<td colSpan="3">
|
||||
{dataList.char_info && dataList.char_info.character_name}
|
||||
<EditButton
|
||||
hidden={true}
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
handleClick();
|
||||
}}></EditButton>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>시즌 패스 레벨</th>
|
||||
<td colSpan="3">{dataList.char_info && dataList.char_info.level}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>골드</th>
|
||||
<td>{dataList.char_info && dataList.char_info.gold_cali}</td>
|
||||
<th>사파이어</th>
|
||||
<td>{dataList.char_info && dataList.char_info.blue_cali}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>칼리움</th>
|
||||
<td>{dataList.char_info && dataList.char_info.red_cali}</td>
|
||||
<th>루비</th>
|
||||
<td>{dataList.char_info && dataList.char_info.black_cali}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserInfoTable>
|
||||
</div>
|
||||
<NicknameChangeModal pwPop={pwPop} handleClick={handleClick} dataList={dataList} />
|
||||
<DynamicModal
|
||||
modalType={modalTypes.childOkCancel}
|
||||
view={gmModal}
|
||||
modalText={t('USER_GM_CHANGE')}
|
||||
handleCancel={handleCancel}
|
||||
handleSubmit={handleSubmit}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default UserDefaultInfo;
|
||||
125
src/components/DataManage/UserDressInfo.js
Normal file
@@ -0,0 +1,125 @@
|
||||
import styled from 'styled-components';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { UserClothView } from '../../apis/Users';
|
||||
import { TableSkeleton } from '../Skeleton/TableSkeleton';
|
||||
|
||||
const UserDressInfo = ({ userInfo }) => {
|
||||
const [dataList, setDataList] = useState();
|
||||
const [rowData, setRowData] = useState([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setRowData([
|
||||
{ slotType : "상의", smallType: '셔츠', itemNo : dataList?.cloth_info?.cloth_shirt?.cloth || 0, itemName: dataList?.cloth_info?.cloth_shirt?.clothName || null},
|
||||
{ slotType : "상의", smallType: '드레스', itemNo : dataList?.cloth_info?.cloth_dress?.cloth || 0, itemName: dataList?.cloth_info?.cloth_dress?.clothName || null},
|
||||
{ slotType : "외투", smallType: '외투', itemNo : dataList?.cloth_info?.cloth_outer?.cloth || 0, itemName: dataList?.cloth_info?.cloth_outer?.clothName || null},
|
||||
{ slotType : "하의", smallType: '바지', itemNo : dataList?.cloth_info?.cloth_pants?.cloth || 0, itemName: dataList?.cloth_info?.cloth_pants?.clothName || null},
|
||||
{ slotType : "장갑", smallType: '장갑', itemNo : dataList?.cloth_info?.cloth_gloves?.cloth || 0, itemName: dataList?.cloth_info?.cloth_gloves?.clothName || null},
|
||||
{ slotType : "장갑", smallType: '반지', itemNo : dataList?.cloth_info?.cloth_ring?.cloth || 0, itemName: dataList?.cloth_info?.cloth_ring?.clothName || null},
|
||||
{ slotType : "장갑", smallType: '팔찌', itemNo : dataList?.cloth_info?.cloth_bracelet?.cloth || 0, itemName: dataList?.cloth_info?.cloth_bracelet?.clothName || null},
|
||||
{ slotType : "가방", smallType: '가방', itemNo : dataList?.cloth_info?.cloth_bag?.cloth || 0, itemName: dataList?.cloth_info?.cloth_bag?.clothName || null},
|
||||
{ slotType : "가방", smallType: '배낭', itemNo : dataList?.cloth_info?.cloth_backpack?.cloth || 0, itemName: dataList?.cloth_info?.cloth_backpack?.clothName || null},
|
||||
{ slotType : "머리 장식", smallType: '모자', itemNo : dataList?.cloth_info?.cloth_cap?.cloth || 0, itemName: dataList?.cloth_info?.cloth_cap?.clothName || null},
|
||||
{ slotType : "얼굴 장식", smallType: '얼굴 장식', itemNo : dataList?.cloth_info?.cloth_mask?.cloth || 0, itemName: dataList?.cloth_info?.cloth_mask?.clothName || null},
|
||||
{ slotType : "얼굴 장식", smallType: '안경', itemNo : dataList?.cloth_info?.cloth_glasses?.cloth || 0, itemName: dataList?.cloth_info?.cloth_glasses?.clothName || null},
|
||||
{ slotType : "귀걸이", smallType: '귀걸이', itemNo : dataList?.cloth_info?.cloth_earring?.cloth || 0, itemName: dataList?.cloth_info?.cloth_earring?.clothName || null},
|
||||
{ slotType : "목걸이", smallType: '목걸이', itemNo : dataList?.cloth_info?.cloth_necklace?.cloth || 0, itemName: dataList?.cloth_info?.cloth_necklace?.clothName || null},
|
||||
{ slotType : "신발", smallType: '신발', itemNo : dataList?.cloth_info?.cloth_shoes?.cloth || 0, itemName: dataList?.cloth_info?.cloth_shoes?.clothName || null},
|
||||
{ slotType : "양말", smallType: '양말', itemNo : dataList?.cloth_info?.cloth_socks?.cloth || 0, itemName: dataList?.cloth_info?.cloth_socks?.clothName || null},
|
||||
{ slotType : "양말", smallType: '발찌', itemNo : dataList?.cloth_info?.cloth_anklet?.cloth || 0, itemName: dataList?.cloth_info?.cloth_anklet?.clothName || null}
|
||||
])
|
||||
}, [dataList])
|
||||
|
||||
const fetchData = async () => {
|
||||
const token = sessionStorage.getItem('token');
|
||||
await UserClothView(token, userInfo.guid).then(data => {
|
||||
setDataList(data);
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
const groupedData = rowData.reduce((acc, el) => {
|
||||
const key = el.slotType;
|
||||
if (!acc[key]) {
|
||||
acc[key] = [];
|
||||
}
|
||||
acc[key].push(el);
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
return (
|
||||
loading ? <TableSkeleton width='30%' count={15} /> :
|
||||
<>
|
||||
<DressWrapper>
|
||||
<UserInfoTable $maxwidth="670px">
|
||||
<colgroup>
|
||||
<col width="100" />
|
||||
<col width="120" />
|
||||
<col width="30%" />
|
||||
<col width="50%" />
|
||||
</colgroup>
|
||||
<tbody>
|
||||
{Object.keys(groupedData).map((key) => {
|
||||
const rows = groupedData[key];
|
||||
return rows.map((el, idx) => (
|
||||
<tr key={`${key}-${idx}`}>
|
||||
{idx === 0 && (
|
||||
<th rowSpan={rows.length}>{el.slotType}</th>
|
||||
)}
|
||||
<th>{el.smallType}</th>
|
||||
<td>{el.itemNo}</td>
|
||||
<td>{el.itemName}</td>
|
||||
</tr>
|
||||
));
|
||||
})}
|
||||
</tbody>
|
||||
</UserInfoTable>
|
||||
</DressWrapper>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserDressInfo;
|
||||
|
||||
const UserInfoTable = styled.table`
|
||||
width: 100%;
|
||||
max-width: ${props => props.$maxwidth || 'auto'};
|
||||
font-size: 13px;
|
||||
border-radius: 15px;
|
||||
overflow: hidden;
|
||||
tr:first-child {
|
||||
th,
|
||||
td {
|
||||
border-top: 0;
|
||||
}
|
||||
}
|
||||
th,
|
||||
td {
|
||||
height: 36px;
|
||||
vertical-align: middle;
|
||||
border-top: 1px solid #d9d9d9;
|
||||
border-right: 1px solid #d9d9d9;
|
||||
}
|
||||
th {
|
||||
width: 120px;
|
||||
background: #888;
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
}
|
||||
td {
|
||||
background: #fff;
|
||||
padding: 0 20px;
|
||||
}
|
||||
`;
|
||||
|
||||
const DressWrapper = styled.div`
|
||||
${UserInfoTable} {
|
||||
td {
|
||||
border-left: 1px solid #d9d9d9;
|
||||
}
|
||||
}
|
||||
`;
|
||||
194
src/components/DataManage/UserFriendInfo.js
Normal file
@@ -0,0 +1,194 @@
|
||||
import { useState, Fragment, useEffect } from 'react';
|
||||
import { SelectInput } from '../../styles/Components';
|
||||
import { UserTableWrapper, SelectWrapper, RequestTabWrapper, RequestTab, UserDefaultTable } from '../../styles/ModuleComponents';
|
||||
import { UserFriendListView } from '../../apis';
|
||||
import { convertKTC } from '../../utils';
|
||||
import { TableSkeleton } from '../Skeleton/TableSkeleton';
|
||||
|
||||
const UserFriendInfo = ({ userInfo }) => {
|
||||
const [activeSection, setActiveSection] = useState('list');
|
||||
const [activeRequest, setActiveRequest] = useState('received');
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const [dataList, setDataList] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
const fetchData = async () => {
|
||||
const token = sessionStorage.getItem('token');
|
||||
await UserFriendListView(token, userInfo.guid).then(data => {
|
||||
setDataList(data);
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
loading ? <TableSkeleton /> :
|
||||
<>
|
||||
<SelectWrapper>
|
||||
<SelectInput
|
||||
onChange={e => {
|
||||
setActiveSection(e.target.value);
|
||||
}}>
|
||||
<option value="list">친구 목록</option>
|
||||
<option value="request">친구 요청</option>
|
||||
<option value="block">차단 목록</option>
|
||||
</SelectInput>
|
||||
{activeSection === 'request' && (
|
||||
<RequestTabWrapper>
|
||||
<RequestTab
|
||||
$state={activeRequest === 'received' ? 'active' : 'inactive'}
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
setActiveRequest('received');
|
||||
}}>
|
||||
받은 요청
|
||||
</RequestTab>
|
||||
<RequestTab
|
||||
$state={activeRequest === 'sended' ? 'active' : 'inactive'}
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
setActiveRequest('sended');
|
||||
}}>
|
||||
보낸 요청
|
||||
</RequestTab>
|
||||
</RequestTabWrapper>
|
||||
)}
|
||||
</SelectWrapper>
|
||||
{activeSection === 'list' && (
|
||||
<>
|
||||
<UserTableWrapper>
|
||||
<UserDefaultTable>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="70">번호</th>
|
||||
<th width="200">친구 닉네임</th>
|
||||
<th width="300">친구 GUID</th>
|
||||
<th width="100">국가(언어)</th>
|
||||
<th width="160">친구 수락일</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{dataList && dataList.friend_list &&
|
||||
dataList.friend_list.map((data, idx) => (
|
||||
<Fragment key={idx}>
|
||||
<tr>
|
||||
<td>{data.row_num}</td>
|
||||
<td>{data.friend_name}</td>
|
||||
<td>{data.friend_guid}</td>
|
||||
<td>{data.language}</td>
|
||||
<td>{data.receive_dt && convertKTC(data.receive_dt)}</td>
|
||||
</tr>
|
||||
</Fragment>
|
||||
))}
|
||||
</tbody>
|
||||
</UserDefaultTable>
|
||||
</UserTableWrapper>
|
||||
</>
|
||||
)}
|
||||
{activeSection === 'request' && (
|
||||
<>
|
||||
{activeRequest === 'received' && (
|
||||
<>
|
||||
<UserDefaultTable>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="70">번호</th>
|
||||
<th width="200">요청자 닉네임</th>
|
||||
<th width="300">요청자 GUID</th>
|
||||
<th width="100">국가(언어)</th>
|
||||
<th width="160">받은 일자</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{dataList && dataList.friend_receive_list && dataList.friend_receive_list.map((data, idx) => {
|
||||
return (
|
||||
<Fragment key={idx}>
|
||||
<tr>
|
||||
<td>{data.row_num}</td>
|
||||
<td>{data.friend_name}</td>
|
||||
<td>{data.friend_guid}</td>
|
||||
<td>{data.language}</td>
|
||||
<td>{data.receive_dt && convertKTC(data.receive_dt)}</td>
|
||||
</tr>
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</UserDefaultTable>
|
||||
</>
|
||||
)}
|
||||
{activeRequest === 'sended' && (
|
||||
<>
|
||||
<UserTableWrapper>
|
||||
<UserDefaultTable>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="70">번호</th>
|
||||
<th width="200">요청 대상자 닉네임</th>
|
||||
<th width="300">요청 대상자 GUID</th>
|
||||
<th width="100">국가(언어)</th>
|
||||
<th width="160">요청일</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{dataList && dataList.friend_send_list && dataList.friend_send_list.map((data, idx) => {
|
||||
return (
|
||||
<Fragment key={idx}>
|
||||
<tr>
|
||||
<td>{data.row_num}</td>
|
||||
<td>{data.friend_name}</td>
|
||||
<td>{data.friend_guid}</td>
|
||||
<td>{data.language}</td>
|
||||
<td>{data.receive_dt && convertKTC(data.receive_dt)}</td>
|
||||
</tr>
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</UserDefaultTable>
|
||||
</UserTableWrapper>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{activeSection === 'block' && (
|
||||
<>
|
||||
<UserTableWrapper>
|
||||
<UserDefaultTable>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="70">번호</th>
|
||||
<th width="200">차단 닉네임</th>
|
||||
<th width="300">차단 대상 GUID</th>
|
||||
<th width="100">국가(언어)</th>
|
||||
<th width="160">차단 일자</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{dataList && dataList.friend_block_list && dataList.friend_block_list.map((data, idx) => {
|
||||
return (
|
||||
<Fragment key={idx}>
|
||||
<tr>
|
||||
<td>{data.row_num}</td>
|
||||
<td>{data.friend_name}</td>
|
||||
<td>{data.friend_guid}</td>
|
||||
<td>{data.language}</td>
|
||||
<td>{data.receive_dt && convertKTC(data.receive_dt)}</td>
|
||||
</tr>
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</UserDefaultTable>
|
||||
</UserTableWrapper>
|
||||
</>
|
||||
)}
|
||||
{/*{loading && <Loading/>}*/}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserFriendInfo;
|
||||
363
src/components/DataManage/UserInventoryInfo.js
Normal file
@@ -0,0 +1,363 @@
|
||||
import styled from 'styled-components';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { UserInventoryItemDelete, UserInventoryView } from '../../apis/Users';
|
||||
import Button from '../common/button/Button';
|
||||
import ConfirmModal from '../common/modal/ConfirmModal';
|
||||
import CompletedModal from '../common/modal/CompletedModal';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { InputItem, SelectInput, TextInput } from '../../styles/Components';
|
||||
import CustomConfirmModal from '../common/modal/CustomConfirmModal';
|
||||
import { ivenTabType } from '../../assets/data';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { authList } from '../../store/authList';
|
||||
import { TableSkeleton } from '../Skeleton/TableSkeleton';
|
||||
import { InfoSubTitle, UserDefaultTable, UserTableWrapper } from '../../styles/ModuleComponents';
|
||||
|
||||
const UserInventoryInfo = ({ userInfo }) => {
|
||||
const { t } = useTranslation();
|
||||
const authInfo = useRecoilValue(authList);
|
||||
|
||||
const [dataList, setDataList] = useState();
|
||||
const [itemCount, setItemCount] = useState('');
|
||||
const [selected, setSelected] = useState({});
|
||||
const [itemUpdateCount, setItemUpdateCount] = useState('1');
|
||||
const [deleteConfirmModal, setDeleteConfirmModal] = useState('hidden');
|
||||
const [deleteSubmitModal, setDeleteSubmitModal] = useState('hidden');
|
||||
const [deleteCompleteModal, setDeleteCompleteModal] = useState('hidden');
|
||||
const [authDelete, setAuthDelete] = useState(false);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setAuthDelete(authInfo.auth_list.some(auth => auth.id === 35));
|
||||
}, [authInfo]);
|
||||
|
||||
const fetchData = async () => {
|
||||
const token = sessionStorage.getItem('token');
|
||||
await UserInventoryView(token, userInfo.guid).then(data => {
|
||||
setDataList(data);
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
const handleDeleteConfirmModal = (data, type) =>{
|
||||
setItemCount(data.count);
|
||||
let row;
|
||||
switch(type){
|
||||
case ivenTabType.CLOTH:
|
||||
row = dataList.inventory_list.cloth.find(item => item.item_guid === data.item_guid);
|
||||
row.type = ivenTabType.CLOTH;
|
||||
break;
|
||||
case ivenTabType.PROP:
|
||||
row = dataList.inventory_list.prop.find(item => item.item_guid === data.item_guid);
|
||||
row.type = ivenTabType.PROP;
|
||||
break;
|
||||
case ivenTabType.BEAUTY:
|
||||
row = dataList.inventory_list.beauty.find(item => item.item_guid === data.item_guid);
|
||||
row.type = ivenTabType.BEAUTY;
|
||||
break;
|
||||
case ivenTabType.TATTOO:
|
||||
row = dataList.inventory_list.tattoo.find(item => item.item_guid === data.item_guid);
|
||||
row.type = ivenTabType.TATTOO;
|
||||
break;
|
||||
case ivenTabType.CURRENCY:
|
||||
row = dataList.inventory_list.currency.find(item => item.item_guid === data.item_guid);
|
||||
row.type = ivenTabType.CURRENCY;
|
||||
break;
|
||||
default:
|
||||
row = dataList.inventory_list.etc.find(item => item.item_guid === data.item_guid);
|
||||
row.type = ivenTabType.ETC;
|
||||
break;
|
||||
}
|
||||
setSelected(row);
|
||||
setDeleteConfirmModal('view');
|
||||
}
|
||||
|
||||
// 개수 입력 모달 hidden
|
||||
const handleDeleteConfirmClose = () => {
|
||||
setDeleteConfirmModal('hidden');
|
||||
setItemUpdateCount(1);
|
||||
setSelected({});
|
||||
}
|
||||
|
||||
// 삭제 모달 hidden
|
||||
const handleDeleteClose = () => {
|
||||
setDeleteSubmitModal('hidden');
|
||||
}
|
||||
|
||||
const handleDeleteConfirm = () => {
|
||||
setDeleteSubmitModal('view');
|
||||
}
|
||||
|
||||
// 삭제 처리
|
||||
const handleDeleteSubmit = async () => {
|
||||
let params = {}
|
||||
params.guid = userInfo.guid;
|
||||
params.item_guid = selected.item_guid;
|
||||
params.current_cnt = selected.count;
|
||||
params.cnt = itemUpdateCount;
|
||||
const token = sessionStorage.getItem('token');
|
||||
const result = await UserInventoryItemDelete(token, params);
|
||||
if(result.result === "SUCCESS"){
|
||||
//성공시 아이템 삭제 or 개수 차감
|
||||
if(selected.count <= itemUpdateCount){
|
||||
switch (selected.type) {
|
||||
case ivenTabType.CLOTH:
|
||||
dataList.inventory_list.cloth.splice(dataList.inventory_list.cloth.findIndex(item => item.item_guid === selected.item_guid), 1);
|
||||
break;
|
||||
case ivenTabType.PROP:
|
||||
dataList.inventory_list.prop.splice(dataList.inventory_list.prop.findIndex(item => item.item_guid === selected.item_guid), 1);
|
||||
break;
|
||||
case ivenTabType.BEAUTY:
|
||||
dataList.inventory_list.beauty.splice(dataList.inventory_list.beauty.findIndex(item => item.item_guid === selected.item_guid), 1);
|
||||
break;
|
||||
case ivenTabType.TATTOO:
|
||||
dataList.inventory_list.tattoo.splice(dataList.inventory_list.tattoo.findIndex(item => item.item_guid === selected.item_guid), 1);
|
||||
break;
|
||||
case ivenTabType.CURRENCY:
|
||||
dataList.inventory_list.currency.splice(dataList.inventory_list.currency.findIndex(item => item.item_guid === selected.item_guid), 1);
|
||||
break;
|
||||
default:
|
||||
dataList.inventory_list.etc.splice(dataList.inventory_list.etc.findIndex(item => item.item_guid === selected.item_guid), 1);
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
selected.count = selected.count - itemUpdateCount;
|
||||
}
|
||||
}
|
||||
handleDeleteClose();
|
||||
handleDeleteConfirmClose();
|
||||
setDeleteCompleteModal('view')
|
||||
}
|
||||
|
||||
const handleDeleteComplete = () => {
|
||||
setDeleteCompleteModal('hidden');
|
||||
}
|
||||
|
||||
const handleItemCount = e => {
|
||||
if (e.target.value === '0' || e.target.value === '-0') {
|
||||
setItemUpdateCount('1');
|
||||
e.target.value = '1';
|
||||
} else if (e.target.value < 0) {
|
||||
let plusNum = Math.abs(e.target.value);
|
||||
setItemUpdateCount(plusNum);
|
||||
} else if(e.target.value > itemCount){
|
||||
alert(t('DEL_COUNT_CHECK'));
|
||||
setItemUpdateCount(itemCount);
|
||||
} else {
|
||||
setItemUpdateCount(e.target.value);
|
||||
}
|
||||
};
|
||||
|
||||
const ConfirmChild = () => {
|
||||
return(
|
||||
<InputItem>
|
||||
<p>{t('DEL_COUNT_CONFIRM', {count: itemCount})}</p>
|
||||
<TextInput placeholder="수량" type="number" value={itemUpdateCount} onChange={e => handleItemCount(e)} width="200px" />
|
||||
</InputItem>
|
||||
);
|
||||
}
|
||||
|
||||
const InvenTable = ({invenList, title, type}) => {
|
||||
return (
|
||||
<>
|
||||
<InfoSubTitle>{title}</InfoSubTitle>
|
||||
<UserTableWrapper>
|
||||
<UserDefaultTable>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="80">no.</th>
|
||||
<th width="120">ID</th>
|
||||
<th width="50%">아이템</th>
|
||||
<th width="100">보유개수</th>
|
||||
<th width="60">삭제</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{invenList.map((el, idx) => {
|
||||
return (
|
||||
<tr key={idx}>
|
||||
<td>{idx + 1}</td>
|
||||
<td>{el.item_id}</td>
|
||||
<td>{el.item_name}</td>
|
||||
<td>{el.count}</td>
|
||||
<td>
|
||||
<Button theme={authDelete ? "line" : "disable"} id={el.item_guid} name="single" text="삭제" handleClick={e => {handleDeleteConfirmModal(el, type)}} disabled={!authDelete}/>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</UserDefaultTable>
|
||||
</UserTableWrapper>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
loading ? <TableSkeleton count={15}/> :
|
||||
<>
|
||||
{dataList && dataList.inventory_list && <InvenTable title="의상 탭" type={ivenTabType.CLOTH} invenList={dataList.inventory_list.cloth} />}
|
||||
{dataList && dataList.inventory_list && <InvenTable title="소품 탭" type={ivenTabType.PROP} invenList={dataList.inventory_list.prop} />}
|
||||
{dataList && dataList.inventory_list && <InvenTable title="미용 탭" type={ivenTabType.BEAUTY} invenList={dataList.inventory_list.beauty} />}
|
||||
{dataList && dataList.inventory_list && <InvenTable title="타투 탭" type={ivenTabType.TATTOO} invenList={dataList.inventory_list.tattoo} />}
|
||||
{dataList && dataList.inventory_list && <InvenTable title="재화 탭" type={ivenTabType.CURRENCY} invenList={dataList.inventory_list.currency} />}
|
||||
{dataList && dataList.inventory_list && <InvenTable title="기타 탭" type={ivenTabType.ETC} invenList={dataList.inventory_list.etc} />}
|
||||
<CustomConfirmModal
|
||||
ChildView={ConfirmChild}
|
||||
view={deleteConfirmModal}
|
||||
handleSubmit={handleDeleteConfirm}
|
||||
handleCancel={handleDeleteConfirmClose}
|
||||
handleClose={handleDeleteConfirmClose}
|
||||
/>
|
||||
<ConfirmModal
|
||||
modalText={t('DEL_CONFIRM')}
|
||||
view={deleteSubmitModal}
|
||||
handleSubmit={handleDeleteSubmit}
|
||||
handleCancel={handleDeleteClose}
|
||||
handleClose={handleDeleteClose}
|
||||
/>
|
||||
<CompletedModal
|
||||
view={deleteCompleteModal}
|
||||
modalText={t('DEL_COMPLETE')}
|
||||
handleComplete={handleDeleteComplete}
|
||||
/>
|
||||
{/* <InfoSubTitle>의상 탭</InfoSubTitle>
|
||||
<UserTableWrapper>
|
||||
<UserDefaultTable>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="80">no.</th>
|
||||
<th width="120">ID</th>
|
||||
<th width="50%">아이템</th>
|
||||
<th width="100">보유개수</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{dataList &&
|
||||
dataList.inventory_list.cloth.map((el, idx) => {
|
||||
return (
|
||||
<tr key={idx}>
|
||||
<td>{idx + 1}</td>
|
||||
<td>{el.item_id}</td>
|
||||
<td>{el.item_name}</td>
|
||||
<td>{el.count}</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</UserDefaultTable>
|
||||
</UserTableWrapper>
|
||||
<InfoSubTitle>소품 탭</InfoSubTitle>
|
||||
<UserTableWrapper>
|
||||
<UserDefaultTable>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="80">no.</th>
|
||||
<th width="120">ID</th>
|
||||
<th width="50%">아이템</th>
|
||||
<th width="100">보유개수</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{dataList &&
|
||||
dataList.inventory_list.prop.map((el, idx) => {
|
||||
return (
|
||||
<tr key={idx}>
|
||||
<td>{idx + 1}</td>
|
||||
<td>{el.item_id}</td>
|
||||
<td>{el.item_name}</td>
|
||||
<td>{el.count}</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</UserDefaultTable>
|
||||
</UserTableWrapper>
|
||||
<InfoSubTitle>미용 탭</InfoSubTitle>
|
||||
<UserTableWrapper>
|
||||
<UserDefaultTable>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="80">no.</th>
|
||||
<th width="120">ID</th>
|
||||
<th width="50%">아이템</th>
|
||||
<th width="100">보유개수</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{dataList &&
|
||||
dataList.inventory_list.beauty.map((el, idx) => {
|
||||
return (
|
||||
<tr key={idx}>
|
||||
<td>{idx + 1}</td>
|
||||
<td>{el.item_id}</td>
|
||||
<td>{el.item_name}</td>
|
||||
<td>{el.count}</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</UserDefaultTable>
|
||||
</UserTableWrapper>
|
||||
<InfoSubTitle>타투 탭</InfoSubTitle>
|
||||
<UserTableWrapper>
|
||||
<UserDefaultTable>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="80">no.</th>
|
||||
<th width="120">ID</th>
|
||||
<th width="50%">아이템</th>
|
||||
<th width="100">보유개수</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{dataList &&
|
||||
dataList.inventory_list.tattoo.map((el, idx) => {
|
||||
return (
|
||||
<tr key={idx}>
|
||||
<td>{idx + 1}</td>
|
||||
<td>{el.item_id}</td>
|
||||
<td>{el.item_name}</td>
|
||||
<td>{el.count}</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</UserDefaultTable>
|
||||
</UserTableWrapper>
|
||||
<InfoSubTitle>기타 탭</InfoSubTitle>
|
||||
<UserTableWrapper>
|
||||
<UserDefaultTable>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="80">슬롯 no.</th>
|
||||
<th width="320">ID</th>
|
||||
<th width="50%">아이템</th>
|
||||
<th width="100">보유개수</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{dataList &&
|
||||
dataList.inventory_list.etc.map((el, idx) => {
|
||||
return (
|
||||
<tr key={idx}>
|
||||
<td>{idx + 1}</td>
|
||||
<td>{el.item_id}</td>
|
||||
<td>{el.item_name}</td>
|
||||
<td>{el.count}</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</UserDefaultTable>
|
||||
</UserTableWrapper> */}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserInventoryInfo;
|
||||
|
||||
398
src/components/DataManage/UserMailInfo.js
Normal file
@@ -0,0 +1,398 @@
|
||||
import { useState, Fragment, useEffect } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import styled from 'styled-components';
|
||||
|
||||
import CheckBox from '../../components/common/input/CheckBox';
|
||||
import MailDetailModal from '../../components/DataManage/MailDetailModal';
|
||||
import { SelectInput, TextInput } from '../../styles/Components';
|
||||
import { UserMailDelete, UserMailItemDelete, UserMailView } from '../../apis';
|
||||
import ConfirmModal from '../common/modal/ConfirmModal';
|
||||
import CompletedModal from '../common/modal/CompletedModal';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import CustomConfirmModal from '../common/modal/CustomConfirmModal';
|
||||
import DynamicModal from '../common/modal/DynamicModal';
|
||||
import { authType, ivenTabType } from '../../assets/data';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { authList } from '../../store/authList';
|
||||
import { convertKTC } from '../../utils';
|
||||
import { TableSkeleton } from '../Skeleton/TableSkeleton';
|
||||
|
||||
const UserMailInfo = ({ userInfo }) => {
|
||||
const token = sessionStorage.getItem('token');
|
||||
const { t } = useTranslation();
|
||||
const authInfo = useRecoilValue(authList);
|
||||
|
||||
//데이터 리스트
|
||||
const [dataList, setDataList] = useState([]);
|
||||
// 받은 우편, 보낸 우편
|
||||
const [option, setOption] = useState('RECEIVE');
|
||||
// 상세 정보
|
||||
const [detail, setDetail] = useState({ title: '', content: '', item_list: [], mail_guid: '' });
|
||||
const [deleteSelected, setDeleteSelected] = useState({});
|
||||
const [itemUpdateCount, setItemUpdateCount] = useState('1');
|
||||
const [authDelete, setAuthDelete] = useState(false);
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
const [modalState, setModalState] = useState({
|
||||
detailModal: 'hidden',
|
||||
deleteItemModal: 'hidden',
|
||||
deleteSubmitModal: 'hidden',
|
||||
deleteCompleteModal: 'hidden',
|
||||
deleteItemCompleteModal: 'hidden'
|
||||
});
|
||||
|
||||
// 받은 우편, 보낸 우편 option 에 따른 data fetch
|
||||
useEffect(() => {
|
||||
fetchData(option);
|
||||
}, [option]);
|
||||
|
||||
useEffect(() => {
|
||||
setAuthDelete(authInfo.auth_list.some(auth => auth.id === authType.userSearchDelete));
|
||||
}, [authInfo]);
|
||||
|
||||
const fetchData = async option => {
|
||||
await UserMailView(token, userInfo.guid, option).then(data =>{
|
||||
setDataList(data);
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
// 상세 모달 value 세팅
|
||||
const handleDetail = (title, content, itmeList, mail_guid) => {
|
||||
setDetail({ title: title, content: content, item_list: itmeList, mail_guid: mail_guid });
|
||||
};
|
||||
|
||||
// 우편 아이템 삭제 개수 처리
|
||||
const handleItemCount = e => {
|
||||
if (e.target.value === '0' || e.target.value === '-0') {
|
||||
setItemUpdateCount('1');
|
||||
e.target.value = '1';
|
||||
} else if (e.target.value < 0) {
|
||||
let plusNum = Math.abs(e.target.value);
|
||||
setItemUpdateCount(plusNum);
|
||||
} else if(e.target.value > deleteSelected.count){
|
||||
alert(t('DEL_COUNT_CHECK'));
|
||||
setItemUpdateCount(deleteSelected.count);
|
||||
} else {
|
||||
setItemUpdateCount(e.target.value);
|
||||
}
|
||||
};
|
||||
|
||||
const handleModalView = (type) => {
|
||||
setModalState((prevState) => ({
|
||||
...prevState,
|
||||
[`${type}Modal`]: 'view',
|
||||
}));
|
||||
}
|
||||
|
||||
const handleModalClose = (type) => {
|
||||
setModalState((prevState) => ({
|
||||
...prevState,
|
||||
[`${type}Modal`]: 'hidden',
|
||||
}));
|
||||
}
|
||||
|
||||
const handleModalSubmit = async (type, param = null) => {
|
||||
let params;
|
||||
let result;
|
||||
switch (type) {
|
||||
case "detail":
|
||||
handleModalView('deleteSubmit');
|
||||
break;
|
||||
case "deleteItem":
|
||||
setDeleteSelected(param);
|
||||
handleModalView('deleteItem');
|
||||
break;
|
||||
case "deleteSubmit":
|
||||
params = {}
|
||||
params.type = option;
|
||||
params.guid = userInfo.guid;
|
||||
params.mail_guid = detail.mail_guid;
|
||||
|
||||
result = await UserMailDelete(token, params);
|
||||
|
||||
handleModalClose('deleteSubmit');
|
||||
handleModalView('deleteComplete');
|
||||
break;
|
||||
case "deleteItemSubmit":
|
||||
params = {}
|
||||
params.type = option;
|
||||
params.guid = userInfo.guid;
|
||||
params.mail_guid = detail.mail_guid;
|
||||
params.item_id = deleteSelected.item_id;
|
||||
params.parrent_count = deleteSelected.count;
|
||||
params.count = itemUpdateCount;
|
||||
|
||||
result = await UserMailItemDelete(token, params);
|
||||
if(result.result === "SUCCESS"){
|
||||
if(deleteSelected.count <= itemUpdateCount){
|
||||
const item_idx = detail.item_list.findIndex(item => item.item_id === deleteSelected.item_id);
|
||||
if(item_idx >= 0) {
|
||||
detail.item_list.splice(item_idx, 1);
|
||||
}
|
||||
}else{
|
||||
deleteSelected.count = deleteSelected.count - itemUpdateCount;
|
||||
}
|
||||
}
|
||||
handleModalClose('deleteItem');
|
||||
handleModalView('deleteItemComplete');
|
||||
break;
|
||||
case "deleteComplete":
|
||||
handleModalClose('deleteComplete');
|
||||
handleModalClose('detail');
|
||||
// const idx = dataList.mail_list.findIndex(mail => mail.mail_guid === detail.mail_guid);
|
||||
// if(idx >= 0) {
|
||||
// dataList.mail_list.splice(idx, 1);
|
||||
// }
|
||||
fetchData(option);
|
||||
break;
|
||||
case "deleteItemComplete":
|
||||
handleModalClose('deleteItemComplete');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const ConfirmChild = () => {
|
||||
return(
|
||||
<InputItem>
|
||||
<p>{t('DEL_COUNT_CONFIRM', {count: deleteSelected.count})}</p>
|
||||
<TextInput placeholder="수량" type="number" value={itemUpdateCount} onChange={e => handleItemCount(e)} width="200px" />
|
||||
</InputItem>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
loading ? <TableSkeleton count={10}/> :
|
||||
<>
|
||||
<SelectWrapper>
|
||||
<SelectInput
|
||||
value={option}
|
||||
onChange={e => {
|
||||
setOption(e.target.value);
|
||||
}}>
|
||||
<option value="RECEIVE">받은 우편</option>
|
||||
<option value="SEND">보낸 우편</option>
|
||||
</SelectInput>
|
||||
</SelectWrapper>
|
||||
{option === 'RECEIVE' && (
|
||||
<>
|
||||
{/* <CheckWrapper>
|
||||
<CheckBox id="viewDelReceiveMail" label="삭제 우편 보기" />
|
||||
</CheckWrapper> */}
|
||||
<UserTableWrapper>
|
||||
<UserDefaultTable>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="170">수신일자</th>
|
||||
<th width="200">발송자</th>
|
||||
<th width="300">우편 제목</th>
|
||||
<th width="80">상태</th>
|
||||
<th width="100">첨부 아이템</th>
|
||||
<th width="80">수령</th>
|
||||
<th width="80">시스템 우편</th>
|
||||
{/* <th width="170">수령 일자</th> */}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{dataList.mail_list &&
|
||||
dataList.mail_list.map((mail, idx) => {
|
||||
return (
|
||||
<tr key={idx}>
|
||||
<td>{convertKTC(mail.create_time)}</td>
|
||||
<td>{mail.sender_nickname}</td>
|
||||
<td>
|
||||
<MailLink
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
handleModalView('detail');
|
||||
handleDetail(mail.title, mail.content, mail.item_list, mail.mail_guid);
|
||||
}}>
|
||||
{mail.title}
|
||||
</MailLink>
|
||||
</td>
|
||||
<td>{mail.status === true ? '확인' : '미확인'}</td>
|
||||
<td>{mail.item_list.length > 0 ? 'Y' : 'N'}</td>
|
||||
<td>{mail.is_get_item === true ? '수령함' : '미수령함'}</td>
|
||||
<td>{mail.is_system_mail === true ? 'Y' : 'N'}</td>
|
||||
{/* <td>
|
||||
{mail.is_get_item_dt && String(new Date(new Date(mail.is_get_item_dt).setHours(new Date(mail.is_get_item_dt).getHours() + 9)).toLocaleString())}
|
||||
</td> */}
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</UserDefaultTable>
|
||||
</UserTableWrapper>
|
||||
</>
|
||||
)}
|
||||
{option === 'SEND' && (
|
||||
<>
|
||||
{/* <CheckWrapper>
|
||||
<CheckBox id="viewDelSendMail" label="삭제 우편 보기" />
|
||||
</CheckWrapper> */}
|
||||
<UserTableWrapper>
|
||||
<UserDefaultTable>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="170">발송 일자</th>
|
||||
<th width="200">수신자</th>
|
||||
<th width="300">우편 제목</th>
|
||||
<th width="120">첨부 아이템</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{dataList.mail_list &&
|
||||
dataList.mail_list.map((mail, idx) => {
|
||||
return (
|
||||
<tr key={idx}>
|
||||
<td>{convertKTC(mail.create_time)}</td>
|
||||
<td>{mail.receiver_nickname}</td>
|
||||
<td>
|
||||
<MailLink
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
handleModalView('detail');
|
||||
handleDetail(mail.title, mail.content, mail.item_list, mail.mail_guid);
|
||||
}}>
|
||||
{mail.title}
|
||||
</MailLink>
|
||||
</td>
|
||||
<td>{mail.item_list.length > 0 ? 'Y' : 'N'}</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</UserDefaultTable>
|
||||
</UserTableWrapper>
|
||||
</>
|
||||
)}
|
||||
{/*상세*/}
|
||||
<MailDetailModal
|
||||
mailModal={modalState.detailModal}
|
||||
handleClick={() => handleModalClose('detail')}
|
||||
setDetail={setDetail}
|
||||
content={detail}
|
||||
handleDelete={() => handleModalSubmit('detail')}
|
||||
handleItemDelete={(param) => handleModalSubmit('deleteItem', param)}
|
||||
authDelete={authDelete}
|
||||
/>
|
||||
{/*메일 삭제 모달*/}
|
||||
<ConfirmModal
|
||||
modalText={t('USER_MAIL_DEL_CONFIRM')}
|
||||
view={modalState.deleteSubmitModal}
|
||||
handleSubmit={() => handleModalSubmit('deleteSubmit')}
|
||||
handleCancel={() => handleModalClose('deleteSubmit')}
|
||||
handleClose={() => handleModalClose('deleteSubmit')}
|
||||
/>
|
||||
<CompletedModal
|
||||
view={modalState.deleteCompleteModal}
|
||||
modalText={t('DEL_COMPLETE')}
|
||||
handleComplete={() => handleModalSubmit('deleteComplete')}
|
||||
/>
|
||||
{/*메일 아이템 삭제 모달*/}
|
||||
<CustomConfirmModal
|
||||
ChildView={ConfirmChild}
|
||||
view={modalState.deleteItemModal}
|
||||
handleSubmit={() => handleModalSubmit('deleteItemSubmit')}
|
||||
handleCancel={() => handleModalClose('deleteItem')}
|
||||
handleClose={() => handleModalClose('deleteItem')}
|
||||
/>
|
||||
<CompletedModal
|
||||
view={modalState.deleteItemCompleteModal}
|
||||
modalText={t('DEL_ITEM_COMPLETE')}
|
||||
handleComplete={() => handleModalSubmit('deleteItemComplete')}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserMailInfo;
|
||||
|
||||
const UserDefaultTable = styled.table`
|
||||
border: 1px solid #e8eaec;
|
||||
border-top: 1px solid #000;
|
||||
font-size: 14px;
|
||||
margin-bottom: 40px;
|
||||
th {
|
||||
background: #efefef;
|
||||
font-weight: 700;
|
||||
}
|
||||
th,
|
||||
td {
|
||||
padding: 12px;
|
||||
text-align: center;
|
||||
border-left: 1px solid #e8eaec;
|
||||
vertical-align: middle;
|
||||
}
|
||||
td {
|
||||
background: #fff;
|
||||
border-bottom: 1px solid #e8eaec;
|
||||
word-break: break-all;
|
||||
}
|
||||
button {
|
||||
height: 24px;
|
||||
font-size: 13px;
|
||||
}
|
||||
`;
|
||||
|
||||
const QuestTable = styled(UserDefaultTable)`
|
||||
tbody {
|
||||
td {
|
||||
padding: 9px 12px;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const UserTableWrapper = styled.div`
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
margin-bottom: 40px;
|
||||
${UserDefaultTable}, ${QuestTable} {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
&::-webkit-scrollbar {
|
||||
height: 4px;
|
||||
}
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #666666;
|
||||
}
|
||||
&::-webkit-scrollbar-track {
|
||||
background: #d9d9d9;
|
||||
}
|
||||
`;
|
||||
|
||||
const MailLink = styled.div`
|
||||
color: #61a2d0;
|
||||
text-decoration: underline;
|
||||
`;
|
||||
|
||||
const SelectWrapper = styled.div`
|
||||
select {
|
||||
height: 30px;
|
||||
}
|
||||
margin-bottom: 10px;
|
||||
`;
|
||||
const CheckWrapper = styled.div`
|
||||
text-align: right;
|
||||
padding: 10px;
|
||||
margin-top: -40px;
|
||||
height: 30px;
|
||||
margin-bottom: 10px;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
`;
|
||||
|
||||
const InputItem = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center; /* 수평 중앙 정렬 */
|
||||
gap: 10px;
|
||||
${TextInput} {
|
||||
height: 35px;
|
||||
font-size: 14px;
|
||||
width: 100px;
|
||||
padding: 10px 20px;
|
||||
}
|
||||
`;
|
||||
70
src/components/DataManage/UserMyHomeInfo.js
Normal file
@@ -0,0 +1,70 @@
|
||||
import styled from 'styled-components';
|
||||
import Button from '../common/button/Button';
|
||||
import { InfoSubTitle, UserDefaultTable, UserInfoTable, UserTableWrapper } from '../../styles/ModuleComponents';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { authList } from '../../store/authList';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { TableSkeleton } from '../Skeleton/TableSkeleton';
|
||||
import { UserInventoryView, UserMyhomeView } from '../../apis';
|
||||
|
||||
const UserMyHomeInfo = ({ userInfo }) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [dataList, setDataList] = useState();
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
const fetchData = async () => {
|
||||
const token = sessionStorage.getItem('token');
|
||||
await UserMyhomeView(token, userInfo.guid).then(data => {
|
||||
setDataList(data.myhome_info);
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
loading ? <TableSkeleton count={15}/> :
|
||||
dataList &&
|
||||
<>
|
||||
<UserInfoTable $maxwidth="700px">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>마이 홈명</th>
|
||||
<td>{dataList.myhome_name}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</UserInfoTable>
|
||||
<InfoSubTitle top='30px'>배치 소품</InfoSubTitle>
|
||||
<UserTableWrapper>
|
||||
<UserDefaultTable>
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="80">no.</th>
|
||||
<th width="120">아이템ID</th>
|
||||
<th width="50%">아이템명</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{dataList.prop_list && dataList.prop_list.map((el, idx) => {
|
||||
return (
|
||||
<tr key={idx}>
|
||||
<td>{idx + 1}</td>
|
||||
<td>{el.item_id}</td>
|
||||
<td>{el.item_name}</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</UserDefaultTable>
|
||||
</UserTableWrapper>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserMyHomeInfo;
|
||||
|
||||
|
||||