From 1c61d3d46dc943d3df351b4fa48db6cbab007fa9 Mon Sep 17 00:00:00 2001 From: SuJin Date: Thu, 23 Nov 2023 01:24:58 +0900 Subject: [PATCH] =?UTF-8?q?[#28]=20feat:=20=EC=A0=9C=ED=9C=B4=EA=B0=80?= =?UTF-8?q?=EA=B2=8C=20API=20=EC=97=B0=EA=B2=B0=20(#37)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: icon 에러 수정 * feat: 제휴가게리스트 API 연결 * feat: 라우터 연결 * fix: img 오류 수정 * feat: 제휴가게 상세 API 연결 * feat: modal api 연결 및 디자인 수정 * style: checkbox 적용 --- @types/Contract.d.ts | 28 +++ assets/svg/57/Beauty.svg | 15 ++ assets/svg/57/Cafe.svg | 5 + assets/svg/57/Culture.svg | 7 + assets/svg/57/Etc.svg | 7 + assets/svg/57/Food.svg | 5 + assets/svg/Mid/MBeauty.svg | 15 ++ assets/svg/Mid/MCafe.svg | 5 + assets/svg/Mid/MCulture.svg | 7 + assets/svg/Mid/MEtc.svg | 7 + assets/svg/Mid/MFood.svg | 5 + assets/svg/Small/SBeauty.svg | 15 ++ assets/svg/Small/SCafe.svg | 5 + assets/svg/Small/SCulture.svg | 7 + assets/svg/Small/SEtc.svg | 7 + assets/svg/Small/SFood.svg | 5 + components/Marker/Icon/IconMarker.tsx | 2 +- components/Marker/Name/NameMarker.tsx | 1 - components/organisms/Modal/FinishModal.tsx | 7 +- components/organisms/Modal/StampModal.tsx | 23 ++- pages/api/ContractAPI.ts | 34 ++++ pages/contact/index.tsx | 192 +++++++++++++------- pages/contact/store/{index.tsx => [id].tsx} | 131 ++++++++----- utils/TypeImg.tsx | 78 ++++++++ 24 files changed, 488 insertions(+), 125 deletions(-) create mode 100644 @types/Contract.d.ts create mode 100644 assets/svg/57/Beauty.svg create mode 100644 assets/svg/57/Cafe.svg create mode 100644 assets/svg/57/Culture.svg create mode 100644 assets/svg/57/Etc.svg create mode 100644 assets/svg/57/Food.svg create mode 100644 assets/svg/Mid/MBeauty.svg create mode 100644 assets/svg/Mid/MCafe.svg create mode 100644 assets/svg/Mid/MCulture.svg create mode 100644 assets/svg/Mid/MEtc.svg create mode 100644 assets/svg/Mid/MFood.svg create mode 100644 assets/svg/Small/SBeauty.svg create mode 100644 assets/svg/Small/SCafe.svg create mode 100644 assets/svg/Small/SCulture.svg create mode 100644 assets/svg/Small/SEtc.svg create mode 100644 assets/svg/Small/SFood.svg create mode 100644 pages/api/ContractAPI.ts rename pages/contact/store/{index.tsx => [id].tsx} (58%) diff --git a/@types/Contract.d.ts b/@types/Contract.d.ts new file mode 100644 index 0000000..aba0f54 --- /dev/null +++ b/@types/Contract.d.ts @@ -0,0 +1,28 @@ +export type ContractListInfo = { + category: "FOOD" | "CAFE" | "BEAUTY" | "CULTURE" | "ETC" | "NONE"; + storeId: number; + storeName: string; + benefits: Benefit[]; +}; + +type Benefit = { + amount: number; + benfitId: number; + content: string; + type: "FIX" | "RATE" | "MENU"; +}; + +export type ContractInfo = { + benefits: Benefit[]; + category: "FOOD" | "CAFE" | "BEAUTY" | "CULTURE" | "ETC" | "NONE"; + endDate: string; + latitude: number; + longitude: number; + manager: string; + mapUrl: string; + phoneNumber: string; + startDate: string; + storeId: number; + storeName: string; + visitInfo: object; +}; diff --git a/assets/svg/57/Beauty.svg b/assets/svg/57/Beauty.svg new file mode 100644 index 0000000..cd1ad33 --- /dev/null +++ b/assets/svg/57/Beauty.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/assets/svg/57/Cafe.svg b/assets/svg/57/Cafe.svg new file mode 100644 index 0000000..5c3a44e --- /dev/null +++ b/assets/svg/57/Cafe.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/svg/57/Culture.svg b/assets/svg/57/Culture.svg new file mode 100644 index 0000000..fb01690 --- /dev/null +++ b/assets/svg/57/Culture.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/svg/57/Etc.svg b/assets/svg/57/Etc.svg new file mode 100644 index 0000000..7a175d4 --- /dev/null +++ b/assets/svg/57/Etc.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/svg/57/Food.svg b/assets/svg/57/Food.svg new file mode 100644 index 0000000..119d7ab --- /dev/null +++ b/assets/svg/57/Food.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/svg/Mid/MBeauty.svg b/assets/svg/Mid/MBeauty.svg new file mode 100644 index 0000000..1b322c7 --- /dev/null +++ b/assets/svg/Mid/MBeauty.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/assets/svg/Mid/MCafe.svg b/assets/svg/Mid/MCafe.svg new file mode 100644 index 0000000..07c9060 --- /dev/null +++ b/assets/svg/Mid/MCafe.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/svg/Mid/MCulture.svg b/assets/svg/Mid/MCulture.svg new file mode 100644 index 0000000..73130fd --- /dev/null +++ b/assets/svg/Mid/MCulture.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/svg/Mid/MEtc.svg b/assets/svg/Mid/MEtc.svg new file mode 100644 index 0000000..b155213 --- /dev/null +++ b/assets/svg/Mid/MEtc.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/svg/Mid/MFood.svg b/assets/svg/Mid/MFood.svg new file mode 100644 index 0000000..a7686c9 --- /dev/null +++ b/assets/svg/Mid/MFood.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/svg/Small/SBeauty.svg b/assets/svg/Small/SBeauty.svg new file mode 100644 index 0000000..8d54cd8 --- /dev/null +++ b/assets/svg/Small/SBeauty.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/assets/svg/Small/SCafe.svg b/assets/svg/Small/SCafe.svg new file mode 100644 index 0000000..a67313a --- /dev/null +++ b/assets/svg/Small/SCafe.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/svg/Small/SCulture.svg b/assets/svg/Small/SCulture.svg new file mode 100644 index 0000000..1865e01 --- /dev/null +++ b/assets/svg/Small/SCulture.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/svg/Small/SEtc.svg b/assets/svg/Small/SEtc.svg new file mode 100644 index 0000000..47fc56e --- /dev/null +++ b/assets/svg/Small/SEtc.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/svg/Small/SFood.svg b/assets/svg/Small/SFood.svg new file mode 100644 index 0000000..76a9d27 --- /dev/null +++ b/assets/svg/Small/SFood.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/components/Marker/Icon/IconMarker.tsx b/components/Marker/Icon/IconMarker.tsx index 2417696..979ba9f 100644 --- a/components/Marker/Icon/IconMarker.tsx +++ b/components/Marker/Icon/IconMarker.tsx @@ -17,7 +17,7 @@ export const typeIcon: TypeIcon = SizeTypeImg25(); const eng = ["FOOD", "CAFE", "CULTURE", "BEAUTY", "ETC"]; -const typeEngtoKor = (name: string) => { +export const typeEngtoKor = (name: string) => { const kor = ["음식점", "카페", "문화", "미용", "기타"]; return kor[eng.indexOf(name)]; }; diff --git a/components/Marker/Name/NameMarker.tsx b/components/Marker/Name/NameMarker.tsx index 989ba4f..4070320 100644 --- a/components/Marker/Name/NameMarker.tsx +++ b/components/Marker/Name/NameMarker.tsx @@ -19,7 +19,6 @@ const NameMarker = ({ lat, lng, type = "CULTURE", - icon, title, markerType, }: NameMarkerProps) => { diff --git a/components/organisms/Modal/FinishModal.tsx b/components/organisms/Modal/FinishModal.tsx index 853a46a..3ec47f2 100644 --- a/components/organisms/Modal/FinishModal.tsx +++ b/components/organisms/Modal/FinishModal.tsx @@ -3,8 +3,7 @@ import Modal from "./Modal"; import styled from "@emotion/styled"; import Button from "../Button"; import CloseIcon from "@/assets/svg/Close.svg"; -import Image from "next/image"; -import { SizeTypeImg } from "@/utils/TypeImg"; +import { SizeTypeImg57 } from "@/utils/TypeImg"; interface Props { title: string; @@ -17,13 +16,13 @@ const FinishModal = ({ setIsFinishModal, title, type }: Props) => { setIsFinishModal(false); }; - const typeStyles = SizeTypeImg(57); + const typeStyles = SizeTypeImg57(); return ( - close icon + {typeStyles[type].value} diff --git a/components/organisms/Modal/StampModal.tsx b/components/organisms/Modal/StampModal.tsx index db39f3e..9ddc911 100644 --- a/components/organisms/Modal/StampModal.tsx +++ b/components/organisms/Modal/StampModal.tsx @@ -5,7 +5,9 @@ import Image from "next/image"; import CloseIcon from "@/assets/svg/Close.svg"; import Button from "../Button"; import { COLORS } from "@/styles/colors"; - +import { Checkbox } from "@mui/material"; +import CheckCircleIcon from "@mui/icons-material/CheckCircle"; +import CircleIcon from "@mui/icons-material/Circle"; interface Props { setIsStampModal: Function; } @@ -39,7 +41,7 @@ const StampModal = ({ setIsStampModal }: Props) => { - close icon + 2배 스탬프 적용 @@ -66,12 +68,22 @@ const StampModal = ({ setIsStampModal }: Props) => { 2. 조건 유무 - {/** TODO: svg 적용하기 */} + + } + checkedIcon={} + /> + n명 달성 시 종료 - {/** TODO: svg 적용하기 */} + + } + checkedIcon={} + /> + 제한 인원 X @@ -150,12 +162,13 @@ const ConditionBox = styled.div` const CheckIconBox = styled.div``; const CheckTextBox = styled.div` - margin-left: 8px; color: #000; font-size: 16px; font-weight: 400; line-height: 19.264px; /* 120.399% */ letter-spacing: -1.12px; + display: flex; + align-items: center; `; const PersonBox = styled.div` diff --git a/pages/api/ContractAPI.ts b/pages/api/ContractAPI.ts new file mode 100644 index 0000000..e1c2e7d --- /dev/null +++ b/pages/api/ContractAPI.ts @@ -0,0 +1,34 @@ +import { axiosInstance } from "@/pages/api/axiosInstance"; +import axios from "axios"; +import { FilterProps } from "./StoreAPI"; + +export const getContractBase = async ({ + isPicked = false, + name = "", + category = "NONE", + pageNumber = 0, +}: FilterProps) => { + try { + const response = await axiosInstance.get( + `/contract?isPicked=${isPicked}&name=${name}&category=${category}&pageSize=40&pageNumber=${pageNumber}` + ); + return response.data; + } catch (error) { + if (axios.isAxiosError(error)) { + console.log(error.response?.data); + } + return null; + } +}; + +export const getContractInfo = async (id: number) => { + try { + const response = await axiosInstance.get(`/contract/details/${id}`); + return response.data; + } catch (error) { + if (axios.isAxiosError(error)) { + console.log(error.response?.data); + } + return null; + } +}; diff --git a/pages/contact/index.tsx b/pages/contact/index.tsx index 8babab0..9e9b59a 100644 --- a/pages/contact/index.tsx +++ b/pages/contact/index.tsx @@ -2,8 +2,13 @@ import SearchInput from "@/components/SearchInput"; import Filter from "@/components/organisms/Filter"; import * as styles from "@/components/styles/Contact.styles"; import SearchIcon from "@/assets/svg/Search.svg"; +import { + SizeTypeImg25, + SizeTypeImg49, + SizeTypeImgSmall, +} from "@/utils/TypeImg"; import Image from "next/image"; -import { ReactNode, useState } from "react"; +import { ReactNode, useEffect, useState } from "react"; import Food from "@/assets/svg/Food.svg"; import Cafe from "@/assets/svg/Cafe.svg"; import Culture from "@/assets/svg/Culture.svg"; @@ -12,48 +17,42 @@ import Beauty from "@/assets/svg/Beauty.svg"; import DashBoard from "@/assets/svg/SmallDashBoardIcon.svg"; import Modal from "@/components/organisms/Modal/Modal"; import CloseIcon from "@/assets/svg/Close.svg"; +import { getContractBase } from "../api/ContractAPI"; +import { ContractListInfo } from "@/@types/Contract"; +import { typeIcon } from "@/components/Marker/Icon/IconMarker"; +import Link from "next/link"; +import { useRouter } from "next/router"; +type TypeIcon = { + [key: string]: { + value: JSX.Element; + }; +}; export default function Contact() { - const typeStyles: { [key: string]: { value: ReactNode } } = { - 음식점: { - value: food marker, - }, - 카페: { - value: cafe marker, - }, - 미용: { - value: Beauty marker, - }, - 문화: { - value: ( - Culture marker - ), - }, - 기타: { - value: Etc marker, - }, - }; + const [data, setData] = useState(); + const typeIcon25 = SizeTypeImgSmall(); + const typeIcon49 = SizeTypeImg49(); + + const eng = ["FOOD", "CAFE", "CULTURE", "BEAUTY", "ETC"]; - const typeStyles49: { [key: string]: { value: ReactNode } } = { - 음식점: { - value: food marker, - }, - 카페: { - value: cafe marker, - }, - 미용: { - value: Beauty marker, - }, - 문화: { - value: ( - Culture marker - ), - }, - 기타: { - value: Etc marker, - }, + const typeEngtoKor = (name: string) => { + const kor = ["음식점", "카페", "문화", "미용", "기타"]; + return kor[eng.indexOf(name)]; }; + useEffect(() => { + const baseData = getContractBase({ + isPicked: false, + name: "", + category: "NONE", + pageNumber: 0, + }); + baseData.then((res) => { + setData(res?.contractedStores); + console.log(res?.contractedStores); + }); + }, []); + const [isSearchModalOpen, setIsSearchModalOpen] = useState(false); const [contentFilter, setContentFilter] = useState< "All" | "FOOD" | "CAFE" | "BEAUTY" | "CULTURE" | "ETC" @@ -62,6 +61,9 @@ export default function Contact() { const handleOnClickSearchBtn = () => { setIsSearchModalOpen(!isSearchModalOpen); }; + + const router = useRouter(); + return ( <> @@ -79,7 +81,7 @@ export default function Contact() { - search icon + 삭제하기 @@ -89,27 +91,41 @@ export default function Contact() { - - - - {typeStyles["음식점"].value} - - 음식점 - - dash board icon - - - 제대로 미용실 - - 주문시 - 24% 할인 - - + {data?.map((el) => { + return ( + { + router.push(`/contact/store/${el.storeId}`); + }} + > + + + {typeIcon[typeEngtoKor(el.category)]?.value || null} + + + {typeEngtoKor(el.category)} + + + + + + {el.storeName} + + + {el.benefits[0].content} + + + {el.benefits[0].type === "RATE" + ? el.benefits[0].amount + "% 할인" + : el.benefits[0].type === "FIX" + ? el.benefits[0].amount + "원 할인" + : el.benefits[0].content} + + + + ); + })} {isSearchModalOpen && ( @@ -117,18 +133,13 @@ export default function Contact() {
- close icon +
- search icon + @@ -137,7 +148,52 @@ export default function Contact() { - {typeStyles49["음식점"].value} + {typeIcon49["음식점"].value} + + + + 릴즈 + 음식점 + + + 서울특별시 + + + 확인 + + + + {typeIcon49["음식점"].value} + + + + 릴즈 + 음식점 + + + 서울특별시 + + + 확인 + + + + {typeIcon49["음식점"].value} + + + + 릴즈 + 음식점 + + + 서울특별시 + + + 확인 + + + + {typeIcon49["카페"].value} diff --git a/pages/contact/store/index.tsx b/pages/contact/store/[id].tsx similarity index 58% rename from pages/contact/store/index.tsx rename to pages/contact/store/[id].tsx index 4e0cb9f..ca11bb5 100644 --- a/pages/contact/store/index.tsx +++ b/pages/contact/store/[id].tsx @@ -2,13 +2,12 @@ import KakaoMap from "@/components/Map"; import GrayButton from "@/components/organisms/GrayButton"; import * as styled from "@/components/styles/ContactStore.styles"; import { COLORS } from "@/styles/colors"; -import { SizeTypeImg } from "@/utils/TypeImg"; -import React, { useState } from "react"; +import React, { useEffect, useState } from "react"; import Benefit from "@/assets/svg/info/Benefit.svg"; import Call from "@/assets/svg/info/Call.svg"; -import link from "@/assets/svg/info/Link.svg"; -import place from "@/assets/svg/info/place.svg"; -import profile from "@/assets/svg/info/Profile.svg"; +import LinkImg from "@/assets/svg/info/Link.svg"; +import Place from "@/assets/svg/info/place.svg"; +import Profile from "@/assets/svg/info/Profile.svg"; import NextBtn from "@/assets/svg/NextBtn.svg"; import Image from "next/image"; import NameMarker from "@/components/Marker/Name/NameMarker"; @@ -19,8 +18,32 @@ import Etc from "@/assets/svg/Etc.svg"; import Beauty from "@/assets/svg/Beauty.svg"; import StampModal from "@/components/organisms/Modal/StampModal"; import FinishModal from "@/components/organisms/Modal/FinishModal"; +import { SizeTypeImg68 } from "@/utils/TypeImg"; +import { useRouter } from "next/router"; +import { getContractInfo } from "@/pages/api/ContractAPI"; +import { ContractInfo } from "@/@types/Contract"; +import { typeEngtoKor } from "@/components/Marker/Icon/IconMarker"; const ContactStore = () => { + const [data, setData] = useState({ + benefits: [], + category: "NONE", + endDate: "", + latitude: 0, + longitude: 0, + manager: "", + mapUrl: "", + phoneNumber: "", + startDate: "string", + storeId: 0, + storeName: "", + visitInfo: {}, + }); + + const router = useRouter(); + const { id } = router.query; + console.log("id", id); + const [isStampModal, setIsStampModal] = useState(false); const [isFinishModal, setIsFinishModal] = useState(false); const handleOnClickStamp = () => { @@ -30,8 +53,32 @@ const ContactStore = () => { const handleOnClickFinish = () => { setIsFinishModal(!isFinishModal); }; + const typeStyles: { + [key: string]: { + value: React.JSX.Element; + }; + } = SizeTypeImg68(); - const typeStyles = SizeTypeImg(68); + useEffect(() => { + const info = getContractInfo(Number(id)); + info.then((res) => { + setData(res); + console.log("info", res); + }); + }, [id]); + const eng = ["FOOD", "CAFE", "CULTURE", "BEAUTY", "ETC"]; + + const typeEngtoKor = ( + name: string + ): "음식점" | "카페" | "문화" | "미용" | "기타" => { + const kor = ["음식점", "카페", "문화", "미용", "기타"]; + return kor[eng.indexOf(name)] as + | "음식점" + | "카페" + | "문화" + | "미용" + | "기타"; + }; return ( <> @@ -39,7 +86,7 @@ const ContactStore = () => { 제휴 가게 @@ -62,40 +109,42 @@ const ContactStore = () => { - - + + {data && ( + + )} - {typeStyles["음식점"].value} + {data ? typeStyles[typeEngtoKor(data.category)]?.value : ""} - 릴즈 - 음식점 + {data?.storeName} + + {typeEngtoKor(data?.category)} + - place icon + - 서울특별시 + {/** TODO: address 연결 */} - Benefit icon + 주문시 @@ -104,38 +153,28 @@ const ContactStore = () => { - Call icon + - 서울특별시 + {data?.phoneNumber} - profile icon + - 서울특별시 + {data?.manager} - link icon + - 서울특별시 + {data?.mapUrl} 대시보드 - next button + @@ -159,8 +198,8 @@ const ContactStore = () => { {isStampModal && } {isFinishModal && ( )} diff --git a/utils/TypeImg.tsx b/utils/TypeImg.tsx index 8b3e1fb..0d784e9 100644 --- a/utils/TypeImg.tsx +++ b/utils/TypeImg.tsx @@ -1,15 +1,53 @@ +import SCafe from "@/assets/svg/Small/SCafe.svg"; +import SCulture from "@/assets/svg/Small/SCulture.svg"; +import SEtc from "@/assets/svg/Small/SEtc.svg"; +import SFood from "@/assets/svg/Small/SFood.svg"; +import SBeauty from "@/assets/svg/Small/SBeauty.svg"; + import Cafe from "@/assets/svg/Cafe.svg"; import Culture from "@/assets/svg/Culture.svg"; import Etc from "@/assets/svg/Etc.svg"; import Food from "@/assets/svg/Food.svg"; import Beauty from "@/assets/svg/Beauty.svg"; +import MFood from "@/assets/svg/Mid/MFood.svg"; +import MCafe from "@/assets/svg/Mid/MCafe.svg"; +import MBeauty from "@/assets/svg/Mid/MBeauty.svg"; +import MCulture from "@/assets/svg/Mid/MCulture.svg"; +import MEtc from "@/assets/svg/Mid/MEtc.svg"; + +import MLFood from "@/assets/svg/57/Food.svg"; +import MLCafe from "@/assets/svg/57/Cafe.svg"; +import MLBeauty from "@/assets/svg/57/Beauty.svg"; +import MLCulture from "@/assets/svg/57/Culture.svg"; +import MLEtc from "@/assets/svg/57/Etc.svg"; + import LCafe from "@/assets/svg/Big/Cafe.svg"; import LCulture from "@/assets/svg/Big/Culture.svg"; import LEtc from "@/assets/svg/Big/Etc.svg"; import LFood from "@/assets/svg/Big/Food.svg"; import LBeauty from "@/assets/svg/Big/Beauty.svg"; +export const SizeTypeImgSmall = () => { + return { + 음식점: { + value: , + }, + 카페: { + value: , + }, + 미용: { + value: , + }, + 문화: { + value: , + }, + 기타: { + value: , + }, + }; +}; + export const SizeTypeImg25 = () => { return { 음식점: { @@ -30,6 +68,46 @@ export const SizeTypeImg25 = () => { }; }; +export const SizeTypeImg49 = () => { + return { + 음식점: { + value: , + }, + 카페: { + value: , + }, + 미용: { + value: , + }, + 문화: { + value: , + }, + 기타: { + value: , + }, + }; +}; + +export const SizeTypeImg57 = () => { + return { + 음식점: { + value: , + }, + 카페: { + value: , + }, + 미용: { + value: , + }, + 문화: { + value: , + }, + 기타: { + value: , + }, + }; +}; + export const SizeTypeImg68 = () => { return { 음식점: {