diff --git a/components/hooks/useCouponData.ts b/components/hooks/useCouponData.ts index 02a8dce..4b014f1 100644 --- a/components/hooks/useCouponData.ts +++ b/components/hooks/useCouponData.ts @@ -8,6 +8,7 @@ interface CouponContent { couponStore: string; couponCondition: Array; couponQuantity: number; + couponId: number; } export const useCouponData = () => { @@ -33,18 +34,3 @@ export const useCouponData = () => { return { coupons }; }; -// // 예시 데이터 -// const exData: CouponContent[] = [ -// { -// couponName: "엽떡 10000원 할인", -// couponStore: "엽기 떡볶이", -// couponCondition: ["10만원 이상 구매시", "4명 이상이 오면"], -// couponQuantity: 50, -// }, -// { -// couponName: "소소 떡볶이 10000원 할인", -// couponStore: "엽기 떡볶이", -// couponCondition: ["10만원 이상 구매시", "4명 이상이 오면"], -// couponQuantity: 50, -// }, -// ]; diff --git a/components/hooks/useStores.ts b/components/hooks/useStores.ts new file mode 100644 index 0000000..aac139b --- /dev/null +++ b/components/hooks/useStores.ts @@ -0,0 +1,39 @@ +import { getFoods } from "@/pages/api/others"; +import { useEffect, useState } from "react"; + +interface CouponProps { + isPicked: boolean; + name: string; + category: "FOOD" | "CAFE" | "BEAUTY" | "CULTURE" | "ETC"; + pageSize: number; + pageNumber: number; +} + +export const useStores = async ({ + isPicked, + name, + category, + pageSize, + pageNumber, +}: CouponProps) => { + const [data, setData] = useState(); + + useEffect(() => { + const fetchData = async () => { + const result = await getFoods({ + isPicked, + name, + category, + pageSize, + pageNumber, + }); + + setData(result.coupons); + console.log(result.coupons); + }; + + fetchData(); + }, []); + + return { data }; +}; diff --git a/components/organisms/Header.tsx b/components/organisms/Header.tsx index 8ba1557..e2d77ad 100644 --- a/components/organisms/Header.tsx +++ b/components/organisms/Header.tsx @@ -1,27 +1,32 @@ import styled from "@emotion/styled"; import Link from "next/link"; - import React, { useEffect, useState } from "react"; import NotificationsNoneOutlinedIcon from "@mui/icons-material/NotificationsNoneOutlined"; import Logo from "@/components/atoms/Logo.svg"; import { useRouter } from "next/router"; import { useModal } from "../hooks/useModal"; -import { useSetRecoilState } from "recoil"; +import { useRecoilState } from "recoil"; import { initialState } from "@/state/user/user"; import { Logout } from "@/pages/api/login"; +import { Box, Button, Modal } from "@mui/material"; +import { css } from "@emotion/css"; -/* -TODO: -1. 로그인 - 세션스토리지 안에 로그인 여부에 따라서 다르게 -*/ const Header = () => { + const [modalOpen, setModalOpen] = useState(false); + const handleOpen = () => { + setModalOpen(true); + }; + const handleClose = () => { + setModalOpen(false); + }; + const router = useRouter(); const { openModal } = useModal(); const [userSessionData, setUserSessionData] = useState(null); - const setLogout = useSetRecoilState(initialState); + const [logData, setLogData] = useRecoilState(initialState); useEffect(() => { setUserSessionData(window.sessionStorage?.getItem("userSession")); @@ -32,21 +37,75 @@ const Header = () => { }, [userSessionData]); const logoutHandler = async () => { - console.log("logout"); - const response = await Logout(); - console.log(response); - setLogout({ + console.log("logout합니다"); + const result = await Logout(); + console.log(result); + + setLogData({ + logined: false, email: "", type: "", typeName: "", token: "", }); + sessionStorage.clear(); + setUserSessionData(null); }; return ( + +
+ 정말 로그아웃 하시겠습니까? + 로그인한 모든 곳에서 로그아웃됩니다. +
+ + +
+
+
{ router.push("/"); @@ -61,6 +120,8 @@ const Header = () => { { if (userSessionData) { + + setModalOpen(true); logoutHandler(); } else { @@ -113,6 +174,24 @@ const Header = () => { ); }; +const ModalTitle = styled.p` + color: var(--, #3d4149); + text-align: center; + font-family: Pretendard; + font-size: 20px; + font-style: normal; + font-weight: 600; +`; + +const ModalSubTitle = styled.p` + color: #afafaf; + text-align: center; + font-family: Pretendard Variable; + font-size: 13.984px; + font-style: normal; + font-weight: 400; +`; + const HeaderFrame = styled.div` padding: 1rem 10rem 1rem 10rem; diff --git a/components/organisms/Modal.tsx b/components/organisms/Modal.tsx index f955964..6cbf8b4 100644 --- a/components/organisms/Modal.tsx +++ b/components/organisms/Modal.tsx @@ -8,6 +8,7 @@ import Logo from "@/components/atoms/Logo.svg"; import ModalCloseButton from "@/components/atoms/ModalCloseBtn.svg"; import { login } from "@/pages/api/login"; import { initialState } from "@/state/user/user"; +import { useRouter } from "next/router"; interface ModalProps { children?: React.ReactNode; @@ -18,6 +19,8 @@ const LoginModal: React.FC = () => { const { closeModal } = useModal(); + const router = useRouter(); + const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const setLoginedUserState = useSetRecoilState(initialState); @@ -27,18 +30,16 @@ const LoginModal: React.FC = () => { const result = await login({ email: email, password: password }); setLoginedUserState((prev) => ({ ...prev, + logined: true, token: result.accessToken, })); + router.reload(); return result.data; } catch (error) { console.error(error); } }; - useEffect(() => { - console.log(`${email} + ${password}`); - }, []); - if (!isOpen) return null; return ( diff --git a/pages/api/coupon.ts b/pages/api/coupon.ts index ce7be2c..e691a66 100644 --- a/pages/api/coupon.ts +++ b/pages/api/coupon.ts @@ -1,21 +1,7 @@ import axios from "axios"; -const apiBase = () => { - const userSession = sessionStorage.getItem("userSession"); - let token: string = ""; - if (userSession) { - const parsedSession = JSON.parse(userSession); - token = parsedSession.user?.token || ""; - } else { - console.log("유저세션 없음"); - } +import { axiosInstance } from "./axiosInstance"; - return axios.create({ - baseURL: process.env.NEXT_PUBLIC_API_URL, - timeout: 3000, - headers: { Authorization: `Bearer ${token}` }, - }); -}; interface CouponProps { type: "COUPON"; @@ -30,7 +16,9 @@ export const getCoupons = async ({ }: CouponProps) => { try { const url = `${process.env.NEXT_PUBLIC_API_URL}${process.env.NEXT_PUBLIC_GET_COUPONS}?type=${type}&pageSize=${pageSize}&pageNumber=${pageNumber}`; - const response = await apiBase().get(url); + + const response = await axiosInstance().get(url); + return response.data; } catch (e) { console.error(`Error 코드 : ${e}`); @@ -59,7 +47,9 @@ export const createCoupon = async ({ }: EventProps) => { try { const url = `${process.env.NEXT_PUBLIC_API_URL}${process.env.NEXT_PUBLIC_POST_COUPON}`; - const response = await apiBase().post(url, { + + const response = await axiosInstance().post(url, { + storeId, type, name, @@ -72,3 +62,19 @@ export const createCoupon = async ({ console.error(`Error 코드 : ${e}`); } }; + + +interface DeleteProps { + items: number[]; +} + +export const deleteCoupons = async ({ items }: DeleteProps) => { + try { + const url = `${process.env.NEXT_PUBLIC_API_URL}${process.env.NEXT_PUBLIC_DELETE_COUPONS}?type=COUPON&ids=${items}`; + const response = await axiosInstance().delete(url); + return response.data; + } catch (e) { + console.error(`Error 코드 : ${e}`); + } +}; + diff --git a/pages/api/login.ts b/pages/api/login.ts index c4f136a..6650277 100644 --- a/pages/api/login.ts +++ b/pages/api/login.ts @@ -1,4 +1,5 @@ import axios from "axios"; +import { axiosInstance } from "./axiosInstance"; const apiBase = axios.create({ baseURL: process.env.NEXT_PUBLIC_API_URL, @@ -89,28 +90,13 @@ export const CreateImage = async (file: File) => { // 로그아웃 export const Logout = async () => { - const userSession = sessionStorage.getItem("userSession"); - let token: string = ""; - if (userSession) { - const parsedSession = JSON.parse(userSession); - token = parsedSession.user?.token || ""; - } else { - console.log("유저세션 없음"); - } - try { - const response = await apiBase.post( - `${process.env.NEXT_PUBLIC_LOGOUT_ENDPOINT}`, - - { - headers: { - Authorization: `Bearer ${token}`, - }, - } - ); + try { + const url = `${process.env.NEXT_PUBLIC_API_URL}${process.env.NEXT_PUBLIC_LOGOUT_ENDPOINT}`; + const response = await axiosInstance().post(url); return response.data; } catch (e) { - console.error(`에러코드 : ${e}`); + console.error(`Error 코드 : ${e}`); } }; diff --git a/pages/api/others.ts b/pages/api/others.ts index 4489c6e..1729ea9 100644 --- a/pages/api/others.ts +++ b/pages/api/others.ts @@ -1,26 +1,31 @@ import { axiosInstance } from "./axiosInstance"; -interface FoodProps { + +interface CouponProps { isPicked: boolean; - name: "string"; - category: "FOOD"; - pageSize: 40; - pageNumber: 0; + name: string; + category: "FOOD" | "CAFE" | "BEAUTY" | "CULTURE" | "ETC"; + pageSize: number; + pageNumber: number; } -// export const getFoods = async ({ -// type, -// pageSize = 40, -// pageNumber = 0, -// }: CouponProps) => { -// try { -// const url = `${process.env.NEXT_PUBLIC_API_URL}${process.env.NEXT_PUBLIC_GET_COUPONS}?isp=${type}&pageSize=${pageSize}&pageNumber=${pageNumber}`; -// const response = await axiosInstance().get(url); -// return response.data; -// } catch (e) { -// console.error(`Error 코드 : ${e}`); -// } -// }; +// 가게조회 +export const getFoods = async ({ + isPicked, + name, + category, + pageSize, + pageNumber, +}: CouponProps) => { + try { + const url = `${process.env.NEXT_PUBLIC_API_URL}${process.env.NEXT_PUBLIC_GET_COUPONS}?isPicked=${isPicked}&name=${name}&category=${category}&pageSize=${pageSize}&pageNumber=${pageNumber}`; + const response = await axiosInstance().get(url); + return response.data; + } catch (e) { + console.error(`Error 코드 : ${e}`); + } +}; + export const getUnivs = async () => { try { diff --git a/pages/dashboard/index.tsx b/pages/dashboard/index.tsx index 932aa71..7bedad0 100644 --- a/pages/dashboard/index.tsx +++ b/pages/dashboard/index.tsx @@ -60,14 +60,7 @@ const DashBoardPage: React.FC = () => { - {/* - 전체 - 음식점 - 카페 - 미용 - 문화 - 기타 - */} + 최근 7일 diff --git a/pages/student/coupon/index.tsx b/pages/student/coupon/index.tsx index 4a51ab0..f24888f 100644 --- a/pages/student/coupon/index.tsx +++ b/pages/student/coupon/index.tsx @@ -1,12 +1,15 @@ import { useRouter } from "next/router"; -import React from "react"; +import React, { useEffect, useState } from "react"; import * as styles from "@/components/styles/popup/style"; import { css } from "@emotion/css"; import { useCouponData } from "@/components/hooks/useCouponData"; import Link from "next/link"; import EmptyComponent from "@/components/atoms/EmptyComponent"; +import { Checkbox } from "@mui/material"; +import { deleteCoupons } from "@/pages/api/coupon"; +import { useStores } from "@/components/hooks/useStores"; import { usePopupData } from "@/components/hooks/usePopupData"; import { Checkbox } from "@mui/material"; @@ -17,9 +20,28 @@ const CouponAdminPage: React.FC = () => { const { coupons } = useCouponData(); - const data = useUniv(); - console.log(coupons); + const [deleteList, setDeleteList] = useState>([]); + + const handleCheckboxChange = (couponId: number, isChecked: boolean) => { + setDeleteList((prevList) => { + if (isChecked) { + return [...prevList, couponId]; + } else { + return prevList.filter((id) => id !== couponId); + } + }); + }; + + const data = useStores({ + isPicked: false, + name: "나", + category: "FOOD", + pageSize: 40, + pageNumber: 0, + }); + + return ( @@ -41,20 +63,26 @@ const CouponAdminPage: React.FC = () => { {coupons.length !== 0 ? ( - coupons.map((element, index) => ( - - {index + 1} - {element.couponName} - - - {element.couponStore} - - - - - - - )) + coupons.map((element, index) => { + return ( + + {index + 1} + {element.couponName} + + + {element.couponStore} + + + + handleCheckboxChange(element.couponId, e.target.checked) + } + /> + + + ); + }) + ) : (
{ 등록하기 - 삭제하기 + { + const deleteCoupon = async () => { + const result = await deleteCoupons({ items: deleteList }); + }; + deleteCoupon(); + router.reload(); + }} + > + 삭제하기 +
); diff --git a/pages/student/coupon/register/Inputs.tsx b/pages/student/coupon/register/Inputs.tsx index 5ba217d..217feac 100644 --- a/pages/student/coupon/register/Inputs.tsx +++ b/pages/student/coupon/register/Inputs.tsx @@ -1,18 +1,27 @@ import React, { useEffect, useMemo, useState } from "react"; import * as styles from "../../../../components/styles/CInputs.style"; - import { css } from "@emotion/css"; import { Checkbox, + Dialog, FilledInput, IconButton, InputAdornment, + List, + ListItem, + ListItemText, + } from "@mui/material"; import SearchTwoToneIcon from "@mui/icons-material/SearchTwoTone"; import { createCoupon } from "@/pages/api/coupon"; import CheckCircleIcon from "@mui/icons-material/CheckCircle"; import CircleIcon from "@mui/icons-material/Circle"; + +import { getFoods } from "@/pages/api/others"; +import { useCouponData } from "@/components/hooks/useCouponData"; +import { useStores } from "@/components/hooks/useStores"; + interface EventProps { storeId: number; type: "COUPON"; @@ -35,6 +44,20 @@ const Inputs: React.FC = () => { ); + const [stores, setStores] = useState([]); + const [searchTerm, setSearchTerm] = useState(""); + + const handleSelectedStore = (store: any) => { + setFormData({ ...formData, storeId: store.storeId }); + }; + + useEffect(() => { + console.log(formData); + }, []); + + console.log(stores); + + const [formData, setFormData] = useState({ storeId: 2, type: "COUPON", @@ -105,6 +128,11 @@ const Inputs: React.FC = () => { className={css` width: 50%; `} + + onChange={(e) => { + setSearchTerm(e.target.value); + }} + placeholder={placeHolders[1]} endAdornment={ diff --git a/pages/student/popup/index.tsx b/pages/student/popup/index.tsx index b2768ff..4a585ca 100644 --- a/pages/student/popup/index.tsx +++ b/pages/student/popup/index.tsx @@ -9,7 +9,6 @@ import EmptyComponent from "@/components/atoms/EmptyComponent"; import { usePopupData } from "@/components/hooks/usePopupData"; import { Checkbox } from "@mui/material"; - const PopupAdminPage: React.FC = () => { const router = useRouter(); @@ -87,4 +86,3 @@ const PopupAdminPage: React.FC = () => { }; export default PopupAdminPage; - diff --git a/pages/user/index.tsx b/pages/user/index.tsx index 861e73e..520a56d 100644 --- a/pages/user/index.tsx +++ b/pages/user/index.tsx @@ -84,11 +84,9 @@ const UserPage: React.FC = () => { } checkedIcon={} - onChange={(e: React.ChangeEvent) => { const { checked } = e.target; checked