diff --git a/src/App.tsx b/src/App.tsx index 1b6594e..0ba8161 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,7 +5,15 @@ import { ToastContainer } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.css'; import { Navbar } from './components'; -import { MainPage, SuccessPage, DownloadPage, DeletePage, FileListPage } from './pages'; +import { + MainPage, + SuccessPage, + DownloadPage, + DeletePage, + FileListPage, + ApiPage, + NotFoundPage, +} from './pages'; import { store } from './state/store'; export const App: React.FC = () => ( @@ -41,6 +49,8 @@ export const App: React.FC = () => ( } /> } /> } /> + } /> + } /> diff --git a/src/components/common/FileListBox/styled.ts b/src/components/common/FileListBox/styled.ts index 188c4d1..ca82e66 100644 --- a/src/components/common/FileListBox/styled.ts +++ b/src/components/common/FileListBox/styled.ts @@ -2,7 +2,7 @@ import styled from '@emotion/styled'; export const FileListBoxContainer = styled.div` background-color: var(--color-backgorund-filelistbox); - color: var(--color-text-filelistbox); + color: var(--color-text-tertiary); border-radius: 10px; padding: 1.2rem 1.2rem 1.2rem 1.2rem; display: flex; diff --git a/src/components/common/Navbar/index.tsx b/src/components/common/Navbar/index.tsx index 158854f..199306c 100644 --- a/src/components/common/Navbar/index.tsx +++ b/src/components/common/Navbar/index.tsx @@ -1,22 +1,11 @@ import React from 'react'; -import { toast } from 'react-toastify'; import * as S from './styled'; export const Navbar: React.FC = () => ( Upload - { - toast.success('제작중!', { - autoClose: 1000, - position: toast.POSITION.BOTTOM_RIGHT, - }); - }} - > - API - + API File list ); diff --git a/src/components/common/Navbar/styled.ts b/src/components/common/Navbar/styled.ts index 7fdbdc1..9d71ba8 100644 --- a/src/components/common/Navbar/styled.ts +++ b/src/components/common/Navbar/styled.ts @@ -7,6 +7,7 @@ export const NavbarContainer = styled.nav` margin: 30px auto 30px auto; display: flex; justify-content: space-between; + z-index: 99; `; export const Nav = styled(Link)` diff --git a/src/components/common/SkeletonUIBox/index.ts b/src/components/common/SkeletonUIBox/index.ts new file mode 100644 index 0000000..7ff992b --- /dev/null +++ b/src/components/common/SkeletonUIBox/index.ts @@ -0,0 +1,64 @@ +import styled from '@emotion/styled'; +export const SkeletonUIBox = styled.div<{ randomWitdh: string }>` + display: flex; + background-color: var(--color-backgorund-filelistbox); + border-radius: 10px; + margin-bottom: 1.5rem; + min-height: 4.6rem; + min-width: ${(props) => props.randomWitdh}rem; + overflow: hidden; + &::before { + content: ' '; + width: 100%; + height: auto; + animation: loading 2s infinite; + box-shadow: 0 0 30px 30px rgba(255, 255, 255, 0.3); + } + @keyframes loading { + 0% { + transform: translateX(-50%); + } + 50% { + transform: translateX(100%); + } + 100% { + transform: translate(200%); + } + } +`; +export const SkeletonUIApiBox = styled(SkeletonUIBox)` + min-height: 6.2rem; + margin: 1rem; +`; + +export const SkeletonUI = styled.div<{ + width: string; + height: string; + margin: string; +}>` + display: flex; + min-width: ${(props) => props.width}; + min-height: ${(props) => props.height}; + margin: ${(props) => props.margin}; + background: var(--color-backgorund-filelistbox); + border-radius: 10px; + overflow: hidden; + &::before { + content: ' '; + width: 100%; + height: auto; + animation: loading 2s infinite; + box-shadow: 0 0 30px 30px rgba(255, 255, 255, 0.3); + } + @keyframes loading { + 0% { + transform: translateX(-50%); + } + 50% { + transform: translateX(100%); + } + 100% { + transform: translate(200%); + } + } +`; diff --git a/src/components/common/index.ts b/src/components/common/index.ts index 1c2559f..bdee441 100644 --- a/src/components/common/index.ts +++ b/src/components/common/index.ts @@ -7,3 +7,4 @@ export * from './Navbar'; export * from './Button'; export * from './FileListBox'; export * from './Progress'; +export * from './SkeletonUIBox'; diff --git a/src/pages/api/index.tsx b/src/pages/api/index.tsx new file mode 100644 index 0000000..2dbe97d --- /dev/null +++ b/src/pages/api/index.tsx @@ -0,0 +1,74 @@ +import axios from 'axios'; +import React, { useState, useEffect } from 'react'; +import { Route, Routes, Link } from 'react-router-dom'; + +import { SkeletonUIApiBox } from '../../components'; +import { ApiPostPage } from '../postApi'; +import * as S from './styled'; + +export const ApiPage: React.FC = () => { + const [loading, setLoading] = useState(false); + const [apiInfo, setApiInfo] = useState(); + const SkeletonUIRandomWidth = ['40', '50', '55', '45']; + const getApiInfo = async () => { + await axios({ + method: 'get', + url: 'https://tfb.minpeter.cf/info', + }) + .then((res) => { + setApiInfo(res.data); + setTimeout(() => { + setLoading(true); //loading 확인하고싶으면 false로 바꿔주세요. + }, 1200); + }) + .catch((err) => { + console.log(err); + }); + }; + + useEffect(() => { + getApiInfo(); + }, []); + + return ( + + + + + {loading ? ( + <> + {apiInfo?.map((item, index) => ( + + {item.apiUrl} + + ))} + + ) : ( + <> + + + + + + )} + + + + } + /> + } /> + + + ); +}; diff --git a/src/pages/api/styled.ts b/src/pages/api/styled.ts new file mode 100644 index 0000000..51a526a --- /dev/null +++ b/src/pages/api/styled.ts @@ -0,0 +1,40 @@ +import styled from '@emotion/styled'; + +export const ApiPageContainer = styled.div` + display: flex; + align-items: center; + flex-direction: column; +`; + +export const ApiListSection = styled.div` + overflow-y: auto; + display: flex; + flex-direction: column; + align-items: center; + max-height: 40rem; + &::-webkit-scrollbar { + display: none; + } +`; + +export const ApiListBox = styled.div` + background-color: var(--color-backgorund-filelistbox); + color: var(--color-text-tertiary); + border-radius: 10px; + padding: 2rem 1.4rem 2rem 1.4rem; + margin: 1rem; + display: flex; + flex-direction: row; + align-items: center; + font-size: 2.2rem; + font-weight: 700; + cursor: pointer; +`; + +export const ApiListSectionShadow = styled.div` + width: 100%; + height: 6rem; + position: relative; + top: -25px; + background: linear-gradient(180deg, rgba(40, 42, 58, 0) 0%, #282a3a 45.31%); +`; diff --git a/src/pages/download/styled.ts b/src/pages/download/styled.ts index 0e7cf2d..b035ca7 100644 --- a/src/pages/download/styled.ts +++ b/src/pages/download/styled.ts @@ -15,7 +15,7 @@ export const DownloadPageButtonSection = styled.div` export const DonwloadFileBox = styled.div` background-color: var(--color-backgorund-filelistbox); - color: var(--color-text-filelistbox); + color: var(--color-text-tertiary); border-radius: 10px; padding: 1.2rem 1.2rem 1.2rem 1.2rem; display: flex; diff --git a/src/pages/filelist/index.tsx b/src/pages/filelist/index.tsx index 1dd8db8..09bc3ab 100644 --- a/src/pages/filelist/index.tsx +++ b/src/pages/filelist/index.tsx @@ -4,7 +4,7 @@ import { useDispatch } from 'react-redux'; import { useNavigate } from 'react-router-dom'; import { bindActionCreators } from 'redux'; -import { FileListBox } from '../../components'; +import { FileListBox, SkeletonUIBox } from '../../components'; import { actionCreators } from '../../state'; import { getFileSize, getShortFileName, getDate } from '../../utils'; import * as S from './styled'; @@ -25,7 +25,7 @@ export const FileListPage: React.FC = () => { setFileList(res.data.list); //파일리스트 요소 갯수에 따른 핸들링 추가예정 setTimeout(() => { setLoading(true); //loading 확인하고싶으면 false로 바꿔주세요. - }, 1500); + }, 1200); }) .catch((err) => { console.log(err); @@ -62,27 +62,13 @@ export const FileListPage: React.FC = () => { ) : ( <> - - - - - - - + + + + + + + diff --git a/src/pages/filelist/styled.ts b/src/pages/filelist/styled.ts index 77f8d8e..03bdfdf 100644 --- a/src/pages/filelist/styled.ts +++ b/src/pages/filelist/styled.ts @@ -18,31 +18,3 @@ export const FileListPageBoxShoadow = styled.div` top: -25px; background: linear-gradient(180deg, rgba(40, 42, 58, 0) 0%, #282a3a 45.31%); `; - -export const FileListSkeletonUI = styled.div<{ randomWitdh: string }>` - display: flex; - background-color: var(--color-backgorund-filelistbox); - border-radius: 10px; - margin-bottom: 1.5rem; - min-height: 4.6rem; - min-width: ${(props) => props.randomWitdh}rem; - overflow: hidden; - &::before { - content: ' '; - width: 100%; - height: auto; - animation: loading 2s infinite; - box-shadow: 0 0 30px 30px rgba(255, 255, 255, 0.3); - } - @keyframes loading { - 0% { - transform: translateX(-50%); - } - 50% { - transform: translateX(100%); - } - 100% { - transform: translate(200%); - } - } -`; diff --git a/src/pages/index.ts b/src/pages/index.ts index 0986ab2..3fdcd0e 100644 --- a/src/pages/index.ts +++ b/src/pages/index.ts @@ -3,3 +3,5 @@ export * from './success'; export * from './download'; export * from './delete'; export * from './filelist'; +export * from './api'; +export * from './notfound'; diff --git a/src/pages/main/index.tsx b/src/pages/main/index.tsx index 35161de..8709bd4 100644 --- a/src/pages/main/index.tsx +++ b/src/pages/main/index.tsx @@ -18,6 +18,7 @@ export const MainPage: React.FC = () => { const [retentionPeriod, setRetentionPeriod] = useState(false); const [downloadCount, setDownloadCount] = useState(false); const [passwordBoolean, setPasswordBoolean] = useState(false); + const [password, setPassword] = useState(''); const [fileProps, setFileProps] = useState({ name: '', size: '', fileType: '', fileData: '' }); const navigate = useNavigate(); @@ -41,7 +42,9 @@ export const MainPage: React.FC = () => { formdata.append('file', fileProps.fileData); await axios({ method: 'post', - url: 'https://tfb.minpeter.cf/upload', + url: `https://tfb.minpeter.cf/upload${ + passwordBoolean && password != '' && password != undefined ? `?pw=${password}` : '' + }`, data: formdata, headers: { 'Content-Type': 'multipart/form-data', @@ -52,6 +55,7 @@ export const MainPage: React.FC = () => { }, }) .then(async (res) => { + console.log(res); setUploading(true); toast.success('업로드 성공!', { autoClose: 3000, @@ -119,18 +123,21 @@ export const MainPage: React.FC = () => { label={'다운로드 횟수'} /> { - setPasswordBoolean(false); - toast.success('제작중!', { - autoClose: 1000, - position: toast.POSITION.BOTTOM_RIGHT, - }); - }} + click={() => setPasswordBoolean(!passwordBoolean)} isCheck={passwordBoolean} label={'비밀번호'} /> - {passwordBoolean ? : <>} + {passwordBoolean ? ( + { + setPassword(text.target.value.replace(/(\s*)/g, '')); + }} + placeholder="비밀번호를 입력해주세요." + /> + ) : ( + <> + )} diff --git a/src/pages/notfound/index.tsx b/src/pages/notfound/index.tsx new file mode 100644 index 0000000..c6c4185 --- /dev/null +++ b/src/pages/notfound/index.tsx @@ -0,0 +1,5 @@ +import React from 'react'; + +import * as S from './styled'; + +export const NotFoundPage: React.FC = () => 404; diff --git a/src/pages/notfound/styled.ts b/src/pages/notfound/styled.ts new file mode 100644 index 0000000..36b117a --- /dev/null +++ b/src/pages/notfound/styled.ts @@ -0,0 +1,3 @@ +import styled from '@emotion/styled'; + +export const NotFoundPage = styled.div``; diff --git a/src/pages/postApi/index.tsx b/src/pages/postApi/index.tsx new file mode 100644 index 0000000..847c297 --- /dev/null +++ b/src/pages/postApi/index.tsx @@ -0,0 +1,68 @@ +import axios from 'axios'; +import React, { useEffect, useState } from 'react'; +import { useParams } from 'react-router-dom'; +import { useNavigate } from 'react-router-dom'; +import { toast } from 'react-toastify'; + +import { Button, SkeletonUI } from '../../components'; +import * as S from './styled'; + +export const ApiPostPage: React.FC = () => { + const [apiInfo, setApiInfo] = useState(); + const [loading, setLoading] = useState(false); + const { urlApi } = useParams<{ urlApi: string }>(); + const navigate = useNavigate(); + useEffect(() => { + const getUrlApiInfo = async () => { + await axios({ + method: 'get', + url: `https://tfb.minpeter.cf/info?api=${urlApi}`, + }) + .then((res) => { + if (res.data?.message === 'invalid api name') { + navigate('/404'); //나중에 404페이지로 이동하게 + } else { + setApiInfo(res.data); + setTimeout(() => { + setLoading(true); //loading 확인하고싶으면 false로 바꿔주세요. + }, 1200); + } + }) + .catch((err) => { + console.log(err); + }); + }; + getUrlApiInfo(); + }, [navigate, urlApi]); + return ( + <> + {loading ? ( + <> + + {apiInfo?.apiName} / method: {apiInfo?.method} + + {apiInfo?.desc} + {apiInfo?.command} +