From 21d146f58be4748ed036f0f3f0aa30e65a3e8dd1 Mon Sep 17 00:00:00 2001 From: Ethan Lim Date: Thu, 23 Nov 2023 06:32:35 +0900 Subject: [PATCH] =?UTF-8?q?[#45]=20feat=20:=20=EA=B0=9C=EB=B3=84=20?= =?UTF-8?q?=EB=8C=80=EC=8B=9C=EB=B3=B4=EB=93=9C=20=EA=B0=9C=EB=B0=9C=20?= =?UTF-8?q?=EB=B0=8F=20=EC=A0=84=EC=B2=B4=EB=8C=80=EC=8B=9C=EB=B3=B4?= =?UTF-8?q?=EB=93=9C=20=EC=83=89=EC=83=81=20=EC=88=98=EC=A0=95=20(#46)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Release test 0.0.1 (#41) * feat: 기본 컴포넌트 생성 * feat: 지도 구현 * Update README.md * Update README.md * Update README.md * feat: marker 이미지 추가 * feat: only icon marker 디자인 완료 * feat: name marker 디자인 완료 * refactor: 지도에 보이는 방식 변경 * feat: 업체 리스트 디자인 완료 하트 상태 useState로 관리 * Create pull_request_template.md * feat: 검색창 구현 * feat: 픽한업체 디자인 * refactor: 겹치는 코드 분리 size 인수로 받는 함수 만들어서 그 사이즈에 맞게 이미지 코드 반환 * feat: 필터 디자인 완료 * feat: 스크롤바 디자인 * style: store list 디자인 변경사항 반영 * style: 이름 마커 디자인 수정 * feat: 라우터 설정 * feat: 가게 정보 디자인 완료 * style: heart -> :+1: 으로 디자인 변경 * fix: 지도 안뜨는 문제 해결 * refact: 공통 컴포넌트 분리 (필터, 검색창) * refact: 이름 마커 컴포넌트 공통으로 리팩토링 * refact: children props 넘겨주는 방식 변경 * refact: icon marker 코드 하나로 분리 * chore: 해당하는 마커만 지도에 띄우기 * fix: 우선 error는 안뜨도록 수정 * fix: 같은 매장 여러번 클릭할 수 있도록 수정 * fix: 기본값 설정 * docs: PR template update 체크리스트 추가 * [#17] feat: 헤더 #17 (#21) * feat : 화면 구현 * feat : 헤더 구현 * style : 알림 아이콘 추가 * [#3] feat: 제휴가게 페이지 (#13) * feat: component 구성 * style: 타이틀 디자인 구현 완성 * style: 필터, 검색, 버튼 디자인 완료 * style: store 컴포넌트 디자인 완료 * style: 변경된 디자인 반영 * feat: 가게 검색 모달 창 디자인 완료 * feat: 공통 버튼 컴포넌트 분리 * feat: [제휴가게 조회] 컴포넌트 구성 * style: [제휴가게 조회] 화면 디자인 완료 * feat: 스탬프 모달 완성 * feat: 조건 박스 추가 * refact: modal 폴더 생성 * feat: 제휴 종료 모달 완성 * fix: 버튼 스타일링 변경 * refact: && 연산자로 변경 * [#22] feat: 가게 찾기 페이지 API 연결 (#25) * fix: img 오류 수정 * feat: api data 형식 추가 및 적용 * feat: 가게 전체 조회 api 연결 * style: 제목 div 깨짐 수정 * feat: map type filter 설정 * feat: filter API 설정 * feat: 위도 경도 연결 * refact: 전체 필터용으로 api 방식 수정 * feat: 픽한업체 필터 설정 * feat: 검색어 필터 연결 /contact 부분 props 수정 필요 * feat: storeInfo와 filter 예외처리 storeInfo가 열려있는 상태로 filter를 누르면 지도 내용이 누른 filter를 반영하도록 변경 * chore: 사용안하는 코드 삭제 * feat: 픽한 업체 API 연결 * feat: 가게 상세 정보 조회 API 연결 * fix: 선택한 가게 기본값 설정 * feat: 이름 마커 zindex 설정 * feat: 맨 위 데이터 "이름 마커" 로 뜨는 조건 * style: 디자인적 요소 수정 cursor 포인터로, 도보 시간 0분으로 안뜨도록, 픽한 업체 글자 눌렀을때도 클릭 되도록 * [#24] feat : 팝업관리, 쿠폰관리, 마이페이지, 대시보드 화면 구현 (#29) * feat : 화면 구현 * feat : 헤더 구현 * feat : 로그인 모달 구현 * feat : 회원가입 화면 구현 * style : header 알림 아이콘 추가 * style : 로그인 모달 세부 디자인 수정 * feat : api 설정 및 부분 연동 * feat : 로그인 액세스토큰 세션 스토리지에 저장 * feat : 대시보드 레이아웃 잡기 * feat : 첫번째 박스 구현 * feat : 두번째 박스 구현 * feat : 대시보드 화면 완성 * feat : 쿠폰관리 리스트 화면 구현 * feat : 팝업관리 화면 구현 * feat : popup api 연동 * feat : 쿠폰 등록 화면 구현 * feat : 비었을때 보여줄 컴포넌트 삽입 * feat : 팝업등록 화면 구현 * feat : 마이페이지 화면 구현 * feat : 팝업관리 화면 구현, 일부 api 연동 * [#16] feat: 팝업관리 페이지 디자인 구현 (#31) * feat: 가게 검색 모달 창 디자인 완료 * feat: 스탬프 모달 완성 * feat: 조건 박스 추가 * refact: modal 폴더 생성 * feat: 컴포넌트 구성 * feat: 팝업 관리 페이지 디자인 완료 * feat: 환경 설정 package json 수정, base api 수정 * [#28] feat: 제휴가게 API 연결 (#37) * fix: icon 에러 수정 * feat: 제휴가게리스트 API 연결 * feat: 라우터 연결 * fix: img 오류 수정 * feat: 제휴가게 상세 API 연결 * feat: modal api 연결 및 디자인 수정 * style: checkbox 적용 * [#39] fix : 서브메뉴 디자인 변경 및 링크추가 (#40) * style : 팝업 / 쿠폰 관리 삭제박스 추가 * fix : 헤더 디자인 수정 및 링크 추가 --------- Co-authored-by: Ethan Lim * fix : 타입 오류 수정 * fix: error 수정 * fix : 타입 오류 수정 * fix: modal error * fix: npm run build error * fix: build error 해결 * fix: 위치 에러 수정 * feat : 가게 대시보드 구현 --------- Co-authored-by: SuJin --- components/StoreInfo.tsx | 2 +- components/atoms/ChartBackground.svg | 6 +- components/atoms/modalState.tsx | 18 +- components/hooks/useModal.ts | 2 +- components/hooks/usePopupData.ts | 38 +--- components/organisms/Header.tsx | 7 +- components/organisms/Modal.tsx | 6 +- .../styles/CInputs.style.ts | 0 .../styles}/Inputs.style.ts | 0 .../styles}/SecondBox.styles.ts | 0 components/styles/dashboardDetail/style.ts | 114 ++++++++++++ package-lock.json | 16 ++ package.json | 1 + pages/api/ContractAPI.ts | 4 +- pages/api/login.ts | 43 +++-- pages/apply/form/index.tsx | 0 pages/apply/index.tsx | 85 --------- pages/dashboard/BackgroundedChart.tsx | 98 +++++++++++ pages/dashboard/BarChart.tsx | 4 +- pages/dashboard/ComposedChart.tsx | 125 +++++++++++++ pages/dashboard/FifthBox.tsx | 0 pages/dashboard/FirstChart.tsx | 49 ++++++ pages/dashboard/FourthBox.tsx | 0 pages/dashboard/ListChart.tsx | 4 +- pages/dashboard/OneStackChart.tsx | 110 ++++++++++++ pages/dashboard/PieCharts.tsx | 9 +- pages/dashboard/StackCharts.tsx | 4 +- pages/dashboard/[store].tsx | 166 ++++++++++++++++++ pages/dashboard/index.tsx | 14 +- pages/student/coupon/register/Inputs.tsx | 7 +- pages/student/popup/index.tsx | 4 +- pages/student/popup/register/Inputs.tsx | 4 +- pages/user/auth/index.tsx | 11 +- pages/user/form/index.tsx | 4 +- pages/user/index.tsx | 21 +-- 35 files changed, 776 insertions(+), 200 deletions(-) rename pages/student/coupon/register/Inputs.style.ts => components/styles/CInputs.style.ts (100%) rename {pages/student/popup/register => components/styles}/Inputs.style.ts (100%) rename {pages/dashboard => components/styles}/SecondBox.styles.ts (100%) create mode 100644 components/styles/dashboardDetail/style.ts delete mode 100644 pages/apply/form/index.tsx delete mode 100644 pages/apply/index.tsx create mode 100644 pages/dashboard/BackgroundedChart.tsx create mode 100644 pages/dashboard/ComposedChart.tsx delete mode 100644 pages/dashboard/FifthBox.tsx create mode 100644 pages/dashboard/FirstChart.tsx delete mode 100644 pages/dashboard/FourthBox.tsx create mode 100644 pages/dashboard/OneStackChart.tsx create mode 100644 pages/dashboard/[store].tsx diff --git a/components/StoreInfo.tsx b/components/StoreInfo.tsx index 376e847..b4e127a 100644 --- a/components/StoreInfo.tsx +++ b/components/StoreInfo.tsx @@ -54,7 +54,7 @@ const StoreInfo = ({ storeId }: SInfo) => { 전화 컨택 가이드 - 🙂 안녕하세요, 건국대학교 예술대학 학생회 ‘다빈치' 입니다. 건국대 상권 + 🙂 안녕하세요, 건국대학교 예술대학 학생회 다빈치 입니다. 건국대 상권 활성화를 위한 제휴 사업을 제한하고자 합니다. diff --git a/components/atoms/ChartBackground.svg b/components/atoms/ChartBackground.svg index 373882b..65fafaa 100644 --- a/components/atoms/ChartBackground.svg +++ b/components/atoms/ChartBackground.svg @@ -1,4 +1,4 @@ - - - + + + diff --git a/components/atoms/modalState.tsx b/components/atoms/modalState.tsx index 5751344..9e72bbf 100644 --- a/components/atoms/modalState.tsx +++ b/components/atoms/modalState.tsx @@ -1,16 +1,8 @@ import { atom } from "recoil"; +const modalState = atom({ + key: "modalState", + default: false, +}); -if (!global._recoilAtoms) { - global._recoilAtoms = {}; -} - -export const modalState = - global._recoilAtoms.modalState || - atom({ - key: "modalState", - default: false, - }); - -global._recoilAtoms.modalState = modalState; - +export default modalState; diff --git a/components/hooks/useModal.ts b/components/hooks/useModal.ts index e863fd0..c394af6 100644 --- a/components/hooks/useModal.ts +++ b/components/hooks/useModal.ts @@ -1,5 +1,5 @@ import { useSetRecoilState } from "recoil"; -import { modalState } from "../atoms/modalState"; +import modalState from "../atoms/modalState"; export const useModal = () => { const setModalOpen = useSetRecoilState(modalState); diff --git a/components/hooks/usePopupData.ts b/components/hooks/usePopupData.ts index 20e91b3..24a790a 100644 --- a/components/hooks/usePopupData.ts +++ b/components/hooks/usePopupData.ts @@ -1,29 +1,19 @@ import { getPopups } from "@/pages/api/popup"; import { useEffect, useState } from "react"; -enum PopupPeriod { - none, - - aDay = "하루간", - aWeek = "1주간", - twoWeek = "2주간", - aMonth = "1달간", - -} interface Popup { title: string; - contents: string; - period: PopupPeriod; - timing: Date | boolean; - store: string; + content: string; + endData: string; + reservation: string; + storeId: number; } export const usePopupData = () => { const [popups, setPopups] = useState([]); - // api 호출해서 초기화 useEffect(() => { const fetchData = async () => { @@ -40,23 +30,3 @@ export const usePopupData = () => { return { popups }; }; -// 예시 데이터 - - -// const exData: Popup[] = [ -// { -// title: "오늘만 배부른 최뚝배기 가게 5% 추가할인!", -// contents: "내용", -// period: PopupPeriod.twoWeek, -// timing: true, -// store: "최뚝배기", -// }, -// { -// title: "오늘만 배부른 최뚝배기 가게 5% 추가할인!", -// contents: "내용", -// period: PopupPeriod.twoWeek, -// timing: true, -// store: "최뚝배기", -// }, -// ]; - diff --git a/components/organisms/Header.tsx b/components/organisms/Header.tsx index 40882a2..8ba1557 100644 --- a/components/organisms/Header.tsx +++ b/components/organisms/Header.tsx @@ -19,7 +19,7 @@ TODO: const Header = () => { const router = useRouter(); const { openModal } = useModal(); - const [userSessionData, setUserSessionData] = useState(); + const [userSessionData, setUserSessionData] = useState(null); const setLogout = useSetRecoilState(initialState); @@ -45,7 +45,6 @@ const Header = () => { }); }; - return ( { />
    - { if (userSessionData) { @@ -79,9 +77,7 @@ const Header = () => { 회원가입 - 마이페이지 - @@ -91,7 +87,6 @@ const Header = () => {
      - 대시보드 diff --git a/components/organisms/Modal.tsx b/components/organisms/Modal.tsx index 40cc254..f955964 100644 --- a/components/organisms/Modal.tsx +++ b/components/organisms/Modal.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useState } from "react"; import styled from "@emotion/styled"; import { Button, Checkbox, TextField, keyframes } from "@mui/material"; import { useRecoilState, useSetRecoilState } from "recoil"; -import { modalState } from "../atoms/modalState"; +import modalState from "../atoms/modalState"; import { useModal } from "../hooks/useModal"; import Logo from "@/components/atoms/Logo.svg"; import ModalCloseButton from "@/components/atoms/ModalCloseBtn.svg"; @@ -18,8 +18,8 @@ const LoginModal: React.FC = () => { const { closeModal } = useModal(); - const [email, setEmail] = useState(); - const [password, setPassword] = useState(); + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); const setLoginedUserState = useSetRecoilState(initialState); const handleLogin = async (email: string, password: string) => { diff --git a/pages/student/coupon/register/Inputs.style.ts b/components/styles/CInputs.style.ts similarity index 100% rename from pages/student/coupon/register/Inputs.style.ts rename to components/styles/CInputs.style.ts diff --git a/pages/student/popup/register/Inputs.style.ts b/components/styles/Inputs.style.ts similarity index 100% rename from pages/student/popup/register/Inputs.style.ts rename to components/styles/Inputs.style.ts diff --git a/pages/dashboard/SecondBox.styles.ts b/components/styles/SecondBox.styles.ts similarity index 100% rename from pages/dashboard/SecondBox.styles.ts rename to components/styles/SecondBox.styles.ts diff --git a/components/styles/dashboardDetail/style.ts b/components/styles/dashboardDetail/style.ts new file mode 100644 index 0000000..1f934ba --- /dev/null +++ b/components/styles/dashboardDetail/style.ts @@ -0,0 +1,114 @@ +import { FlexTemplate, GridTemplate } from "@/components/atoms/basics"; +import styled from "@emotion/styled"; + +export const Container = styled(FlexTemplate)` + flex-flow: column nowrap; + + padding-top: 1rem; + width: 80%; + margin: 0px auto; + + row-gap: 3rem; +`; + +export const UpperContainer = styled(FlexTemplate)` + flex-flow: column nowrap; + + row-gap: 10px; +`; + +export const LowerContainer = styled(GridTemplate)` + width: 100%; + min-height: 100vh; + + grid-template-columns: repeat(6, 1fr); + grid-template-rows: repeat(6, minmax(auto, 1fr)); + + row-gap: 15px; + column-gap: 15px; +`; +// ----- Layers ------ +export const FirstBox = styled(FlexTemplate)` + grid-column: 1/3; + grid-row: 1/2; + + height: 100%; + width: 100%; + padding: 10px; +`; +export const SecondBox = styled(FlexTemplate)` + grid-column: 3/5; + grid-row: 1/2; + padding: 10px; +`; +export const ThirdBox = styled(FlexTemplate)` + grid-column: 5/7; + grid-row: 1/2; + border: 1px solid var(--g0, #f4f4f4); + padding: 10px; +`; + +export const FourthBox = styled(FlexTemplate)` + grid-column: 1/4; + grid-row: 2/4; + border: 1px solid var(--g0, #f4f4f4); + padding: 10px; + + justify-content: center; + align-items: center; +`; +export const FifthBox = styled(FlexTemplate)` + grid-column: 4/7; + grid-row: 2/4; + border: 1px solid var(--g0, #f4f4f4); + padding: 10px; +`; + +export const SixthBox = styled(FlexTemplate)` + grid-column: 1/4; + grid-row: 4/7; + border: 1px solid var(--g0, #f4f4f4); + padding: 10px; +`; +export const SeventhBox = styled(FlexTemplate)` + grid-column: 4/7; + grid-row: 4/7; + border: 1px solid var(--g0, #f4f4f4); + padding: 10px; +`; + +// ----- Box Level ------ +export const IndexBtnBox = styled(FlexTemplate)` + column-gap: 10px; +`; + +// ------ element Level ------ +export const Title = styled.p` + color: var(--, #1c1c1e); + font-family: Pretendard Variable; + font-size: 28px; + font-style: normal; + font-weight: 600; + + margin-bottom: 20px; +`; + +export const SubTitle = styled.p` + color: #676767; + font-family: Pretendard Variable; + font-size: 15px; + font-style: normal; + font-weight: 500; + + margin-bottom: 15px; +`; + +export const IndexButton = styled(FlexTemplate)` + border: 1px solid var(--g1, #c6c6c6); + width: 113px; + height: 37px; + padding: 5.827px 20.977px; + + justify-content: center; + align-items: center; +`; diff --git a/package-lock.json b/package-lock.json index fbf838c..d59ed64 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "@mui/x-date-pickers": "^6.18.1", "@svgr/webpack": "^8.1.0", "axios": "^1.5.1", + "date-fns": "^2.30.0", "dayjs": "^1.11.10", "next": "latest", "react": "latest", @@ -4062,6 +4063,21 @@ "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", "dev": true }, + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, "node_modules/dayjs": { "version": "1.11.10", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", diff --git a/package.json b/package.json index d64d59a..e4600b3 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "@mui/x-date-pickers": "^6.18.1", "@svgr/webpack": "^8.1.0", "axios": "^1.5.1", + "date-fns": "^2.30.0", "dayjs": "^1.11.10", "next": "latest", "react": "latest", diff --git a/pages/api/ContractAPI.ts b/pages/api/ContractAPI.ts index e1c2e7d..0f27c7c 100644 --- a/pages/api/ContractAPI.ts +++ b/pages/api/ContractAPI.ts @@ -9,7 +9,7 @@ export const getContractBase = async ({ pageNumber = 0, }: FilterProps) => { try { - const response = await axiosInstance.get( + const response = await axiosInstance().get( `/contract?isPicked=${isPicked}&name=${name}&category=${category}&pageSize=40&pageNumber=${pageNumber}` ); return response.data; @@ -23,7 +23,7 @@ export const getContractBase = async ({ export const getContractInfo = async (id: number) => { try { - const response = await axiosInstance.get(`/contract/details/${id}`); + const response = await axiosInstance().get(`/contract/details/${id}`); return response.data; } catch (error) { if (axios.isAxiosError(error)) { diff --git a/pages/api/login.ts b/pages/api/login.ts index 722dfb7..c4f136a 100644 --- a/pages/api/login.ts +++ b/pages/api/login.ts @@ -22,8 +22,10 @@ interface SignUpProps { // 로그인 export const login = async ({ email, password }: LoginProps) => { try { - const loginEndpoint = process.env.NEXT_PUBLIC_LOGIN_ENDPOINT; - const response = await apiBase.post(loginEndpoint, { email, password }); + const response = await apiBase.post( + `${process.env.NEXT_PUBLIC_LOGIN_ENDPOINT}`, + { email, password } + ); const accessToken = response.headers.authorization; console.log("로그인 성공:", accessToken); @@ -44,14 +46,16 @@ export const SignUp = async ({ proofImageUrl, }: SignUpProps) => { try { - const signUpEndpoint = process.env.NEXT_PUBLIC_SIGNUP_ENDPOINT; - const response = await apiBase.post(signUpEndpoint, { - email, - password, - type, - typeName, - proofImageUrl, - }); + const response = await apiBase.post( + `${process.env.NEXT_PUBLIC_SIGNUP_ENDPOINT}`, + { + email, + password, + type, + typeName, + proofImageUrl, + } + ); return response.data; } catch (error) { @@ -63,15 +67,18 @@ export const SignUp = async ({ // 이미지 업로드 (회원가입 전에) export const CreateImage = async (file: File) => { try { - const createImageEndpoint = process.env.NEXT_PUBLIC_CREATE_IMAGE_ENDPOINT; const formData = new FormData(); formData.append("file", file); - const response = await apiBase.post(createImageEndpoint, formData, { - headers: { - "Content-Type": "multipart/form-data", - }, - }); + const response = await apiBase.post( + `${process.env.NEXT_PUBLIC_CREATE_IMAGE_ENDPOINT}`, + formData, + { + headers: { + "Content-Type": "multipart/form-data", + }, + } + ); return response.data; } catch (error) { @@ -92,7 +99,9 @@ export const Logout = async () => { } try { const response = await apiBase.post( - process.env.NEXT_PUBLIC_LOGOUT_ENDPOINT, + + `${process.env.NEXT_PUBLIC_LOGOUT_ENDPOINT}`, + { headers: { Authorization: `Bearer ${token}`, diff --git a/pages/apply/form/index.tsx b/pages/apply/form/index.tsx deleted file mode 100644 index e69de29..0000000 diff --git a/pages/apply/index.tsx b/pages/apply/index.tsx deleted file mode 100644 index 7f5788d..0000000 --- a/pages/apply/index.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import * as styles from "@/components/styles/apply-list/style"; -import Head from "next/head"; -import MySvg from "@/components/atoms/ApplyListIcon.svg"; - -export default function ApplyList() { - return ( - <> - - 제휴제안서 리스트 - - - - 제안서 작성 - - 컨텍 전 제안서 - 사장님이 검토 중인 제안서 - - - {StoreInfo.map((element, index) => { - return ( - -
      - -

      {element.category}

      -
      -
      -

      {element.title}

      -

      {element.description}

      -

      {element.address}

      -

      {element.distance}

      -
      -
      - ); - })} -
      - 추가하기 -
      - - ); -} - -const StoreInfo = [ - { - title: "냠냠돈까스", - description: "아메리칸 브런치, 잉글리쉬 브런치, 인도커리 브런치 등", - address: "서울특별시 성동구 청계천로 474", - distance: 176, - category: "음식점", - }, - { - title: "냠냠돈까스", - description: "아메리칸 브런치, 잉글리쉬 브런치, 인도커리 브런치 등", - address: "서울특별시 성동구 청계천로 474", - distance: 176, - category: "음식점", - }, - { - title: "냠냠돈까스", - description: "아메리칸 브런치, 잉글리쉬 브런치, 인도커리 브런치 등", - address: "서울특별시 성동구 청계천로 474", - distance: 176, - category: "음식점", - }, - { - title: "냠냠돈까스", - description: "아메리칸 브런치, 잉글리쉬 브런치, 인도커리 브런치 등", - address: "서울특별시 성동구 청계천로 474", - distance: 176, - category: "음식점", - }, - { - title: "냠냠돈까스", - description: "아메리칸 브런치, 잉글리쉬 브런치, 인도커리 브런치 등", - address: "서울특별시 성동구 청계천로 474", - distance: 176, - category: "음식점", - }, - { - title: "냠냠돈까스", - description: "아메리칸 브런치, 잉글리쉬 브런치, 인도커리 브런치 등", - address: "서울특별시 성동구 청계천로 474", - distance: 176, - category: "음식점", - }, -]; diff --git a/pages/dashboard/BackgroundedChart.tsx b/pages/dashboard/BackgroundedChart.tsx new file mode 100644 index 0000000..a61e272 --- /dev/null +++ b/pages/dashboard/BackgroundedChart.tsx @@ -0,0 +1,98 @@ +import { FlexTemplate } from "@/components/atoms/basics"; +import styled from "@emotion/styled"; +import { Bar, BarChart, ResponsiveContainer, XAxis } from "recharts"; +interface ChartProps { + title: string; + color?: string; + data: Array; +} + +interface Data { + name: string; + uv: number; + pv: number; + amt: number; +} + +const BackgroundedChart: React.FC = ({ + title, + color = "#8884d8", + data, +}) => { + return ( + + + + {title} + + + + + + + + + + + + ); +}; + +export default BackgroundedChart; + +const Container = styled(FlexTemplate)` + height: 100%; + width: 100%; + position: relative; +`; + +const LayerBox = styled(FlexTemplate)` + position: absolute; + z-index: 10; + + width: 565px; + height: 347px; + + flex-flow: column nowrap; + align-items: center; + justify-content: center; + width: 100%; +`; + +const LayerTitleBox = styled(FlexTemplate)` + width: 100%; + + justify-content: center; +`; + +const ChartTitle = styled.p` + width: 50%; + text-align: center; + padding-bottom: 1rem; + padding-top: 1rem; + font-weight: 500; + font-size: 1.5rem; + border-bottom: 2px solid black; +`; +const ChartBox = styled(FlexTemplate)` + width: 100%; + height: 80%; + + padding-top: 10px; +`; + +const Title = styled.p` + color: #676767; + font-family: Pretendard Variable; + font-size: 1rem; + font-style: normal; + font-weight: 500; +`; + +const Contents = styled.p` + color: #000; + font-family: Pretendard Variable; + font-size: 1.7rem; + font-style: normal; + font-weight: bolder; +`; diff --git a/pages/dashboard/BarChart.tsx b/pages/dashboard/BarChart.tsx index d41456e..143a302 100644 --- a/pages/dashboard/BarChart.tsx +++ b/pages/dashboard/BarChart.tsx @@ -1,11 +1,11 @@ import React from "react"; -import * as ChartStyles from "./SecondBox.styles"; +import * as ChartStyles from "../../components/styles/SecondBox.styles"; import { Bar, ResponsiveContainer, BarChart, XAxis } from "recharts"; interface DataProps { title: string; data: Array; - color: string; + color?: string; } interface ChartElement { diff --git a/pages/dashboard/ComposedChart.tsx b/pages/dashboard/ComposedChart.tsx new file mode 100644 index 0000000..cbdb92c --- /dev/null +++ b/pages/dashboard/ComposedChart.tsx @@ -0,0 +1,125 @@ +import { FlexTemplate } from "@/components/atoms/basics"; +import styled from "@emotion/styled"; +import { + Area, + AreaChart, + CartesianGrid, + Legend, + Line, + LineChart, + ResponsiveContainer, + Tooltip, +} from "recharts"; + +interface ChartProps { + title: string; +} + +const ComposedChart: React.FC = ({ title }) => { + return ( + + + {title} + + + + + + + + + + + + + + + ); +}; + +export default ComposedChart; + +const Container = styled(FlexTemplate)` + width: 100%; + height: 100%; + + flex-flow: column nowrap; +`; +const Title = styled.p` + width: 100%; + color: #676767; + font-family: Pretendard Variable; + font-size: 1.5rem; + font-style: normal; + font-weight: 500; +`; + +const UpperBox = styled(FlexTemplate)` + height: 10%; +`; + +const ContentBox = styled(FlexTemplate)` + height: 90%; + justify-content: center; + align-items: center; +`; + +const data = [ + { + name: "Page A", + uv: 800, + pv: 2400, + amt: 600, + }, + { + name: "Page B", + uv: 1000, + pv: 1398, + amt: 990, + }, + { + name: "Page C", + uv: 1230, + pv: 9800, + amt: 1100, + }, + { + name: "Page D", + uv: 2500, + pv: 3908, + amt: 1250, + }, + { + name: "Page E", + uv: 1600, + pv: 4800, + amt: 1300, + }, + { + name: "Page F", + uv: 1700, + pv: 3800, + amt: 1600, + }, + { + name: "Page G", + uv: 3490, + pv: 4300, + amt: 2100, + }, +]; diff --git a/pages/dashboard/FifthBox.tsx b/pages/dashboard/FifthBox.tsx deleted file mode 100644 index e69de29..0000000 diff --git a/pages/dashboard/FirstChart.tsx b/pages/dashboard/FirstChart.tsx new file mode 100644 index 0000000..20f62aa --- /dev/null +++ b/pages/dashboard/FirstChart.tsx @@ -0,0 +1,49 @@ +import { FlexTemplate } from "@/components/atoms/basics"; +import styled from "@emotion/styled"; + +interface ChartProps { + title: string; + content: string; +} + +const FirstChart: React.FC = ({ title, content }) => { + return ( + + {title} + {content} + + ); +}; + +export default FirstChart; + +const Container = styled(FlexTemplate)` + width: 95%; + height: 90%; + padding: 3%; + + margin: 0px auto; + border-bottom: 2px solid black; + + flex-flow: column nowrap; + justify-content: flex-start; + align-items: flex-start; + + row-gap: 25px; +`; + +const Title = styled.p` + color: #676767; + font-family: Pretendard Variable; + font-size: 1.5rem; + font-style: normal; + font-weight: 500; +`; + +const Contents = styled.p` + color: #000; + font-family: Pretendard Variable; + font-size: 1.7rem; + font-style: normal; + font-weight: bolder; +`; diff --git a/pages/dashboard/FourthBox.tsx b/pages/dashboard/FourthBox.tsx deleted file mode 100644 index e69de29..0000000 diff --git a/pages/dashboard/ListChart.tsx b/pages/dashboard/ListChart.tsx index c6fefd0..df2cfb1 100644 --- a/pages/dashboard/ListChart.tsx +++ b/pages/dashboard/ListChart.tsx @@ -1,6 +1,6 @@ import React from "react"; import styled from "@emotion/styled"; -import * as containerStyle from "./SecondBox.styles"; +import * as containerStyle from "../../components/styles/SecondBox.styles"; import { css } from "@emotion/css"; import { NumberBall } from "@/components/atoms/basics"; @@ -37,7 +37,7 @@ const ListChart: React.FC = ({ title, contents }) => { `} key={index} > - {index} + {index + 1} {element} ); diff --git a/pages/dashboard/OneStackChart.tsx b/pages/dashboard/OneStackChart.tsx new file mode 100644 index 0000000..c99691e --- /dev/null +++ b/pages/dashboard/OneStackChart.tsx @@ -0,0 +1,110 @@ +import { FlexTemplate } from "@/components/atoms/basics"; +import styled from "@emotion/styled"; +import { + Area, + AreaChart, + CartesianGrid, + Line, + LineChart, + ResponsiveContainer, + Tooltip, +} from "recharts"; + +interface ChartProps { + title: string; +} + +const OneStackChart: React.FC = ({ title }) => { + return ( + + + {title} + + + + + + + + + + ); +}; + +export default OneStackChart; + +const Container = styled(FlexTemplate)` + width: 100%; + height: 100%; + + flex-flow: column nowrap; +`; +const Title = styled.p` + width: 100%; + color: #676767; + font-family: Pretendard Variable; + font-size: 1.5rem; + font-style: normal; + font-weight: 500; +`; + +const UpperBox = styled(FlexTemplate)` + height: 10%; +`; + +const ContentBox = styled(FlexTemplate)` + height: 100%; + width: 100%; + justify-content: center; + align-items: center; +`; + +const data = [ + { + name: "Page A", + uv: 800, + pv: 2400, + amt: 2400, + }, + { + name: "Page B", + uv: 1400, + pv: 1398, + amt: 2210, + }, + { + name: "Page C", + uv: 700, + pv: 9800, + amt: 2290, + }, + { + name: "Page D", + uv: 1100, + pv: 3908, + amt: 2000, + }, + { + name: "Page E", + uv: 1890, + pv: 4800, + amt: 2181, + }, + { + name: "Page F", + uv: 3000, + pv: 3800, + amt: 2500, + }, + { + name: "Page G", + uv: 5000, + pv: 4300, + amt: 2100, + }, +]; diff --git a/pages/dashboard/PieCharts.tsx b/pages/dashboard/PieCharts.tsx index d12d5bf..5545b27 100644 --- a/pages/dashboard/PieCharts.tsx +++ b/pages/dashboard/PieCharts.tsx @@ -1,5 +1,5 @@ import { ReactNode, useState } from "react"; -import * as styles from "./SecondBox.styles"; +import * as styles from "../../components/styles/SecondBox.styles"; import { Pie, PieChart, ResponsiveContainer, Sector, Tooltip } from "recharts"; interface SecondBoxProps { children?: ReactNode; @@ -15,7 +15,7 @@ const data01 = [ const SecondBox: React.FC = () => { const [activeIndex, setActiveIndex] = useState(0); - const onPieEnter = (_, index) => { + const onPieEnter = (_: any, index: any) => { setActiveIndex(index); }; @@ -46,7 +46,7 @@ const SecondBox: React.FC = () => { ); }; -const renderActiveShape = (props) => { +const renderActiveShape = (props: any) => { const RADIAN = Math.PI / 180; const { cx, @@ -93,13 +93,14 @@ const renderActiveShape = (props) => { innerRadius={outerRadius + 6} outerRadius={outerRadius + 10} fill={fill} + color="#0E6EFF" /> - + = 0 ? 1 : -1) * 12} y={ey} diff --git a/pages/dashboard/StackCharts.tsx b/pages/dashboard/StackCharts.tsx index 3f46019..893e9de 100644 --- a/pages/dashboard/StackCharts.tsx +++ b/pages/dashboard/StackCharts.tsx @@ -10,7 +10,7 @@ interface ThirdBoxProps { children?: ReactNode; } -import * as styles from "./SecondBox.styles"; +import * as styles from "../../components/styles/SecondBox.styles"; const ThirdBox: React.FC = () => { return ( @@ -39,7 +39,7 @@ const ThirdBox: React.FC = () => { type="monotone" dataKey="uv" stroke="#8884d8" - fill="#8884d8" + fill="#0E6EFF" /> diff --git a/pages/dashboard/[store].tsx b/pages/dashboard/[store].tsx new file mode 100644 index 0000000..7656f46 --- /dev/null +++ b/pages/dashboard/[store].tsx @@ -0,0 +1,166 @@ +import { useRouter } from "next/router"; +import { useEffect, useState } from "react"; +import * as styles from "@/components/styles/dashboardDetail/style"; +import useDateRange from "@/components/hooks/useDateRange"; +import FirstChart from "./FirstChart"; +import ComposedChart from "./ComposedChart"; +import OneStackChart from "./OneStackChart"; +import BackgroundedChart from "./BackgroundedChart"; +import FirstLayerChart from "./FirstLayerChart"; + +interface dateProps { + startDate: string; + endDate: string; +} + +const StorePage = () => { + const router = useRouter(); + const { store } = router.query; + + const [date, setDate] = useState(); + const { dateRange, calculateDateRange } = useDateRange(); + + useEffect(() => { + calculateDateRange(1, "month"); + }, []); + + return ( + + + {store}의 대시보드 + + {dateRange?.startDate} ~ {dateRange?.endDate}기준입니다 + + + 최근 7일 + 최근 14일 + 이번 달 + 지난 달 + 올해 + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default StorePage; + +const data = [ + { + name: "월요일", + uv: 200, + pv: 2400, + amt: 2400, + }, + { + name: "화요일", + uv: 1000, + pv: 1398, + amt: 2210, + }, + { + name: "수요일", + uv: 1400, + pv: 9800, + amt: 2290, + }, + { + name: "목요일", + uv: 1200, + pv: 3908, + amt: 2000, + }, + { + name: "금요일", + uv: 800, + pv: 4800, + amt: 2181, + }, + { + name: "토요일", + uv: 1500, + pv: 3800, + amt: 2500, + }, + { + name: "일요일", + uv: 1700, + pv: 4300, + amt: 2100, + }, +]; + +const data2 = [ + { + name: "경영", + uv: 4000, + pv: 2400, + amt: 2400, + }, + { + name: "경제", + uv: 3000, + pv: 1398, + amt: 2210, + }, + { + name: "컴공", + uv: 2000, + pv: 9800, + amt: 2290, + }, + { + name: "신소재", + uv: 2780, + pv: 3908, + amt: 2000, + }, + { + name: "법학", + uv: 1890, + pv: 4800, + amt: 2181, + }, + { + name: "영어영문", + uv: 2390, + pv: 3800, + amt: 2500, + }, + { + name: "철학", + uv: 3490, + pv: 4300, + amt: 2100, + }, +]; diff --git a/pages/dashboard/index.tsx b/pages/dashboard/index.tsx index 9edeee0..035a7c8 100644 --- a/pages/dashboard/index.tsx +++ b/pages/dashboard/index.tsx @@ -82,7 +82,7 @@ const DashBoardPage: React.FC = () => { - + @@ -107,10 +107,18 @@ const DashBoardPage: React.FC = () => { - + - + diff --git a/pages/student/coupon/register/Inputs.tsx b/pages/student/coupon/register/Inputs.tsx index 6cf7736..5ba217d 100644 --- a/pages/student/coupon/register/Inputs.tsx +++ b/pages/student/coupon/register/Inputs.tsx @@ -1,6 +1,7 @@ import React, { useEffect, useMemo, useState } from "react"; -import * as styles from "./Inputs.style"; +import * as styles from "../../../../components/styles/CInputs.style"; + import { css } from "@emotion/css"; import { Checkbox, @@ -133,7 +134,9 @@ const Inputs: React.FC = () => { placeholder={placeHolders[3]} name="condition" onChange={(e) => { - let result = []; + + let result: any = []; + result.push(e.target.value); setFormData((prev) => ({ ...prev, conditions: result })); diff --git a/pages/student/popup/index.tsx b/pages/student/popup/index.tsx index 6b5b5e2..78eed23 100644 --- a/pages/student/popup/index.tsx +++ b/pages/student/popup/index.tsx @@ -40,7 +40,9 @@ const PopupAdminPage: React.FC = () => { {element.content} - {element.endDate}/{element.reservation} + + {element.content}/{element.reservation} + diff --git a/pages/student/popup/register/Inputs.tsx b/pages/student/popup/register/Inputs.tsx index 7953666..0b573b1 100644 --- a/pages/student/popup/register/Inputs.tsx +++ b/pages/student/popup/register/Inputs.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useMemo, useState } from "react"; -import * as styles from "./Inputs.style"; +import * as styles from "@/components/styles/Inputs.style"; import { css } from "@emotion/css"; import { FilledInput, IconButton, InputAdornment } from "@mui/material"; import SearchTwoToneIcon from "@mui/icons-material/SearchTwoTone"; @@ -169,7 +169,7 @@ const Inputs: React.FC = () => { { + onChange={(newValue: any) => { let date = `${newValue.$y}-${newValue.$M}-${newValue.$D} ${newValue.$H}:${newValue.$m}`; console.log(date); setFormData((prev) => ({ diff --git a/pages/user/auth/index.tsx b/pages/user/auth/index.tsx index d194527..68c10f2 100644 --- a/pages/user/auth/index.tsx +++ b/pages/user/auth/index.tsx @@ -1,8 +1,6 @@ import * as phase from "@/components/styles/user/first/style"; import * as styles from "@/components/styles/user/third/style"; import { CreateImage, SignUp } from "@/pages/api/login"; -import { Button, Checkbox, TextField } from "@mui/material"; -import axios from "axios"; import Head from "next/head"; import { useRouter } from "next/router"; import React, { useState } from "react"; @@ -17,13 +15,12 @@ const AuthPage: React.FC = () => { // states const [email, setEmail] = useState(""); - const [phone, setPhone] = useState(""); const [password, setPassword] = useState(""); const [passwordConfirm, setPasswordConfirm] = useState(""); const [proofImage, setProofImage] = useState(null); // input file changes - const handleFileInput = (e) => { + const handleFileInput = (e: any) => { const file = e.target.files[0]; console.log(file); setProofImage(file); @@ -31,7 +28,11 @@ const AuthPage: React.FC = () => { const registerImage = async () => { try { - const response = await CreateImage(proofImage); + let response: any = ""; + if (proofImage) { + response = await CreateImage(proofImage); + } + setProofImage(response); } catch (err) { console.error(err); diff --git a/pages/user/form/index.tsx b/pages/user/form/index.tsx index 356a8d4..983c437 100644 --- a/pages/user/form/index.tsx +++ b/pages/user/form/index.tsx @@ -54,7 +54,7 @@ const FormPage: React.FC = () => { const checkBoxInputHandler = (e: React.ChangeEvent) => { const { name, checked } = e.target; - setFormData((prev) => ({ + setFormData((prev: any) => ({ ...prev, [name]: checked, })); @@ -63,7 +63,7 @@ const FormPage: React.FC = () => { const InputHandler = (e: React.ChangeEvent) => { const { value, name } = e.target; - setFormData((prev) => ({ + setFormData((prev: any) => ({ ...prev, [name]: value, })); diff --git a/pages/user/index.tsx b/pages/user/index.tsx index 86b8cb3..eefbfad 100644 --- a/pages/user/index.tsx +++ b/pages/user/index.tsx @@ -10,11 +10,11 @@ interface UserProps { } interface CheckBoxValid { - first?: boolean; - second?: boolean; - third?: boolean; - fourth?: boolean; - fifth?: boolean; + first: boolean; + second: boolean; + third: boolean; + fourth: boolean; + fifth: boolean; } const UserPage: React.FC = () => { @@ -82,7 +82,7 @@ const UserPage: React.FC = () => { ) => { + onChange={(e: React.ChangeEvent) => { const { checked } = e.target; checked ? setChecked({ @@ -93,6 +93,7 @@ const UserPage: React.FC = () => { fifth: true, }) : setChecked({ + first: true, second: true, third: true, fourth: true, @@ -106,7 +107,7 @@ const UserPage: React.FC = () => { 회원 서비스 이용약관 (필수) @@ -114,7 +115,7 @@ const UserPage: React.FC = () => { 개인정보 수집 및 이용동의 (필수) @@ -122,7 +123,7 @@ const UserPage: React.FC = () => { 개인정보의 제3자 제공 동의 (선택) @@ -130,7 +131,7 @@ const UserPage: React.FC = () => { 마케팅 수신 동의 (선택)