= {
+ [StoreItemType.EXTENSION]: {
+ icon: ItemIconMap.EXTENSION,
+ title: "연장권",
+ content: `
+ store 탭을 눌러 연장권 구매하기 버튼을 클릭 후 3일 , 15일 , 31일 단위로 구매할 수 있습니다.
+ 구매한 아이템은 인벤토리 탭에서 확인할 수 있습니다.
+
+ ◦ 사용방법
+
+ 사물함을 대여한 상태로, 상단 오른쪽의 상자 아이콘 을 누르면 현재 자신의 사물함의 정보 를 볼 수 있습니다.
+ 연장권 사용하기 버튼을 눌러 보유한 연장권 중 원하는 타입을 선택 후 사용합니다.
+ 이미 사용한 연장권은 취소할 수 없습니다.
+ 공유사물함의 모든 인원이 연장권을 사용할 수 있지만, 남은 인원이 한 명인 경우 연장권을 사용할 수 없습니다.
+
+ `,
+ },
+ [StoreItemType.SWAP]: {
+ icon: ItemIconMap.SWAP,
+ title: "이사권",
+ content: `
+
+ 기존 일주일에 한 번 가능했던 이사하기 기능을 제한 없이 자유롭게 사용할 수 있습니다.
+ 현재 이용중인 사물함의 대여 기간을 유지 한 채 다른 사물함으로 이사할 수 있습니다.
+ store 탭에서 구매할 수 있으며, 인벤토리 탭에서 구매한 아이템을 확인할 수 있습니다.
+
+ ◦ 사용방법
+
+ 개인 사물함을 이용중인 사용자 만 이사권을 사용할 수 있습니다.
+ 아이템을 보유한 상태로 비어있는 개인 사물함 을 눌렀을 때 이사하기 버튼이 활성화됩니다.
+ 이미 사용한 이사권은 취소할 수 없습니다.
+
+
+ `,
+ },
+ [StoreItemType.ALARM]: {
+ icon: ItemIconMap.ALARM,
+ title: "알림 등록권",
+ content: `
+ 내가 원하는 섹션에 빈 자리 가 나온다면 알림을 받을 수 있습니다.
+ 개인사물함 에 대해서만 알림을 받을 수 있습니다.
+ store 탭에서 구매할 수 있으며, 인벤토리 탭에서 구매한 아이템을 확인할 수 있습니다.
+
+ ◦ 사용방법
+
+ 아이템 구매 후 원하는 섹션으로 이동해 우측 상단의 하트 아이콘 을 클릭합니다.
+ 사용한 알림 등록권은 섹션을 변경하거나 취소할 수 없습니다.
+ 알림등록권은 1회 알림 후 소멸 됩니다.
+
+
+ `,
+ },
+ [StoreItemType.PENALTY]: {
+ icon: ItemIconMap.PENALTY,
+ title: "페널티 감면권",
+ content: `
+ 페널티 감면권은 7일 , 15일 , 31일 단위로 구매할 수 있습니다.
+ 구매한 아이템은 인벤토리 탭에서 확인할 수 있습니다.
+
+ ◦ 사용방법
+
+ 사물함 대여 불가 페널티가 부과된 유저라면 Profile 탭을 눌러 대여정보 상자 상단의
+ 페널티 감면권 사용하기 버튼 이 활성화됩니다.
+ 버튼을 눌러 내가 보유한 페널티 감면권을 선택하면, 남은 페널티 기간을 확인하실 수 있습니다.
+ 연체된 사물함을 아직 반납하지 않았다면, 우선 반납하기 버튼 을 눌러야 사용 버튼이 활성화됩니다.
+
+ `,
+ },
};
diff --git a/frontend/src/Cabinet/assets/data/SlackAlarm.ts b/frontend/src/Cabinet/assets/data/SlackAlarm.ts
index c89bb73cf..3def9e28e 100644
--- a/frontend/src/Cabinet/assets/data/SlackAlarm.ts
+++ b/frontend/src/Cabinet/assets/data/SlackAlarm.ts
@@ -23,112 +23,165 @@ export const SlackAlarmTemplates: ISlackAlarmTemplate[] = [
{
title: "점검 시작",
content: `:alert::alert::alert::alert::alert::alert:
- :happy_ccabi: 안녕하세요. Cabi 팀입니다! :happy_ccabi:
- :sad_ccabi: 서비스 개선을 위해, 서버를 점검하게 되었습니다. :sad_ccabi:
- :file_cabinet: 서비스 개선과 관련한 사항은 Cabi 채널 에서, :file_cabinet:
- :hammer_and_wrench: 보관물 관련 사항은 *데스크에 직접 문의*해주세요! :hammer_and_wrench:
- 점검 일자 : 2024년 04월 02일 (화요일)
- 점검 시간 : 15시 10분 ~ 완료 공지 시점까지
+:happy_ccabi: 안녕하세요. Cabi 팀입니다! :happy_ccabi:
+:sad_ccabi: 서비스 개선을 위해, 서버를 점검하게 되었습니다. :sad_ccabi:
+:file_cabinet: 서비스 개선과 관련한 사항은 Cabi 채널 에서, :file_cabinet:
+:hammer_and_wrench: 보관물 관련 사항은 *데스크에 직접 문의* 해주세요! :hammer_and_wrench:
- :party-dinosaur::party-dinosaur::party-dinosaur::party-dinosaur:잠시만 기다려주세요! :party-dinosaur::party-dinosaur::party-dinosaur::party-dinosaur:`,
+점검 일자 : 2024년 04월 02일 (화요일)
+점검 시간 : 15시 10분 ~ 완료 공지 시점까지
+
+:party-dinosaur::party-dinosaur::party-dinosaur::party-dinosaur:잠시만 기다려주세요! :party-dinosaur::party-dinosaur::party-dinosaur::party-dinosaur:`,
},
{
title: "점검 완료",
content: `:dancing_kirby::dancing_kirby::dancing_kirby::dancing_kirby::dancing_kirby::dancing_kirby:
- 안녕하세요. Cabi 팀입니다! :happy_ccabi:
- 현시간부로 서비스 이용이 정상화되었습니다.
- :portal_blue_parrot: 서비스는 cabi.42seoul.io 를 이용해주시면 됩니다. :portal_orange_parrot:
- :file_cabinet: 서비스 개선과 관련한 사항은 Cabi 채널 문의주세요! :file_cabinet:
- :party-dinosaur::party-dinosaur::party-dinosaur::party-dinosaur:기다려주셔서 감사합니다! :party-dinosaur::party-dinosaur::party-dinosaur::party-dinosaur:`,
+
+안녕하세요. Cabi 팀입니다! :happy_ccabi:
+현시간부로 서비스 이용이 정상화되었습니다.
+
+:portal_blue_parrot: 서비스는 cabi.42seoul.io 를 이용해주시면 됩니다. :portal_orange_parrot:
+:file_cabinet: 서비스 개선과 관련한 사항은 Cabi 채널 문의주세요! :file_cabinet:
+
+:party-dinosaur::party-dinosaur::party-dinosaur::party-dinosaur:기다려주셔서 감사합니다! :party-dinosaur::party-dinosaur::party-dinosaur::party-dinosaur:`,
},
{
title: "업데이트",
content: `:dancing_kirby::dancing_kirby::dancing_kirby::dancing_kirby::dancing_kirby::dancing_kirby:
- :happy_ccabi:동아리 장분들의 동아리 기능 사용 방법:happy_ccabi:
- ===============================================
- 내용
- ===============================================
- :point_right: 서비스는 cabi.42seoul.io 를 이용해주시면 됩니다. :point_left:`,
+
+:happy_ccabi:동아리 장분들의 동아리 기능 사용 방법:happy_ccabi:
+===============================================
+내용
+===============================================
+
+:point_right: 서비스는 cabi.42seoul.io 를 이용해주시면 됩니다. :point_left:`,
},
{
title: "이용 안내서",
content: `:file_cabinet: Cabi 이용 안내서 :file_cabinet:
- :embarrassed_cabi: 42seoul의 사물함 대여 서비스를 운영중인 Cabi 팀입니다.:embarrassed_cabi:
- 자세한 이용 방법은 Cabi 가입 후 홈페이지의 이용 안내서를 참고해 주세요!
- :point_right: https://cabi.42seoul.io/home
- :alert: Cabi FAQ :alert:
- :pushpin: 사물함의 물리적인 문제가 있습니다 (고장 났거나 잠겨있는 경우)
- :happy_ccabi: 사물함의 물리적인 문제는 데스크에 문의 부탁드립니다!
- :pushpin: 사물함 비밀번호를 모릅니다 (잊어버렸습니다).
- :happy_ccabi: 저희 서비스에서 대여한 화면과 슬랙 화면을 준비해서 데스크에 문의해주시기 바랍니다!
- :pushpin: 사물함을 닫으려는데 빨간 열쇠 표시가 뜨면서 경고음이 나고 잠기지 않습니다.
- :happy_ccabi: 사물함 안이 꽉 차거나 제대로 닫히지 않은 경우에 발생하는데, 문을 누른 상태로 비밀번호를 입력해 보시고, 그래도 되지 않는다면 데스크에 문의 부탁드립니다!
- :pushpin: 사물함 대여 후 사용하려고 했더니 안에 짐이 가득 차 있습니다.
- :happy_ccabi: 이전 사용자의 짐과 관련한 문의는 데스크에 문의 부탁드립니다!
- :pushpin: 공유 사물함을 대여했는데 비밀번호는 어디서 알 수 있을까요?
- :happy_ccabi: 같이 사용하는 사람이 있다면 대여 내역에서 공유 메모에 적혀 있을 수 있습니다. 또는 함께 사용하는 분에게 여쭤보세요!
- :pushpin: 사물함을 연체 했는데 페널티는 무엇인가요?
- :happy_ccabi: 연체일만큼 누적 연체일이 증가하고, 누적일 만큼 대여가 불가능합니다:face_holding_back_tears:`,
+
+
+:embarrassed_cabi: 42seoul의 사물함 대여 서비스를 운영중인 Cabi 팀입니다.:embarrassed_cabi:
+자세한 이용 방법은 Cabi 가입 후 홈페이지의 이용 안내서를 참고해 주세요!
+:point_right: https://cabi.42seoul.io/home
+
+
+:alert: Cabi FAQ :alert:
+
+:pushpin: 사물함의 물리적인 문제가 있습니다 (고장 났거나 잠겨있는 경우)
+:happy_ccabi: 사물함의 물리적인 문제는 데스크에 문의 부탁드립니다!
+
+:pushpin: 사물함 비밀번호를 모릅니다 (잊어버렸습니다).
+:happy_ccabi: 저희 서비스에서 대여한 화면과 슬랙 화면을 준비해서 데스크에 문의해주시기 바랍니다!
+
+:pushpin: 사물함을 닫으려는데 빨간 열쇠 표시가 뜨면서 경고음이 나고 잠기지 않습니다.
+:happy_ccabi: 사물함 안이 꽉 차거나 제대로 닫히지 않은 경우에 발생하는데, 문을 누른 상태로 비밀번호를 입력해 보시고, 그래도 되지 않는다면 데스크에 문의 부탁드립니다!
+
+:pushpin: 사물함 대여 후 사용하려고 했더니 안에 짐이 가득 차 있습니다.
+:happy_ccabi: 이전 사용자의 짐과 관련한 문의는 데스크에 문의 부탁드립니다!
+
+:pushpin: 공유 사물함을 대여했는데 비밀번호는 어디서 알 수 있을까요?
+:happy_ccabi: 같이 사용하는 사람이 있다면 대여 내역에서 공유 메모에 적혀 있을 수 있습니다. 또는 함께 사용하는 분에게 여쭤보세요!
+
+:pushpin: 사물함을 연체 했는데 페널티는 무엇인가요?
+:happy_ccabi: 연체일만큼 누적 연체일이 증가하고, 누적일 만큼 대여가 불가능합니다:face_holding_back_tears:`,
},
{
title: "모집 공고",
- content: `:embarrassed_cabi::embarrassed_cabi::embarrassed_cabi: :embarrassed_cabi::embarrassed_cabi::embarrassed_cabi:
- 안녕하세요 Cabi 팀입니다!
- 새로운 팀원 모집 공고를 올립니다:yesyes:
- 많은 관심 부탁드립니다!
- ----------------------------------------------------
- :dancing_kirby:모집개요:dancing_kirby:
- 오늘 {날짜} 부터, {날짜} 23:59까지!
- 까비 팀의 프론트엔드 / 백엔드 6기 신청을 받습니다!
- 폼 작성 - 간단한 미팅 - 최종 발표 예정입니다!
- ...
- ...까비에 할애할 수 있으신 분!
- - 열정 넘치시는 분!
- :four_leaf_clover::four_leaf_clover::four_leaf_clover::four_leaf_clover::four_leaf_clover::four_leaf_clover::four_leaf_clover::four_leaf_clover::four_leaf_clover:
- :four_leaf_clover::arrow_right:지금 바로 지원하기:arrow_left::four_leaf_clover:
- :four_leaf_clover::four_leaf_clover::four_leaf_clover::four_leaf_clover::four_leaf_clover::four_leaf_clover::four_leaf_clover::four_leaf_clover::four_leaf_clover:
- :man-bowing: 상세한 정보는 구글 폼을 참고해주시고, 이외에 모집과 관련한 문의는
- @jpark2 에게 DM 부탁드립니다! :man-bowing:`,
+ content: `:white_check_mark: 까비 소개 링크, 구글폼 링크 추가 :white_check_mark:
+
+:embarrassed_cabi::embarrassed_cabi::embarrassed_cabi: :embarrassed_cabi::embarrassed_cabi::embarrassed_cabi:
+
+안녕하세요 Cabi 팀입니다!
+새로운 팀원 모집 공고를 올립니다:yesyes:
+많은 관심 부탁드립니다!
+----------------------------------------------------
+:dancing_kirby:모집개요:dancing_kirby:
+오늘 {날짜} 부터, {날짜} 23:59까지!
+까비 팀의 프론트엔드 / 백엔드 n기 신청을 받습니다!
+폼 작성 - 간단한 미팅 - 최종 발표 예정입니다!
+
+
+:file_cabinet: 저희 서비스는요…:file_cabinet:
+사물함 대여 서비스: 42서울의 사물함 400여 개를 편리하게 대여 및 반납할 수 있는 서비스입니다.
+효율적이고 원활한 서비스: 제한된 자원으로 많은 사용자가 원활… (더보기)
+
+
+:hammer_and_wrench: 사용중인 기술 스택 :hammer_and_wrench:
+프론트: :typescript: / :reactjs: / Recoil
+백: :java: / Spring / Spring Boot / JPA / QueryDSL / MariaDB / Redis
+인프라: :aws: EC2, RDS, S3, CloudFront, CodeDeploy / Docker / Github Actions / Pinpoint APM / Grafana / Prometheus
+:star::star::star::star:위에 있는 기술들을 모르셔도 상관 없습니다!!:star::star::star::star:
+
+
+:thumbsup_ccabi: 까비 팀에 합류하시면... :thumbsup_ccabi:
+월 약 1300명의 유저가 사용하는 서비스를 직접 기획 / 운영 / 개발하기!
+메인, 어드민 서비스 유지 및 보수!
+친절하고 유쾌한 까비 팀원들과 친해지기!
+체계적인 협업 컨벤션과 코드 리뷰!
+트러블 슈팅과 기술 아카이브로 포트폴리오 해결!
+42Seoul Cabinet System Developer 칭호까지!
+
+
+:cat_thumbs: 다음과 같은 아이템을 염두하고 있어요! :cat_thumbs:
+재화 시스템 - 기존 상점 페이지에 새로운 아이템 추가 및 고도화
+수요지식회 - Cabi 페이지에 합쳐진 수요지식회 페이지 분리 및 후기 기능 추가
+성능 최적화 - Lighthouse 지표 개선
+
+
+:pushpin: 이런 분을 우대합니다!
+- 블랙홀이 넉넉하신 분!
+- 많은 시간을 까비에 할애할 수 있으신 분!
+- 열정 넘치시는 분!
+
+
+:four_leaf_clover::four_leaf_clover::four_leaf_clover::four_leaf_clover::four_leaf_clover::four_leaf_clover::four_leaf_clover::four_leaf_clover::four_leaf_clover:
+:four_leaf_clover::arrow_right:지금 바로 지원하기:arrow_left::four_leaf_clover:
+:four_leaf_clover::four_leaf_clover::four_leaf_clover::four_leaf_clover::four_leaf_clover::four_leaf_clover::four_leaf_clover::four_leaf_clover::four_leaf_clover:
+
+:man-bowing: 상세한 정보는 구글 폼을 참고해주시고, 이외에 모집과 관련한 문의는
+@담당자 에게 DM 부탁드립니다! :man-bowing:`,
},
{
title: "동아리 사물함",
content: `:happy_ccabi: 안녕하세요 사물함 서비스를 운영중인 Cabi 팀입니다 :happy_ccabi:
- 이번 동아리 사물함 모집을 공지드립니다!
- 기존 {날짜} 에 신청하셨던 분들도 재신청해주시기를 바랍니다.
- 신청 링크 : {링크}
- 내용은 아래와 같습니다.
- -----------------------------------------------------
- < :hourglass_flowing_sand: 모집 기간 >
- 2024년 동아리 사물함 신청은 일주일 동안 진행됩니다.
- 3월 15일(금) 부터
- ~ 3월 22일(금) 23:59 까지 입니다.
- *이 시간대 외의 신청은 유효하지 않은 신청으로 간주됩니다:disappointed_relieved:
- -----------------------------------------------------
- < :pushpin: 선발 기준 >
- [스프레드 시트에 등록된] 42 Seoul 동아리 리스트에 포함된 동아리
- 신청자 수가 사물함보다 많을경우 추첨으로 진행됩니다.
- -----------------------------------------------------
- < :mantelpiece_clock: 발표일 >
- 10월 20일 오후 중 발표 예정입니다!
- 해당 발표 결과는 슬랙의 ‘42seoul_club_cabinet’, ‘42seoul_global_random’ 채널에 공지 드릴 예정입니다.
- 사물함 배정이 완료된 후 동아리 사물함 대표분들에게, 슬랙 DM으로 메시지가 전송될 예정입니다.
- -----------------------------------------------------
- < :man-tipping-hand: 유의사항 >
- 1. 기존에 동아리 사물함을 사용중이셨다면, 새로이 사용하는 동아리들의 원활한 이용을 위해서
- 3월 22일(금)까지 사물함을 비워주시기 바랍니다!
- 2. 위 모든 내용은 상황에 따라 변경될 수 있으며 차후에도 변경될 수 있습니다.
- 이 때에는 재공지될 예정입니다!
- -----------------------------------------------------
- < :telephone_receiver: 문의사항 >
- 슬랙의 ‘42seoul_club_cabinet’ 채널에 문의해주시면 됩니다! :sunglasses:`,
+
+이번 동아리 사물함 모집을 공지드립니다!
+기존 {날짜} 에 신청하셨던 분들도 재신청해주시기를 바랍니다.
+신청 링크 : {링크}
+내용은 아래와 같습니다.
+-----------------------------------------------------
+< :hourglass_flowing_sand: 모집 기간 >
+2024년 동아리 사물함 신청은 일주일 동안 진행됩니다.
+3월 15일(금) 부터
+~ 3월 22일(금) 23:59 까지 입니다.
+*이 시간대 외의 신청은 유효하지 않은 신청으로 간주됩니다:disappointed_relieved:
+-----------------------------------------------------
+< :pushpin: 선발 기준 >
+[스프레드 시트에 등록된] 42 Seoul 동아리 리스트에 포함된 동아리
+신청자 수가 사물함보다 많을경우 추첨으로 진행됩니다.
+-----------------------------------------------------
+< :mantelpiece_clock: 발표일 >
+10월 20일 오후 중 발표 예정입니다!
+해당 발표 결과는 슬랙의 ‘42seoul_club_cabinet’, ‘42seoul_global_random’ 채널에 공지 드릴 예정입니다.
+사물함 배정이 완료된 후 동아리 사물함 대표분들에게, 슬랙 DM으로 메시지가 전송될 예정입니다.
+-----------------------------------------------------
+< :man-tipping-hand: 유의사항 >
+1. 기존에 동아리 사물함을 사용중이셨다면, 새로이 사용하는 동아리들의 원활한 이용을 위해서
+3월 22일(금)까지 사물함을 비워주시기 바랍니다!
+2. 위 모든 내용은 상황에 따라 변경될 수 있으며 차후에도 변경될 수 있습니다.
+이 때에는 재공지될 예정입니다!
+-----------------------------------------------------
+< :telephone_receiver: 문의사항 >
+슬랙의 ‘42seoul_club_cabinet’ 채널에 문의해주시면 됩니다! :sunglasses:`,
},
{
title: "연체",
content: `[CABI] 안녕하세요! :embarrassed_cabi:
- 현재 이용 중이신 사물함이 연체인 것으로 확인되어 연락드립니다.
- 장기간 연체시 서비스 이용에 대한 페널티, 혹은 :tig:가 부여될 수 있음을 인지해주세요!
- 사물함의 대여 기간을 확인하신 후 반납 부탁드립니다.
- 항상 저희 서비스를 이용해 주셔서 감사합니다:)`,
+ 현재 이용 중이신 사물함이 *연체* 된 것으로 확인되어 연락드립니다.
+ *3주(21일) 이상 연체 시 미회수된 개인 물품은 폐기될 수 있음을 인지해 주세요!*
+ 사물함의 대여 기간을 확인하신 후 반납 부탁드립니다.
+ 항상 저희 서비스를 이용해 주셔서 감사합니다:)`,
},
];
diff --git a/frontend/src/Cabinet/assets/data/maps.ts b/frontend/src/Cabinet/assets/data/maps.ts
index 8706697ba..a1bfdfc83 100644
--- a/frontend/src/Cabinet/assets/data/maps.ts
+++ b/frontend/src/Cabinet/assets/data/maps.ts
@@ -1,5 +1,13 @@
+import { css } from "styled-components";
+import {
+ coinBoxStyles,
+ extensionBoxStyles,
+ inSessionBoxStyles,
+ pendingBoxStyles,
+ storeBoxStyles,
+} from "@/Cabinet/components/Home/ManualContentBoxStyles";
import { ReactComponent as ClubIcon } from "@/Cabinet/assets/images/clubIcon.svg";
-import { ReactComponent as ExtensionImg } from "@/Cabinet/assets/images/extension.svg";
+import { ReactComponent as ExtensionImg } from "@/Cabinet/assets/images/storeExtension.svg";
import { ReactComponent as PrivateIcon } from "@/Cabinet/assets/images/privateIcon.svg";
import { ReactComponent as ShareIcon } from "@/Cabinet/assets/images/shareIcon.svg";
import { ReactComponent as AlarmImg } from "@/Cabinet/assets/images/storeAlarm.svg";
@@ -7,6 +15,7 @@ import { ReactComponent as SwapImg } from "@/Cabinet/assets/images/storeMove.svg
import { ReactComponent as PenaltyImg } from "@/Cabinet/assets/images/storePenalty.svg";
import CabinetStatus from "@/Cabinet/types/enum/cabinet.status.enum";
import CabinetType from "@/Cabinet/types/enum/cabinet.type.enum";
+import ContentStatus from "@/Cabinet/types/enum/content.status.enum";
import {
StoreExtensionType,
StoreItemType,
@@ -267,3 +276,16 @@ export const ItemTypeExtensionMap = {
[StoreExtensionType.EXTENSION_15]: "15일",
[StoreExtensionType.EXTENSION_31]: "31일",
};
+
+export const ContentStatusStylesMap: {
+ [key in ContentStatus]: any;
+} = {
+ [ContentStatus.EXTENSION]: extensionBoxStyles,
+ [ContentStatus.STORE]: storeBoxStyles,
+ [ContentStatus.COIN]: coinBoxStyles,
+ [ContentStatus.PENDING]: pendingBoxStyles,
+ [ContentStatus.IN_SESSION]: inSessionBoxStyles,
+ [ContentStatus.PRIVATE]: css``,
+ [ContentStatus.SHARE]: css``,
+ [ContentStatus.CLUB]: css``,
+};
diff --git a/frontend/src/Cabinet/assets/images/coinDolar.svg b/frontend/src/Cabinet/assets/images/coinDolar.svg
new file mode 100644
index 000000000..72f985b8f
--- /dev/null
+++ b/frontend/src/Cabinet/assets/images/coinDolar.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/frontend/src/Cabinet/assets/images/storeAlarm.svg b/frontend/src/Cabinet/assets/images/storeAlarm.svg
index fdec88cdb..deb44a952 100644
--- a/frontend/src/Cabinet/assets/images/storeAlarm.svg
+++ b/frontend/src/Cabinet/assets/images/storeAlarm.svg
@@ -1,4 +1,4 @@
-
-
-
+
+
+
diff --git a/frontend/src/Cabinet/assets/images/storeExtension.svg b/frontend/src/Cabinet/assets/images/storeExtension.svg
index 91c16096c..d97f6f116 100644
--- a/frontend/src/Cabinet/assets/images/storeExtension.svg
+++ b/frontend/src/Cabinet/assets/images/storeExtension.svg
@@ -1,6 +1,6 @@
-
-
-
-
-
+
+
+
+
+
diff --git a/frontend/src/Cabinet/assets/images/storeMove.svg b/frontend/src/Cabinet/assets/images/storeMove.svg
index 4500e4867..f87ec2c31 100644
--- a/frontend/src/Cabinet/assets/images/storeMove.svg
+++ b/frontend/src/Cabinet/assets/images/storeMove.svg
@@ -1,7 +1,7 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/frontend/src/Cabinet/assets/images/storePenalty.svg b/frontend/src/Cabinet/assets/images/storePenalty.svg
index 158760b33..9838cbd18 100644
--- a/frontend/src/Cabinet/assets/images/storePenalty.svg
+++ b/frontend/src/Cabinet/assets/images/storePenalty.svg
@@ -1,5 +1,5 @@
-
-
-
-
+
+
+
+
diff --git a/frontend/src/Cabinet/components/CabinetInfoArea/CabinetInfoArea.tsx b/frontend/src/Cabinet/components/CabinetInfoArea/CabinetInfoArea.tsx
index 8ec38283a..9159f504c 100644
--- a/frontend/src/Cabinet/components/CabinetInfoArea/CabinetInfoArea.tsx
+++ b/frontend/src/Cabinet/components/CabinetInfoArea/CabinetInfoArea.tsx
@@ -9,13 +9,13 @@ import CountTimeContainer from "@/Cabinet/components/CabinetInfoArea/CountTime/C
import ButtonContainer from "@/Cabinet/components/Common/Button";
import SelectInduction from "@/Cabinet/components/Common/SelectInduction";
import CancelModal from "@/Cabinet/components/Modals/CancelModal/CancelModal";
-import ExtendModal from "@/Cabinet/components/Modals/ExtendModal/ExtendModal";
import InvitationCodeModalContainer from "@/Cabinet/components/Modals/InvitationCodeModal/InvitationCodeModal.container";
import LentModal from "@/Cabinet/components/Modals/LentModal/LentModal";
import MemoModalContainer from "@/Cabinet/components/Modals/MemoModal/MemoModal.container";
import PasswordCheckModalContainer from "@/Cabinet/components/Modals/PasswordCheckModal/PasswordCheckModal.container";
import ReturnModal from "@/Cabinet/components/Modals/ReturnModal/ReturnModal";
-import SwapModal from "@/Cabinet/components/Modals/SwapModal/SwapModal";
+import ExtendModal from "@/Cabinet/components/Modals/StoreModal/ExtendModal";
+import SwapModal from "@/Cabinet/components/Modals/StoreModal/SwapModal";
import UnavailableModal from "@/Cabinet/components/Modals/UnavailableModal/UnavailableModal";
import {
additionalModalType,
diff --git a/frontend/src/Cabinet/components/CabinetInfoArea/CountTime/CodeAndTime.tsx b/frontend/src/Cabinet/components/CabinetInfoArea/CountTime/CodeAndTime.tsx
index c3c013be9..5535b3852 100644
--- a/frontend/src/Cabinet/components/CabinetInfoArea/CountTime/CodeAndTime.tsx
+++ b/frontend/src/Cabinet/components/CabinetInfoArea/CountTime/CodeAndTime.tsx
@@ -5,6 +5,7 @@ import { myCabinetInfoState } from "@/Cabinet/recoil/atoms";
import alertImg from "@/Cabinet/assets/images/cautionSign.svg";
import { ReactComponent as ClockImg } from "@/Cabinet/assets/images/clock.svg";
import { MyCabinetInfoResponseDto } from "@/Cabinet/types/dto/cabinet.dto";
+import useDebounce from "@/Cabinet/hooks/useDebounce";
interface CountTimeProps {
minutes: string;
@@ -17,13 +18,18 @@ const CodeAndTime = ({ minutes, seconds, isTimeOver }: CountTimeProps) => {
useRecoilValue(myCabinetInfoState);
const code = myCabinetInfo.shareCode + "";
const [copySuccess, setCopySuccess] = useState(false);
+ const { debounce } = useDebounce();
const handleCopyClick = () => {
navigator.clipboard.writeText(code).then(() => {
setCopySuccess(true);
- setTimeout(() => {
- setCopySuccess(false);
- }, 2000);
+ debounce(
+ "codeCopyClick",
+ () => {
+ setCopySuccess(false);
+ },
+ 2000
+ );
});
};
diff --git a/frontend/src/Cabinet/components/CabinetList/CabinetList.container.tsx b/frontend/src/Cabinet/components/CabinetList/CabinetList.container.tsx
index 64515e003..1e9dd4fc2 100644
--- a/frontend/src/Cabinet/components/CabinetList/CabinetList.container.tsx
+++ b/frontend/src/Cabinet/components/CabinetList/CabinetList.container.tsx
@@ -1,6 +1,7 @@
import React from "react";
-import { useRecoilValue } from "recoil";
+import { useRecoilState, useRecoilValue } from "recoil";
import {
+ currentFloorSectionNamesState,
currentSectionNameState,
isMultiSelectState,
} from "@/Cabinet/recoil/atoms";
@@ -30,6 +31,10 @@ const CabinetListContainer = ({
const currentSectionName = useRecoilValue(currentSectionNameState);
const isMultiSelect = useRecoilValue(isMultiSelectState);
const { handleSelectAll, containsAllCabinets } = useMultiSelect();
+ const [currentFloorSectionNames] = useRecoilState(
+ currentFloorSectionNamesState
+ );
+
return (
{isMultiSelect && (
@@ -45,7 +50,9 @@ const CabinetListContainer = ({
/>
)}
-
+ {currentFloorSectionNames.includes(currentSectionName) && (
+
+ )}
{
};
const DisplayStyleCardWrapper = styled.div`
- z-index: 1;
align-self: start;
`;
diff --git a/frontend/src/Cabinet/components/Card/ExtensionCard/ExtensionCard.container.tsx b/frontend/src/Cabinet/components/Card/ExtensionCard/ExtensionCard.container.tsx
deleted file mode 100644
index 18958f830..000000000
--- a/frontend/src/Cabinet/components/Card/ExtensionCard/ExtensionCard.container.tsx
+++ /dev/null
@@ -1,76 +0,0 @@
-import { useRecoilState, useSetRecoilState } from "recoil";
-import {
- currentCabinetIdState,
- myCabinetInfoState,
- targetCabinetInfoState,
- userState,
-} from "@/Cabinet/recoil/atoms";
-import ExtensionCard from "@/Cabinet/components/Card/ExtensionCard/ExtensionCard";
-import { CabinetInfo } from "@/Cabinet/types/dto/cabinet.dto";
-import { LentDto, LentExtensionDto } from "@/Cabinet/types/dto/lent.dto";
-import { axiosCabinetById } from "@/Cabinet/api/axios/axios.custom";
-import useMenu from "@/Cabinet/hooks/useMenu";
-
-const ExtensionCardContainer = ({
- extensionInfo,
-}: {
- extensionInfo: LentExtensionDto | null;
-}) => {
- const { toggleCabinet, openCabinet, closeAll } = useMenu();
- const [myInfo, setMyInfo] = useRecoilState(userState);
- const [currentCabinetId, setCurrentCabinetId] = useRecoilState(
- currentCabinetIdState
- );
- const [myCabinetInfo, setMyCabinetInfo] = useRecoilState(myCabinetInfoState);
- const setTargetCabinetInfo = useSetRecoilState(
- targetCabinetInfoState
- );
- async function setTargetCabinetInfoToMyCabinet() {
- setCurrentCabinetId(myInfo.cabinetId);
- setMyInfo((prev) => ({ ...prev, cabinetId: null }));
- try {
- if (!myCabinetInfo?.cabinetId) return;
- const { data } = await axiosCabinetById(myCabinetInfo.cabinetId);
- if (data.lents.length === 0 && myInfo.cabinetId !== null) {
- setMyInfo((prev) => ({ ...prev, cabinetId: null }));
- } else {
- const doesNameExist = data.lents.some(
- (lent: LentDto) => lent.name === myInfo.name
- );
- if (doesNameExist) {
- setTargetCabinetInfo(data);
- setCurrentCabinetId(data.cabinetId);
- setMyInfo((prev) => ({ ...prev, cabinetId: data.cabinetId }));
- }
- }
- } catch (error) {
- console.log(error);
- }
- }
- const clickMyCabinet = () => {
- if (!!extensionInfo && !!myInfo.cabinetId) {
- if (myInfo.cabinetId === null && !myCabinetInfo?.cabinetId) {
- setTargetCabinetInfoToMyCabinet();
- toggleCabinet();
- } else if (currentCabinetId !== myInfo.cabinetId) {
- setTargetCabinetInfoToMyCabinet();
- openCabinet();
- } else {
- toggleCabinet();
- }
- }
- };
- return (
- clickMyCabinet(),
- isClickable: !!extensionInfo && !!myInfo.cabinetId,
- isExtensible: !!extensionInfo,
- }}
- />
- );
-};
-
-export default ExtensionCardContainer;
diff --git a/frontend/src/Cabinet/components/Card/ExtensionCard/ExtensionCard.tsx b/frontend/src/Cabinet/components/Card/ExtensionCard/ExtensionCard.tsx
deleted file mode 100644
index e35446a69..000000000
--- a/frontend/src/Cabinet/components/Card/ExtensionCard/ExtensionCard.tsx
+++ /dev/null
@@ -1,63 +0,0 @@
-import { useState } from "react";
-import Card, { IButtonProps } from "@/Cabinet/components/Card/Card";
-import {
- CardContentStyled,
- CardContentWrapper,
- ContentDetailStyled,
- ContentInfoStyled,
-} from "@/Cabinet/components/Card/CardStyles";
-import { NotificationModal } from "@/Cabinet/components/Modals/NotificationModal/NotificationModal";
-import { LentExtensionDto } from "@/Cabinet/types/dto/lent.dto";
-import { formatDate } from "@/Cabinet/utils/dateUtils";
-
-interface ExtensionProps {
- extensionInfo: LentExtensionDto | null;
- button: IButtonProps;
-}
-
-const NotificationModalDetail = `연장권은 매월 2일 제공되며, 이전에 받은 연장권은 사용이 불가능 합니다. 24HANE 기준 160시간을 출석한 경우, 연장권이 부여됩니다.`;
-
-const ExtensionCard = ({ extensionInfo, button }: ExtensionProps) => {
- const [showNotificationModal, setShowNotificationModal] =
- useState(false);
- return (
- <>
- {
- setShowNotificationModal(true);
- }}
- gridArea={"extension"}
- width={"350px"}
- height={"183px"}
- buttons={[button]}
- >
-
-
- 사용 기한
-
- {!!extensionInfo
- ? formatDate(new Date(extensionInfo.expiredAt), ".", 4, 2, 2)
- : "-"}
-
-
-
- 연장 기간
-
- {!!extensionInfo ? extensionInfo.extensionPeriod + "일" : "-"}
-
-
-
-
- {showNotificationModal && (
- setShowNotificationModal(false)}
- />
- )}
- >
- );
-};
-
-export default ExtensionCard;
diff --git a/frontend/src/Cabinet/components/Card/LentInfoCard/LentInfoCard.tsx b/frontend/src/Cabinet/components/Card/LentInfoCard/LentInfoCard.tsx
index 80ab11f97..b3cc0195b 100644
--- a/frontend/src/Cabinet/components/Card/LentInfoCard/LentInfoCard.tsx
+++ b/frontend/src/Cabinet/components/Card/LentInfoCard/LentInfoCard.tsx
@@ -7,11 +7,11 @@ import {
ContentInfoStyled,
} from "@/Cabinet/components/Card/CardStyles";
import { MyCabinetInfo } from "@/Cabinet/components/Card/LentInfoCard/LentInfoCard.container";
+import PenaltyModal from "@/Cabinet/components/Modals/StoreModal/PenaltyModal";
import { cabinetIconComponentMap } from "@/Cabinet/assets/data/maps";
import { IItemTimeRemaining } from "@/Cabinet/types/dto/store.dto";
import CabinetStatus from "@/Cabinet/types/enum/cabinet.status.enum";
import { formatDate } from "@/Cabinet/utils/dateUtils";
-import PenaltyModal from "@/Cabinet/components/Modals//PenaltyModal/PenaltyModal";
const calculateFontSize = (userCount: number): string => {
const baseSize = 1;
diff --git a/frontend/src/Cabinet/components/Card/StoreItemCard/StoreItemCard.tsx b/frontend/src/Cabinet/components/Card/StoreItemCard/StoreItemCard.tsx
index 717e0c2df..17b021574 100644
--- a/frontend/src/Cabinet/components/Card/StoreItemCard/StoreItemCard.tsx
+++ b/frontend/src/Cabinet/components/Card/StoreItemCard/StoreItemCard.tsx
@@ -137,8 +137,6 @@ const ItemIconStyled = styled.div<{ itemType: StoreItemType }>`
& > svg > path {
stroke: var(--white-text-with-bg-color);
- stroke-width: ${(props) =>
- props.itemType === StoreItemType.EXTENSION ? "2.8px" : "1.5px"};
}
`;
diff --git a/frontend/src/Cabinet/components/Club/AdminClubLog.container.tsx b/frontend/src/Cabinet/components/Club/AdminClubLog.container.tsx
index 95b7235f9..67ddd1873 100644
--- a/frontend/src/Cabinet/components/Club/AdminClubLog.container.tsx
+++ b/frontend/src/Cabinet/components/Club/AdminClubLog.container.tsx
@@ -2,7 +2,7 @@ import { useEffect, useState } from "react";
import AdminClubLog from "@/Cabinet/components/Club/AdminClubLog";
import { ClubLogResponseType, ClubUserDto } from "@/Cabinet/types/dto/lent.dto";
import { axiosGetClubUserLog } from "@/Cabinet/api/axios/axios.custom";
-import { STATUS_400_BAD_REQUEST } from "@/Cabinet/constants/StatusCode";
+import { HttpStatusCode } from "axios";
const AdminClubLogContainer = (props: any) => {
const [logs, setLogs] = useState(undefined);
@@ -20,7 +20,7 @@ const AdminClubLogContainer = (props: any) => {
} else setTotalPage(Math.ceil(result.data.totalLength / size));
setLogs(result.data.result);
} catch {
- setLogs(STATUS_400_BAD_REQUEST);
+ setLogs(HttpStatusCode.BadRequest);
setTotalPage(1);
}
};
diff --git a/frontend/src/Cabinet/components/Club/ClubInfo.tsx b/frontend/src/Cabinet/components/Club/ClubInfo.tsx
index d26f04cbc..141635837 100644
--- a/frontend/src/Cabinet/components/Club/ClubInfo.tsx
+++ b/frontend/src/Cabinet/components/Club/ClubInfo.tsx
@@ -1,3 +1,4 @@
+import { HttpStatusCode } from "axios";
import { useEffect, useState } from "react";
import { useRecoilState } from "recoil";
import styled from "styled-components";
@@ -10,7 +11,6 @@ import UnavailableDataInfo from "@/Cabinet/components/Common/UnavailableDataInfo
import { ClubInfoResponseDto } from "@/Cabinet/types/dto/club.dto";
import useClubInfo from "@/Cabinet/hooks/useClubInfo";
import useMenu from "@/Cabinet/hooks/useMenu";
-import { STATUS_400_BAD_REQUEST } from "@/Cabinet/constants/StatusCode";
const ClubInfo = () => {
const [myInfo] = useRecoilState(userState);
@@ -20,7 +20,7 @@ const ClubInfo = () => {
useEffect(() => {
closeAll();
- if (clubInfo && clubInfo !== STATUS_400_BAD_REQUEST) {
+ if (clubInfo && clubInfo !== HttpStatusCode.BadRequest) {
let clubInfoTest = clubInfo as ClubInfoResponseDto;
if (clubInfoTest.clubMaster.userName === myInfo.name) setIsMaster(true);
}
@@ -30,7 +30,7 @@ const ClubInfo = () => {
<>
{clubInfo === undefined ? (
- ) : clubInfo === STATUS_400_BAD_REQUEST ? (
+ ) : clubInfo === HttpStatusCode.BadRequest ? (
<>
>
diff --git a/frontend/src/Cabinet/components/Club/ClubLogTable.tsx b/frontend/src/Cabinet/components/Club/ClubLogTable.tsx
index b99d219f3..59f3f610b 100644
--- a/frontend/src/Cabinet/components/Club/ClubLogTable.tsx
+++ b/frontend/src/Cabinet/components/Club/ClubLogTable.tsx
@@ -1,9 +1,9 @@
+import { HttpStatusCode } from "axios";
import { useRecoilState } from "recoil";
import styled from "styled-components";
import { selectedClubInfoState } from "@/Cabinet/recoil/atoms";
import LoadingAnimation from "@/Cabinet/components/Common/LoadingAnimation";
import { ClubLogResponseType, ClubUserDto } from "@/Cabinet/types/dto/lent.dto";
-import { STATUS_400_BAD_REQUEST } from "@/Cabinet/constants/StatusCode";
const ClubLogTable = ({ ClubList }: { ClubList: ClubLogResponseType }) => {
const [selectedClubInfo, setSelectedClubInfo] = useRecoilState(
@@ -20,7 +20,7 @@ const ClubLogTable = ({ ClubList }: { ClubList: ClubLogResponseType }) => {
return (
<>
- {ClubList !== STATUS_400_BAD_REQUEST && ClubList.length !== 0 ? (
+ {ClubList !== HttpStatusCode.BadRequest && ClubList.length !== 0 ? (
diff --git a/frontend/src/Cabinet/components/Club/ClubMemberList/ClubMemberList.container.tsx b/frontend/src/Cabinet/components/Club/ClubMemberList/ClubMemberList.container.tsx
index 0df8e737c..44c6344cd 100644
--- a/frontend/src/Cabinet/components/Club/ClubMemberList/ClubMemberList.container.tsx
+++ b/frontend/src/Cabinet/components/Club/ClubMemberList/ClubMemberList.container.tsx
@@ -1,11 +1,12 @@
import { useEffect, useState } from "react";
-import { useRecoilState, useRecoilValue } from "recoil";
-import { targetClubUserInfoState, userState } from "@/Cabinet/recoil/atoms";
+import { useRecoilState } from "recoil";
+import { targetClubUserInfoState } from "@/Cabinet/recoil/atoms";
import ClubMemberList from "@/Cabinet/components/Club/ClubMemberList/ClubMemberList";
import {
ClubInfoResponseDto,
ClubUserResponseDto,
} from "@/Cabinet/types/dto/club.dto";
+import useDebounce from "@/Cabinet/hooks/useDebounce";
import useMenu from "@/Cabinet/hooks/useMenu";
export type TClubMemberModalState = "addModal";
@@ -27,7 +28,6 @@ const ClubMemberListContainer = ({
}: ClubMemberListContainerProps) => {
const [moreButton, setMoreButton] = useState(true);
const [members, setMembers] = useState([]);
- // const [sortMembers, setSortMembers] = useState([]);
const [clubModal, setClubModal] = useState({
addModal: false,
});
@@ -36,12 +36,16 @@ const ClubMemberListContainer = ({
const [targetClubUser, setTargetClubUser] = useRecoilState(
targetClubUserInfoState
);
-
+ const { debounce } = useDebounce();
const clickMoreButton = () => {
setIsLoading(true);
- setTimeout(() => {
- setPage(page + 1);
- }, 100);
+ debounce(
+ "clubMemberList",
+ () => {
+ setPage(page + 1);
+ },
+ 300
+ );
};
const selectClubMemberOnClick = (member: ClubUserResponseDto) => {
diff --git a/frontend/src/Cabinet/components/Home/ManualContentBox.tsx b/frontend/src/Cabinet/components/Home/ManualContentBox.tsx
index 5f4885e30..2f973569d 100644
--- a/frontend/src/Cabinet/components/Home/ManualContentBox.tsx
+++ b/frontend/src/Cabinet/components/Home/ManualContentBox.tsx
@@ -1,18 +1,19 @@
import styled, { css, keyframes } from "styled-components";
import { manualContentData } from "@/Cabinet/assets/data/ManualContent";
+import { ContentStatusStylesMap } from "@/Cabinet/assets/data/maps";
import { ReactComponent as ManualPeopleImg } from "@/Cabinet/assets/images/manualPeople.svg";
import { ReactComponent as MoveBtnImg } from "@/Cabinet/assets/images/moveButton.svg";
import ContentStatus from "@/Cabinet/types/enum/content.status.enum";
-interface MaunalContentBoxProps {
+interface ManualContentBoxProps {
contentStatus: ContentStatus;
}
-const MaunalContentBox = ({ contentStatus }: MaunalContentBoxProps) => {
+const ManualContentBox = ({ contentStatus }: ManualContentBoxProps) => {
const contentData = manualContentData[contentStatus];
return (
-
@@ -23,15 +24,13 @@ const MaunalContentBox = ({ contentStatus }: MaunalContentBoxProps) => {
contentData.iconComponent && (
)}
+
- {contentStatus === ContentStatus.IN_SESSION &&
- contentData.iconComponent && (
-
- )}
{contentData.contentTitle}
+
-
+
);
};
@@ -41,7 +40,7 @@ const Rotation = keyframes`
}
`;
-const MaunalContentBoxStyled = styled.div<{
+const ManualContentBoxStyled = styled.div<{
background: string;
contentStatus: ContentStatus;
}>`
@@ -59,12 +58,14 @@ const MaunalContentBoxStyled = styled.div<{
font-weight: bold;
cursor: pointer;
+ ${(props) => ContentStatusStylesMap[props.contentStatus]}
+
.clockImg {
width: 35px;
margin-right: 10px;
margin-top: 160px;
animation: ${Rotation} 1s linear infinite;
- stroke: var(--sys-main-color);
+ stroke: var(--sys-default-main-color);
}
.contentImg {
@@ -73,8 +74,8 @@ const MaunalContentBoxStyled = styled.div<{
& > path {
stroke: ${(props) =>
- props.contentStatus === ContentStatus.EXTENSION
- ? "var(--normal-text-color)"
+ props.contentStatus === ContentStatus.COIN
+ ? "var(--sys-default-main-color)"
: "var(--white-text-with-bg-color)"};
}
}
@@ -86,44 +87,17 @@ const MaunalContentBoxStyled = styled.div<{
position: absolute;
right: 100px;
bottom: 30px;
- fill: var(--sys-main-color);
+ fill: var(--sys-def-main-color);
}
- ${({ contentStatus }) =>
- contentStatus === ContentStatus.PENDING &&
- css`
- border: 5px double var(--sys-main-color);
- box-shadow: inset 0px 0px 0px 5px var(--bg-color);
- `}
-
- ${({ contentStatus }) =>
- contentStatus === ContentStatus.IN_SESSION &&
- css`
- border: 5px solid var(--sys-main-color);
- color: var(--sys-main-color);
- `}
-
- ${({ contentStatus }) =>
- contentStatus === ContentStatus.EXTENSION &&
- css`
- width: 900px;
- color: var(--normal-text-color);
- @media screen and (max-width: 1000px) {
- width: 280px;
- .peopleImg {
- display: none;
- }
- font-size: 21px;
- }
- `}
-
- p {
+ p {
margin-top: 90px;
${({ contentStatus }) =>
(contentStatus === ContentStatus.PENDING ||
+ contentStatus === ContentStatus.COIN ||
contentStatus === ContentStatus.IN_SESSION) &&
css`
- margin-top: 160px;
+ color: var(--sys-default-main-color);
`}
}
@@ -134,34 +108,42 @@ const MaunalContentBoxStyled = styled.div<{
right: 35px;
bottom: 35px;
stroke: ${(props) =>
- props.contentStatus === ContentStatus.IN_SESSION
- ? "var(--sys-main-color)"
+ props.contentStatus === ContentStatus.COIN
+ ? "var(--sys-default-main-color)"
: props.contentStatus === ContentStatus.EXTENSION
? "var(--normal-text-color)"
: "var(--white-text-with-bg-color)"};
cursor: pointer;
}
- :hover {
+ &:hover {
transition: all 0.3s ease-in-out;
${({ contentStatus }) =>
contentStatus === ContentStatus.PENDING
? css`
- border: 5px double var(--sys-main-color);
- box-shadow: inset 0px 0px 0px 5px var(--bg-color),
- 10px 10px 25px 0 var(--left-nav-border-shadow-color);
+ border: 5px double var(--sys-default-main-color);
+ box-shadow: inset 0px 0px 0px 5px var(--bg-color);
+ filter: drop-shadow(
+ 10px 10px 10px var(--left-nav-border-shadow-color)
+ );
`
+ : contentStatus === ContentStatus.STORE
+ ? css`` // No box-shadow or filter for STORE status
: css`
- box-shadow: 10px 10px 25px 0 var(--left-nav-border-shadow-color);
+ filter: drop-shadow(
+ 10px 10px 10px var(--left-nav-border-shadow-color)
+ );
`}
+
p {
transition: all 0.3s ease-in-out;
transform: translateY(-5px);
${({ contentStatus }) =>
(contentStatus === ContentStatus.PENDING ||
+ contentStatus === ContentStatus.COIN ||
contentStatus === ContentStatus.IN_SESSION) &&
css`
- margin-top: 155px;
+ color: var(--sys-default-main-color);
`}
}
.clockImg {
@@ -174,6 +156,11 @@ const MaunalContentBoxStyled = styled.div<{
const ContentTextStyled = styled.div`
display: flex;
align-items: center;
+
+ & > span {
+ font-weight: 400;
+ font-size: 1rem;
+ }
`;
-export default MaunalContentBox;
+export default ManualContentBox;
diff --git a/frontend/src/Cabinet/components/Home/ManualContentBoxStyles.ts b/frontend/src/Cabinet/components/Home/ManualContentBoxStyles.ts
new file mode 100644
index 000000000..99c3489d6
--- /dev/null
+++ b/frontend/src/Cabinet/components/Home/ManualContentBoxStyles.ts
@@ -0,0 +1,97 @@
+import { css } from "styled-components";
+
+export const extensionBoxStyles = css`
+ width: 900px;
+ color: var(--normal-text-color);
+ @media screen and (max-width: 1000px) {
+ width: 280px;
+ font-size: 21px;
+ }
+`;
+
+export const storeBoxStyles = css`
+ width: 620px;
+ height: 280px;
+ position: relative;
+ background: linear-gradient(
+ to bottom,
+ var(--ref-purple-400),
+ var(--ref-purple-600)
+ );
+ border-radius: 40px;
+ clip-path: path(
+ "M 0 163.33
+ A 23.33 23.33 1 0 0 0 116.67
+ L 0 0
+ L 396.56 0
+ L 413.354 15.67
+ L 430.148 0
+ L 620 0
+ L 620 280
+ L 430.148 280
+ L 413.354 264.33
+ L 396.56 280
+ L 0 280
+ Z"
+ );
+ /* Explanation of path:
+ - M 0 175: Move to (0, 175)
+ - A 25 25 1 0 0 0 125: Draw an arc with radius 25, starting from (0, 175) to (0, 125) // radius-x, radius-y, x-axis-rotation, large-arc-flag, sweep-flag, x, y
+ - L 0 0: Draw a line from (0, 125) to (0, 0)
+ - L 396.56 0: Draw a line from (0, 0) to (396.56, 0)
+ - L 413.354 16.794: Draw a line from (396.56, 0) to (413.354, 16.794)
+ - L 430.148 0: Draw a line from (413.354, 16.794) to (430.148, 0)
+ - L 620 0: Draw a line from (430.148, 0) to (620, 0)
+ - L 620 300: Draw a line from (620, 0) to (620, 300)
+ - L 430.148 300: Draw a line from (620, 300) to (430.148, 300)
+ - L 413.354 283.206: Draw a line from (430.148, 300) to (413.354, 283.206)
+ - L 396.56 300: Draw a line from (413.354, 283.206) to (396.56, 300)
+ - L 0 300: Draw a line from (396.56, 300) to (0, 300)
+ - Z: Close the path
+ */
+ &:after {
+ content: "";
+ position: absolute;
+ top: 25px;
+ right: 32.99%; /* 2/3 point */
+ height: 100%;
+ width: 4px;
+ background-image: linear-gradient(
+ to bottom,
+ white 33%,
+ rgba(255, 255, 255, 0) 0%
+ );
+ background-position: right;
+ background-size: 10px 30px;
+ background-repeat: repeat-y;
+ }
+ @media screen and (max-width: 1100px) {
+ width: 280px;
+ font-size: 21px;
+ clip-path: none;
+
+ &:after {
+ display: none;
+ }
+ }
+`;
+
+export const coinBoxStyles = css`
+ border: 5px solid var(--sys-default-main-color);
+ color: var(--sys-main-color);
+`;
+
+export const pendingBoxStyles = css`
+ border: 6px double var(--sys-main-color);
+ box-shadow: inset 0px 0px 0px 5px var(--bg-color);
+`;
+
+export const inSessionBoxStyles = css`
+ border: 5px solid var(--sys-main-color);
+ color: var(--sys-main-color);
+`;
+
+export const privateBoxStyles = css`
+ /* border: 5px solid var(--sys-main-color);
+ color: var(--sys-main-color); */
+`;
diff --git a/frontend/src/Cabinet/components/Home/ServiceManual.tsx b/frontend/src/Cabinet/components/Home/ServiceManual.tsx
index 94f766f70..8416dd658 100644
--- a/frontend/src/Cabinet/components/Home/ServiceManual.tsx
+++ b/frontend/src/Cabinet/components/Home/ServiceManual.tsx
@@ -1,7 +1,8 @@
import { useState } from "react";
import styled from "styled-components";
-import MaunalContentBox from "@/Cabinet/components/Home/ManualContentBox";
+import ManualContentBox from "@/Cabinet/components/Home/ManualContentBox";
import ManualModal from "@/Cabinet/components/Modals/ManualModal/ManualModal";
+import { ReactComponent as LinkImg } from "@/Cabinet/assets/images/link.svg";
import ContentStatus from "@/Cabinet/types/enum/content.status.enum";
const ServiceManual = ({
@@ -20,7 +21,7 @@ const ServiceManual = ({
};
const openNotionLink = () => {
- window.open("https://cabi.oopy.io/0bbb08a2-241c-444b-8a96-6b33c3796451");
+ window.open("https://cabi.oopy.io/115f29ec-ef8e-4748-a8a6-0d0341def33c");
};
return (
@@ -30,68 +31,60 @@ const ServiceManual = ({
Cabi 이용 안내서
- 상세보기
+ 상세보기
+
- 가능성의 확장
+ 당신의 사물함
- 개인, 공유, 동아리 사물함.
+ 당신의 방식으로,
+
openModal(ContentStatus.PRIVATE)}
+ onClick={() => openModal(ContentStatus.COIN)}
>
-
-
- openModal(ContentStatus.SHARE)}
- >
-
-
- openModal(ContentStatus.CLUB)}
- >
-
+
+ new
+
+ openModal(ContentStatus.STORE)}
+ >
+
+ new
+
+
+
- 공정한 대여를 위한
+ 가능성의 확장
- 새로운 사물함 서비스.
+ 개인, 공유, 동아리 사물함.
openModal(ContentStatus.PENDING)}
+ onClick={() => openModal(ContentStatus.PRIVATE)}
>
-
- new
+
openModal(ContentStatus.IN_SESSION)}
+ onClick={() => openModal(ContentStatus.SHARE)}
>
-
- new
+
-
-
- 사물함을 더 오래
-
- 사용할 수 있는 방법.
-
-
openModal(ContentStatus.EXTENSION)}
+ onClick={() => openModal(ContentStatus.CLUB)}
>
-
+
@@ -107,6 +100,15 @@ const ServiceManual = ({
);
};
+const TicketWrapperStyled = styled.div`
+ width: 620px;
+ &:hover {
+ transition: all 0.3s ease-in-out;
+ transform: translateY(-5px);
+ filter: drop-shadow(10px 10px 10px var(--left-nav-border-shadow-color));
+ }
+`;
+
const WrapperStyled = styled.div`
display: flex;
flex-direction: column;
@@ -148,9 +150,30 @@ const NotionBtn = styled.button`
color: var(--notion-btn-text-color);
background: var(--bg-color);
border: 1px solid var(--line-color);
- :hover {
- color: var(--normal-text-color);
- font-weight: 400;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ @media (hover: hover) and (pointer: fine) {
+ &:hover {
+ color: var(--normal-text-color);
+ font-weight: 400;
+
+ #linknImg > path {
+ stroke: var(--normal-text-color);
+ stroke-width: 1.2px;
+ }
+ }
+ }
+
+ & > span {
+ line-height: 14px;
+ height: 16px;
+ }
+
+ & > #linknImg {
+ width: 12px;
+ height: 12px;
+ margin-left: 4px;
}
`;
diff --git a/frontend/src/Cabinet/components/ItemLog/AdminItemProvideLog.container.tsx b/frontend/src/Cabinet/components/ItemLog/AdminItemProvideLog.container.tsx
index 1cca6cf96..388d18a46 100644
--- a/frontend/src/Cabinet/components/ItemLog/AdminItemProvideLog.container.tsx
+++ b/frontend/src/Cabinet/components/ItemLog/AdminItemProvideLog.container.tsx
@@ -2,7 +2,6 @@ import { useEffect, useState } from "react";
import AdminItemProvideLog from "@/Cabinet/components/ItemLog/AdminItemProvideLog";
import { ItemLogResponseType } from "@/Cabinet/types/dto/admin.dto";
import useMenu from "@/Cabinet/hooks/useMenu";
-import { STATUS_400_BAD_REQUEST } from "@/Cabinet/constants/StatusCode";
const AdminItemProvideLogContainer = () => {
const { closeStore } = useMenu();
diff --git a/frontend/src/Cabinet/components/ItemLog/ItemLogTable/AdminItemLogTable.tsx b/frontend/src/Cabinet/components/ItemLog/ItemLogTable/AdminItemLogTable.tsx
index f406f572c..f50767083 100644
--- a/frontend/src/Cabinet/components/ItemLog/ItemLogTable/AdminItemLogTable.tsx
+++ b/frontend/src/Cabinet/components/ItemLog/ItemLogTable/AdminItemLogTable.tsx
@@ -1,8 +1,8 @@
+import { HttpStatusCode } from "axios";
import styled from "styled-components";
import LoadingAnimation from "@/Cabinet/components/Common/LoadingAnimation";
import { ItemLogResponseType } from "@/Cabinet/types/dto/admin.dto";
import { formatDate } from "@/Cabinet/utils/dateUtils";
-import { STATUS_400_BAD_REQUEST } from "@/Cabinet/constants/StatusCode";
const AdminItemLogTable = ({ itemLog }: { itemLog: ItemLogResponseType }) => {
if (!itemLog) return ;
@@ -16,7 +16,7 @@ const AdminItemLogTable = ({ itemLog }: { itemLog: ItemLogResponseType }) => {
사용일
- {itemLog !== STATUS_400_BAD_REQUEST &&
+ {itemLog !== HttpStatusCode.BadRequest &&
Array.isArray(itemLog.itemHistories) && (
{itemLog.itemHistories.map(
@@ -47,7 +47,7 @@ const AdminItemLogTable = ({ itemLog }: { itemLog: ItemLogResponseType }) => {
)}
- {(itemLog === STATUS_400_BAD_REQUEST ||
+ {(itemLog === HttpStatusCode.BadRequest ||
itemLog.totalLength === undefined ||
itemLog.totalLength === 0) && (
아이템 내역이 없습니다.
diff --git a/frontend/src/Cabinet/components/ItemLog/ItemLogTable/AdminItemProvideTable.tsx b/frontend/src/Cabinet/components/ItemLog/ItemLogTable/AdminItemProvideTable.tsx
index cdb30a9fe..098417faa 100644
--- a/frontend/src/Cabinet/components/ItemLog/ItemLogTable/AdminItemProvideTable.tsx
+++ b/frontend/src/Cabinet/components/ItemLog/ItemLogTable/AdminItemProvideTable.tsx
@@ -1,8 +1,8 @@
+import { HttpStatusCode } from "axios";
import styled from "styled-components";
import LoadingAnimation from "@/Cabinet/components/Common/LoadingAnimation";
import { ItemLogResponseType } from "@/Cabinet/types/dto/admin.dto";
import { formatDate } from "@/Cabinet/utils/dateUtils";
-import { STATUS_400_BAD_REQUEST } from "@/Cabinet/constants/StatusCode";
const AdminItemProvideTable = ({
itemLog,
@@ -20,7 +20,7 @@ const AdminItemProvideTable = ({
아이템
- {itemLog !== STATUS_400_BAD_REQUEST && (
+ {itemLog !== HttpStatusCode.BadRequest && (
{itemLog.itemHistories.map(
({ issuedDate, itemName, itemDetails, usedAt }, idx) => (
@@ -47,7 +47,7 @@ const AdminItemProvideTable = ({
)}
- {itemLog === STATUS_400_BAD_REQUEST && (
+ {itemLog === HttpStatusCode.BadRequest && (
아이템 사용기록이 없습니다.
)}
diff --git a/frontend/src/Cabinet/components/LeftNav/LeftMainNav/LeftMainNav.container.tsx b/frontend/src/Cabinet/components/LeftNav/LeftMainNav/LeftMainNav.container.tsx
index f5ed614ab..0f99c12f3 100644
--- a/frontend/src/Cabinet/components/LeftNav/LeftMainNav/LeftMainNav.container.tsx
+++ b/frontend/src/Cabinet/components/LeftNav/LeftMainNav/LeftMainNav.container.tsx
@@ -10,6 +10,7 @@ import {
currentBuildingNameState,
currentFloorCabinetState,
currentFloorNumberState,
+ currentFloorSectionNamesState,
currentMapFloorState,
currentSectionNameState,
isCurrentSectionRenderState,
@@ -52,6 +53,8 @@ const LeftMainNavContainer = ({ isAdmin }: { isAdmin?: boolean }) => {
const setSelectedTypeOnSearch = useSetRecoilState(
selectedTypeOnSearchState
);
+ const [currentFloorSectionNames, setCurrentFloorSectionNames] =
+ useRecoilState(currentFloorSectionNamesState);
useEffect(() => {
if (currentFloor === undefined) {
@@ -64,6 +67,7 @@ const LeftMainNavContainer = ({ isAdmin }: { isAdmin?: boolean }) => {
const sections = response.data.map(
(data: CabinetInfoByBuildingFloorDto) => data.section
);
+ setCurrentFloorSectionNames(sections);
let currentSectionFromPersist = undefined;
const recoilPersist = localStorage.getItem("recoil-persist");
if (recoilPersist) {
@@ -72,6 +76,7 @@ const LeftMainNavContainer = ({ isAdmin }: { isAdmin?: boolean }) => {
currentSectionFromPersist = recoilPersistObj.CurrentSection;
}
}
+
currentSectionFromPersist &&
sections.includes(currentSectionFromPersist)
? setCurrentSection(currentSectionFromPersist)
diff --git a/frontend/src/Cabinet/components/LeftNav/LeftProfileNav/LeftProfileNav.tsx b/frontend/src/Cabinet/components/LeftNav/LeftProfileNav/LeftProfileNav.tsx
index cc18f9c29..c1184208b 100644
--- a/frontend/src/Cabinet/components/LeftNav/LeftProfileNav/LeftProfileNav.tsx
+++ b/frontend/src/Cabinet/components/LeftNav/LeftProfileNav/LeftProfileNav.tsx
@@ -107,10 +107,10 @@ const SectionLinkStyled = styled.div`
@media (hover: hover) and (pointer: fine) {
&:hover {
color: var(--sys-main-color);
- }
- &:hover img {
- filter: invert(33%) sepia(55%) saturate(3554%) hue-rotate(230deg)
- brightness(99%) contrast(107%);
+
+ #linknImg > path {
+ stroke: var(--sys-main-color);
+ }
}
}
`;
diff --git a/frontend/src/Cabinet/components/LentLog/AdminCabinetLentLog.container.tsx b/frontend/src/Cabinet/components/LentLog/AdminCabinetLentLog.container.tsx
index d001b3cae..486c08a5c 100644
--- a/frontend/src/Cabinet/components/LentLog/AdminCabinetLentLog.container.tsx
+++ b/frontend/src/Cabinet/components/LentLog/AdminCabinetLentLog.container.tsx
@@ -1,3 +1,4 @@
+import { HttpStatusCode } from "axios";
import { useEffect, useState } from "react";
import { useRecoilValue } from "recoil";
import { currentCabinetIdState } from "@/Cabinet/recoil/atoms";
@@ -5,7 +6,6 @@ import AdminCabinetLentLog from "@/Cabinet/components/LentLog/AdminCabinetLentLo
import { LentLogResponseType } from "@/Cabinet/types/dto/lent.dto";
import { axiosGetCabinetLentLog } from "@/Cabinet/api/axios/axios.custom";
import useMenu from "@/Cabinet/hooks/useMenu";
-import { STATUS_400_BAD_REQUEST } from "@/Cabinet/constants/StatusCode";
const AdminCabinetLentLogContainer = () => {
const { closeLent } = useMenu();
@@ -20,7 +20,7 @@ const AdminCabinetLentLogContainer = () => {
setTotalPage(Math.ceil(result.data.totalLength / 10));
setLogs(result.data.result);
} catch {
- setLogs(STATUS_400_BAD_REQUEST);
+ setLogs(HttpStatusCode.BadRequest);
setTotalPage(1);
}
}
diff --git a/frontend/src/Cabinet/components/LentLog/AdminUserLentLog.container.tsx b/frontend/src/Cabinet/components/LentLog/AdminUserLentLog.container.tsx
index 637e1cc8a..07ae9a158 100644
--- a/frontend/src/Cabinet/components/LentLog/AdminUserLentLog.container.tsx
+++ b/frontend/src/Cabinet/components/LentLog/AdminUserLentLog.container.tsx
@@ -1,3 +1,4 @@
+import { HttpStatusCode } from "axios";
import { useEffect, useState } from "react";
import { useRecoilValue } from "recoil";
import { targetUserInfoState } from "@/Cabinet/recoil/atoms";
@@ -5,7 +6,6 @@ import AdminUserLentLog from "@/Cabinet/components/LentLog/AdminUserLentLog";
import { LentLogResponseType } from "@/Cabinet/types/dto/lent.dto";
import { axiosGetUserLentLog } from "@/Cabinet/api/axios/axios.custom";
import useMenu from "@/Cabinet/hooks/useMenu";
-import { STATUS_400_BAD_REQUEST } from "@/Cabinet/constants/StatusCode";
const AdminUserLentLogContainer = () => {
const { closeLent } = useMenu();
@@ -20,7 +20,7 @@ const AdminUserLentLogContainer = () => {
setTotalPage(Math.ceil(result.data.totalLength / 10));
setLogs(result.data.result);
} catch {
- setLogs(STATUS_400_BAD_REQUEST);
+ setLogs(HttpStatusCode.BadRequest);
setTotalPage(1);
}
}
diff --git a/frontend/src/Cabinet/components/LentLog/LentLog.container.tsx b/frontend/src/Cabinet/components/LentLog/LentLog.container.tsx
index 7ebed068b..45f66a218 100644
--- a/frontend/src/Cabinet/components/LentLog/LentLog.container.tsx
+++ b/frontend/src/Cabinet/components/LentLog/LentLog.container.tsx
@@ -1,10 +1,10 @@
+import { HttpStatusCode } from "axios";
import { useEffect, useState } from "react";
import LentLog from "@/Cabinet/components/LentLog/LentLog";
import { LentLogResponseType } from "@/Cabinet/types/dto/lent.dto";
import { axiosMyLentLog } from "@/Cabinet/api/axios/axios.custom";
import useMenu from "@/Cabinet/hooks/useMenu";
import { getTotalPage } from "@/Cabinet/utils/paginationUtils";
-import { STATUS_400_BAD_REQUEST } from "@/Cabinet/constants/StatusCode";
const LentLogContainer = () => {
const { closeLent } = useMenu();
@@ -17,7 +17,7 @@ const LentLogContainer = () => {
setTotalPage(getTotalPage(result.data.totalLength, 10));
setLogs(result.data.result);
} catch {
- setLogs(STATUS_400_BAD_REQUEST);
+ setLogs(HttpStatusCode.BadRequest);
}
}
useEffect(() => {
diff --git a/frontend/src/Cabinet/components/LentLog/LogTable/AdminCabinetLogTable.tsx b/frontend/src/Cabinet/components/LentLog/LogTable/AdminCabinetLogTable.tsx
index 2208bc57c..f4c09b9c5 100644
--- a/frontend/src/Cabinet/components/LentLog/LogTable/AdminCabinetLogTable.tsx
+++ b/frontend/src/Cabinet/components/LentLog/LogTable/AdminCabinetLogTable.tsx
@@ -1,8 +1,8 @@
+import { HttpStatusCode } from "axios";
import styled from "styled-components";
import LoadingAnimation from "@/Cabinet/components/Common/LoadingAnimation";
import { LentLogResponseType } from "@/Cabinet/types/dto/lent.dto";
import { formatDate } from "@/Cabinet/utils/dateUtils";
-import { STATUS_400_BAD_REQUEST } from "@/Cabinet/constants/StatusCode";
const AdminCabinetLogTable = ({
lentLog,
@@ -21,7 +21,7 @@ const AdminCabinetLogTable = ({
반납일
- {lentLog !== STATUS_400_BAD_REQUEST && (
+ {lentLog !== HttpStatusCode.BadRequest && (
{lentLog.map(
({ floor, section, name, startedAt, endedAt }, idx) => (
@@ -45,7 +45,7 @@ const AdminCabinetLogTable = ({
)}
- {(lentLog === STATUS_400_BAD_REQUEST || lentLog.length === 0) && (
+ {(lentLog === HttpStatusCode.BadRequest || lentLog.length === 0) && (
대여기록이 없습니다.
)}
diff --git a/frontend/src/Cabinet/components/LentLog/LogTable/LogTable.tsx b/frontend/src/Cabinet/components/LentLog/LogTable/LogTable.tsx
index 9aa25e3f8..47b0d1b9b 100644
--- a/frontend/src/Cabinet/components/LentLog/LogTable/LogTable.tsx
+++ b/frontend/src/Cabinet/components/LentLog/LogTable/LogTable.tsx
@@ -1,8 +1,8 @@
+import { HttpStatusCode } from "axios";
import styled from "styled-components";
import LoadingAnimation from "@/Cabinet/components/Common/LoadingAnimation";
import { LentLogResponseType } from "@/Cabinet/types/dto/lent.dto";
import { formatDate } from "@/Cabinet/utils/dateUtils";
-import { STATUS_400_BAD_REQUEST } from "@/Cabinet/constants/StatusCode";
const LogTable = ({ lentHistory }: { lentHistory: LentLogResponseType }) => {
if (lentHistory === undefined) return ;
@@ -17,7 +17,7 @@ const LogTable = ({ lentHistory }: { lentHistory: LentLogResponseType }) => {
반납일
- {lentHistory !== STATUS_400_BAD_REQUEST && (
+ {lentHistory !== HttpStatusCode.BadRequest && (
{lentHistory.map(
({ floor, section, visibleNum, startedAt, endedAt }, idx) => (
@@ -43,7 +43,7 @@ const LogTable = ({ lentHistory }: { lentHistory: LentLogResponseType }) => {
)}
- {lentHistory === STATUS_400_BAD_REQUEST ||
+ {lentHistory === HttpStatusCode.BadRequest ||
(lentHistory.length === 0 && (
대여기록이 없습니다.
))}
diff --git a/frontend/src/Cabinet/components/MapInfo/MapGrid/MapGrid.tsx b/frontend/src/Cabinet/components/MapInfo/MapGrid/MapGrid.tsx
index 1f7c894d7..889128910 100644
--- a/frontend/src/Cabinet/components/MapInfo/MapGrid/MapGrid.tsx
+++ b/frontend/src/Cabinet/components/MapInfo/MapGrid/MapGrid.tsx
@@ -16,6 +16,7 @@ const MapGrid = ({ floor }: { floor: number }) => {
setIsCurrentSectionRender(true);
setSection(section);
};
+
return (
{floor &&
diff --git a/frontend/src/Cabinet/components/Modals/LentModal/LentModal.tsx b/frontend/src/Cabinet/components/Modals/LentModal/LentModal.tsx
index 614cfaafa..556af4a8e 100644
--- a/frontend/src/Cabinet/components/Modals/LentModal/LentModal.tsx
+++ b/frontend/src/Cabinet/components/Modals/LentModal/LentModal.tsx
@@ -46,7 +46,9 @@ const LentModal: React.FC<{
const formattedExpireDate = getExpireDateString(props.lentType);
const privateLentDetail = `대여기간은 ${formattedExpireDate} 23:59 까지 입니다.
- 귀중품 분실 및 메모 내용의 유출에 책임지지 않습니다.`;
+ 귀중품 분실 및 메모 내용의 유출에 책임지지 않습니다.
+ 3주(21일) 이상 연체 시 사물함은 강제 반납되며
+ 미회수된 개인 물품은 폐기될 수 있습니다.`;
const shareLentDetail = `대여 후 ${
10
// import.meta.env.VITE_SHARE_LENT_COUNTDOWN // TODO: .env 에 등록하기
@@ -54,7 +56,9 @@ const LentModal: React.FC<{
공유 인원 (2인~4인) 이 충족되지 않으면,
공유 사물함의 대여가 취소됩니다.
“메모 내용”은 공유 인원끼리 공유됩니다.
- 귀중품 분실 및 메모 내용의 유출에 책임지지 않습니다.`;
+ 귀중품 분실 및 메모 내용의 유출에 책임지지 않습니다.
+ 3주(21일) 이상 연체 시 사물함은 강제 반납되며
+ 미회수된 개인 물품은 폐기될 수 있습니다.`;
const tryLentRequest = async (e: React.MouseEvent) => {
setIsLoading(true);
try {
diff --git a/frontend/src/Cabinet/components/Modals/ManualModal/ManualModal.tsx b/frontend/src/Cabinet/components/Modals/ManualModal/ManualModal.tsx
index 494d11383..a238f8fb1 100644
--- a/frontend/src/Cabinet/components/Modals/ManualModal/ManualModal.tsx
+++ b/frontend/src/Cabinet/components/Modals/ManualModal/ManualModal.tsx
@@ -1,9 +1,13 @@
import React from "react";
import { useState } from "react";
import styled, { keyframes } from "styled-components";
-import { manualContentData } from "@/Cabinet/assets/data/ManualContent";
+import {
+ manualContentData,
+ manualItemsData,
+} from "@/Cabinet/assets/data/ManualContent";
import { ReactComponent as MoveBtnImg } from "@/Cabinet/assets/images/moveButton.svg";
import ContentStatus from "@/Cabinet/types/enum/content.status.enum";
+import { StoreItemType } from "@/Cabinet/types/enum/store.enum";
interface ModalProps {
contentStatus: ContentStatus;
@@ -15,6 +19,9 @@ const ManualModal: React.FC = ({
setIsModalOpen,
}) => {
const [modalIsOpen, setModalIsOpen] = useState(true);
+ const [selectedItem, setSelectedItem] = useState(
+ StoreItemType.EXTENSION
+ );
const contentData = manualContentData[contentStatus];
const isCabinetType =
@@ -28,6 +35,10 @@ const ManualModal: React.FC = ({
contentStatus === ContentStatus.SHARE ||
contentStatus === ContentStatus.CLUB;
+ const handleIconClick = (index: StoreItemType) => {
+ setSelectedItem(index);
+ };
+
const closeModal = () => {
if (modalIsOpen) {
setModalIsOpen(false);
@@ -76,12 +87,40 @@ const ManualModal: React.FC = ({
)}
)}
- {contentData.contentTitle}
-
-
-
+ {contentStatus === ContentStatus.STORE && (
+ <>
+
+ {Object.entries(manualItemsData).map(([key, item]) => (
+ handleIconClick(key as StoreItemType)}
+ className={selectedItem === key ? "selected" : ""}
+ color={contentData.pointColor}
+ >
+
+
+ ))}
+
+ {manualItemsData[selectedItem].title}
+
+
+
+ >
+ )}
+ {contentStatus !== ContentStatus.STORE && (
+ <>
+ {contentData.contentTitle}
+
+
+
+ >
+ )}
@@ -144,9 +183,10 @@ const ModalWrapper = styled.div<{
border-radius: 40px 40px 0 0;
border: ${(props) =>
props.contentStatus === ContentStatus.PENDING
- ? "5px double var(--sys-main-color)"
- : props.contentStatus === ContentStatus.IN_SESSION
- ? "5px solid var(--sys-main-color)"
+ ? "5px double var(--sys-default-main-color)"
+ : props.contentStatus === ContentStatus.IN_SESSION ||
+ props.contentStatus === ContentStatus.COIN
+ ? "5px solid var(--sys-default-main-color)"
: "none"};
box-shadow: ${(props) =>
props.contentStatus === ContentStatus.PENDING &&
@@ -166,8 +206,9 @@ const ModalContent = styled.div<{
display: flex;
flex-direction: column;
color: ${(props) =>
- props.contentStatus === ContentStatus.IN_SESSION
- ? "var(--sys-main-color)"
+ props.contentStatus === ContentStatus.IN_SESSION ||
+ props.contentStatus === ContentStatus.COIN
+ ? "var(--sys-default-main-color)"
: props.contentStatus === ContentStatus.EXTENSION
? "var(--normal-text-color)"
: "var(--white-text-with-bg-color)"};
@@ -188,8 +229,9 @@ const ModalContent = styled.div<{
}
.moveButton {
stroke: ${(props) =>
- props.contentStatus === ContentStatus.IN_SESSION
- ? "var(--sys-main-color)"
+ props.contentStatus === ContentStatus.IN_SESSION ||
+ props.contentStatus === ContentStatus.COIN
+ ? "var(--sys-default-main-color)"
: props.contentStatus === ContentStatus.EXTENSION
? "var(--normal-text-color)"
: "var(--white-text-with-bg-color)"};
@@ -210,8 +252,9 @@ const CloseButton = styled.div<{
svg {
transform: scaleX(-1);
stroke: ${(props) =>
- props.contentStatus === ContentStatus.IN_SESSION
- ? "var(--sys-main-color)"
+ props.contentStatus === ContentStatus.IN_SESSION ||
+ props.contentStatus === ContentStatus.COIN
+ ? "var(--sys-default-main-color)"
: props.contentStatus === ContentStatus.EXTENSION
? "var(--normal-text-color)"
: "var(--bg-color)"};
@@ -269,7 +312,7 @@ const BoxInfo2 = styled.div`
}
`;
-const ManualContentStyeld = styled.div<{
+const ManualContentStyled = styled.div<{
color: string;
}>`
margin: 40px 0 0 20px;
@@ -330,4 +373,45 @@ const ContentImgStyled = styled.div<{
}
`;
+const ItemContentsStyled = styled.div`
+ width: 45%;
+ height: 90px;
+ display: flex;
+ margin-bottom: 30px;
+`;
+
+const ItemIconStyled = styled.div<{
+ color: string;
+}>`
+ width: 80px;
+ height: 80px;
+ margin-right: 10px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ & > svg {
+ padding: 4px;
+ width: 80px;
+ height: 80px;
+ cursor: pointer;
+ stroke-width: 50px;
+ & > path {
+ transform: scale(2);
+ stroke: var(--ref-purple-690);
+ }
+ }
+
+ &:hover:not(.selected),
+ &.selected > svg {
+ width: 80px;
+ height: 80px;
+ filter: drop-shadow(0px 5px 3px var(--hover-box-shadow-color));
+ transition: all 0.2s ease;
+ & > path {
+ stroke: ${(props) => props.color};
+ }
+ }
+`;
+
export default ManualModal;
diff --git a/frontend/src/Cabinet/components/Modals/Modal.tsx b/frontend/src/Cabinet/components/Modals/Modal.tsx
index a854f03a8..545b606bb 100644
--- a/frontend/src/Cabinet/components/Modals/Modal.tsx
+++ b/frontend/src/Cabinet/components/Modals/Modal.tsx
@@ -6,6 +6,7 @@ import Button from "@/Cabinet/components/Common/Button";
import { ReactComponent as CheckIcon } from "@/Cabinet/assets/images/checkIcon.svg";
import { ReactComponent as ErrorIcon } from "@/Cabinet/assets/images/errorIcon.svg";
import { ReactComponent as NotificationIcon } from "@/Cabinet/assets/images/notificationSign.svg";
+import useMenu from "@/Cabinet/hooks/useMenu";
import useMultiSelect from "@/Cabinet/hooks/useMultiSelect";
/**
@@ -63,6 +64,7 @@ const Modal: React.FC<{ modalContents: IModalContents }> = (props) => {
} = props.modalContents;
const { isMultiSelect, closeMultiSelectMode } = useMultiSelect();
const navigator = useNavigate();
+ const { closeAll } = useMenu();
return (
<>
@@ -127,6 +129,7 @@ const Modal: React.FC<{ modalContents: IModalContents }> = (props) => {
{url && urlTitle && (
{
+ closeAll();
navigator(url);
}}
>
diff --git a/frontend/src/Cabinet/components/Modals/ExtendModal/ExtendModal.tsx b/frontend/src/Cabinet/components/Modals/StoreModal/ExtendModal.tsx
similarity index 86%
rename from frontend/src/Cabinet/components/Modals/ExtendModal/ExtendModal.tsx
rename to frontend/src/Cabinet/components/Modals/StoreModal/ExtendModal.tsx
index 7ac32e373..74a2241c7 100644
--- a/frontend/src/Cabinet/components/Modals/ExtendModal/ExtendModal.tsx
+++ b/frontend/src/Cabinet/components/Modals/StoreModal/ExtendModal.tsx
@@ -22,6 +22,7 @@ import { IInventoryInfo } from "@/Cabinet/components/Store/Inventory/Inventory";
import { additionalModalType, modalPropsMap } from "@/Cabinet/assets/data/maps";
import { MyCabinetInfoResponseDto } from "@/Cabinet/types/dto/cabinet.dto";
import { IItemDetail, IItemStore } from "@/Cabinet/types/dto/store.dto";
+import CabinetStatus from "@/Cabinet/types/enum/cabinet.status.enum";
import IconType from "@/Cabinet/types/enum/icon.type.enum";
import {
axiosCabinetById,
@@ -45,11 +46,11 @@ const ExtendModal: React.FC<{
const [items, setItems] = useState([]);
const [myItems, setMyItems] = useState(null);
const [selectedOption, setSelectedOption] = useState("");
- // const [extensionItems, setExtensionItems] = useState([]);
const [myExtensionItems, setMyExtensionItems] = useState([]);
const [itemDropdownOptions, setItemDropdownOptions] = useState<
IDropdownOptions[]
>([]);
+ const [url, setUrl] = useState(null);
const [currentCabinetId] = useRecoilState(currentCabinetIdState);
const [myInfo, setMyInfo] = useRecoilState(userState);
const [myLentInfo, setMyLentInfo] =
@@ -74,8 +75,10 @@ const ExtendModal: React.FC<{
연장권 사용은 취소할 수 없습니다.`;
const extendInfoDetail = `사물함을 대여하시면 연장권 사용이 가능합니다.
연장권은 ${extensionExpiredDate} 23:59 이후 만료됩니다.`;
- const noExtension = `현재 연장권을 보유하고 있지 않습니다.
+ const noItemMsg = `현재 연장권을 보유하고 있지 않습니다.
연장권은 까비 상점에서 구매하실 수 있습니다.`;
+ const overdueMsg = "연체 중에는 연장권을 사용하실 수 없습니다.";
+ const defaultFailureModalTitle = "연장권 사용실패";
useEffect(() => {
fetchData();
@@ -85,7 +88,7 @@ const ExtendModal: React.FC<{
if (myItems?.extensionItems.length === 0) {
setShowResponseModal(true);
setHasErrorOnResponse(true);
- setModalContents(noExtension);
+ setModalContents(noItemMsg);
} else {
setShowResponseModal(false);
setHasErrorOnResponse(false);
@@ -97,22 +100,21 @@ const ExtendModal: React.FC<{
}
if (items.length) {
const sortedItems = sortItems(items);
- const dropdownOptions: IDropdownOptions[] = getItemDropDownOption(sortedItems[0]);
+ const dropdownOptions: IDropdownOptions[] = getItemDropDownOption(
+ sortedItems[0]
+ );
-// 새로운 항목 생성
-const newOption = {
- name: "출석 연장권 보상",
- value: "EXTENSION_PREV",
- isDisabled: findMyItem("EXTENSION_PREV"),
-};
+ const extensionPrevOption = {
+ name: "출석 연장권 보상",
+ value: "EXTENSION_PREV",
+ isDisabled: findMyItem("EXTENSION_PREV"),
+ };
-// 새로운 항목을 dropdownOptions 배열의 마지막에 추가
-dropdownOptions.push(newOption);
+ dropdownOptions.push(extensionPrevOption);
- // setExtensionItems(sortedItems[0].items);
setItemDropdownOptions(dropdownOptions);
-}
-}, [myItems]);
+ }
+ }, [myItems]);
const fetchData = async () => {
try {
@@ -128,10 +130,9 @@ dropdownOptions.push(newOption);
};
const findMyItem = (period: string) => {
- return !myItems?.extensionItems.some((item) => item.itemSku === period);
+ return !myItems?.extensionItems.some((item) => item.itemSku === period);
};
-
const getItemDropDownOption = (curItem: IItemDetail): IDropdownOptions[] => {
if (curItem) {
return curItem.items.map((item) => ({
@@ -143,7 +144,6 @@ dropdownOptions.push(newOption);
return [];
};
- // Modal related functions
const getModalTitle = (cabinetId: number | null) => {
return cabinetId === null
? modalPropsMap[additionalModalType.MODAL_OWN_EXTENSION].title
@@ -191,7 +191,15 @@ dropdownOptions.push(newOption);
const extensionItemUse = async (item: string) => {
if (currentCabinetId === 0 || myInfo.cabinetId === null) {
setHasErrorOnResponse(true);
- setModalTitle("현재 대여중인 사물함이 없습니다.");
+ setModalTitle(defaultFailureModalTitle);
+ setModalContents("현재 대여중인 사물함이 없습니다.");
+ setShowResponseModal(true);
+ return;
+ }
+ if (myLentInfo.status === CabinetStatus.OVERDUE) {
+ setHasErrorOnResponse(true);
+ setModalTitle(defaultFailureModalTitle);
+ setModalContents(overdueMsg);
setShowResponseModal(true);
return;
}
@@ -218,8 +226,12 @@ dropdownOptions.push(newOption);
} catch (error: any) {
setHasErrorOnResponse(true);
if (error.response.status === 400) {
- setModalTitle("연장권 사용실패");
- setModalContents(noExtension);
+ setModalTitle(defaultFailureModalTitle);
+ setModalContents(noItemMsg);
+ setUrl("/store");
+ } else if (error.response.status === 403) {
+ setModalTitle(defaultFailureModalTitle);
+ setModalContents(overdueMsg);
} else {
setModalTitle(error.response?.data.message || error.data.message);
}
@@ -263,7 +275,7 @@ dropdownOptions.push(newOption);
modalTitle={modalTitle}
modalContents={modalContents}
closeModal={props.onClose}
- url={"/store"}
+ url={url}
urlTitle={"까비상점으로 이동"}
/>
) : (
diff --git a/frontend/src/Cabinet/components/Modals/PenaltyModal/PenaltyModal.tsx b/frontend/src/Cabinet/components/Modals/StoreModal/PenaltyModal.tsx
similarity index 98%
rename from frontend/src/Cabinet/components/Modals/PenaltyModal/PenaltyModal.tsx
rename to frontend/src/Cabinet/components/Modals/StoreModal/PenaltyModal.tsx
index 65d503de0..952ac7baf 100644
--- a/frontend/src/Cabinet/components/Modals/PenaltyModal/PenaltyModal.tsx
+++ b/frontend/src/Cabinet/components/Modals/StoreModal/PenaltyModal.tsx
@@ -12,13 +12,13 @@ import {
FailResponseModal,
SuccessResponseModal,
} from "@/Cabinet/components/Modals/ResponseModal/ResponseModal";
+import { IInventoryInfo } from "@/Cabinet/components/Store/Inventory/Inventory";
import {
IItemDetail,
IItemTimeRemaining,
IStoreItem,
} from "@/Cabinet/types/dto/store.dto";
import { UserDto } from "@/Cabinet/types/dto/user.dto";
-import { StorePenaltyType } from "@/Cabinet/types/enum/store.enum";
import {
axiosItems,
axiosMyInfo,
@@ -26,7 +26,6 @@ import {
axiosUseItem,
} from "@/Cabinet/api/axios/axios.custom";
import { formatDate, formatDateTime } from "@/Cabinet/utils/dateUtils";
-import { IInventoryInfo } from "../../Store/Inventory/Inventory";
interface PenaltyModalProps {
onClose: () => void;
@@ -187,8 +186,6 @@ const PenaltyModal: React.FC = ({
}
};
-
-
const modalContents: IModalContents = {
type: "hasProceedBtn",
iconType: "CHECK",
diff --git a/frontend/src/Cabinet/components/Modals/SectionAlertModal/SectionAlertModal.tsx b/frontend/src/Cabinet/components/Modals/StoreModal/SectionAlertModal.tsx
similarity index 100%
rename from frontend/src/Cabinet/components/Modals/SectionAlertModal/SectionAlertModal.tsx
rename to frontend/src/Cabinet/components/Modals/StoreModal/SectionAlertModal.tsx
diff --git a/frontend/src/Cabinet/components/Modals/SwapModal/SwapModal.tsx b/frontend/src/Cabinet/components/Modals/StoreModal/SwapModal.tsx
similarity index 97%
rename from frontend/src/Cabinet/components/Modals/SwapModal/SwapModal.tsx
rename to frontend/src/Cabinet/components/Modals/StoreModal/SwapModal.tsx
index 7eaaee11e..3d6afba32 100644
--- a/frontend/src/Cabinet/components/Modals/SwapModal/SwapModal.tsx
+++ b/frontend/src/Cabinet/components/Modals/StoreModal/SwapModal.tsx
@@ -16,10 +16,10 @@ import {
import { modalPropsMap } from "@/Cabinet/assets/data/maps";
import { MyCabinetInfoResponseDto } from "@/Cabinet/types/dto/cabinet.dto";
import IconType from "@/Cabinet/types/enum/icon.type.enum";
-import { axiosUseItem } from "@/Cabinet/api/axios/axios.custom";
import {
axiosCabinetById,
axiosMyLentInfo,
+ axiosUseItem,
} from "@/Cabinet/api/axios/axios.custom";
const SwapModal: React.FC<{
@@ -74,7 +74,7 @@ const SwapModal: React.FC<{
}
} catch (error: any) {
setModalTitle("이사권 사용실패");
- if (error.response.ststus === 400) {
+ if (error.response.status === 400) {
setModalContent(
"현재 이사권을 보유하고 있지 않습니다.\n이사권은 까비상점에서 구매하실 수 있습니다."
);
diff --git a/frontend/src/Cabinet/components/Search/SearchCabinetDetails.tsx b/frontend/src/Cabinet/components/Search/SearchCabinetDetails.tsx
index 8861c7450..b092bb807 100644
--- a/frontend/src/Cabinet/components/Search/SearchCabinetDetails.tsx
+++ b/frontend/src/Cabinet/components/Search/SearchCabinetDetails.tsx
@@ -49,9 +49,7 @@ const SearchCabinetDetails = (props: ISearchDetail) => {
);
const { openCabinet, closeCabinet } = useMenu();
const CabinetIcon =
- cabinetIconComponentMap[
- cabinetInfo?.lentType || CabinetType.PRIVATE
- ];
+ cabinetIconComponentMap[cabinetInfo?.lentType || CabinetType.PRIVATE];
const clickSearchItem = () => {
if (
@@ -150,7 +148,6 @@ const SearchCabinetDetails = (props: ISearchDetail) => {
);
};
-
const WrapperStyled = styled.div`
width: 350px;
height: 110px;
@@ -252,4 +249,3 @@ const ButtonWrapper = styled.div`
`;
export default SearchCabinetDetails;
-
diff --git a/frontend/src/Cabinet/components/Search/SearchNoCabinetDetails.tsx b/frontend/src/Cabinet/components/Search/SearchNoCabinetDetails.tsx
index 455a58aed..6456dfc49 100644
--- a/frontend/src/Cabinet/components/Search/SearchNoCabinetDetails.tsx
+++ b/frontend/src/Cabinet/components/Search/SearchNoCabinetDetails.tsx
@@ -145,7 +145,6 @@ const SearchNoCabinetDetails = (props: ISearchDetail) => {
);
};
-
const WrapperStyled = styled.div`
width: 350px;
height: 110px;
diff --git a/frontend/src/Cabinet/components/Store/Admin/UserStoreInfoArea/UserStoreInfoArea.tsx b/frontend/src/Cabinet/components/Store/Admin/UserStoreInfoArea/UserStoreInfoArea.tsx
index a7c79642e..1b2247d1b 100644
--- a/frontend/src/Cabinet/components/Store/Admin/UserStoreInfoArea/UserStoreInfoArea.tsx
+++ b/frontend/src/Cabinet/components/Store/Admin/UserStoreInfoArea/UserStoreInfoArea.tsx
@@ -5,7 +5,6 @@ import { targetUserInfoState } from "@/Cabinet/recoil/atoms";
import AdminItemUsageLogPage from "@/Cabinet/pages/admin/AdminItemUsageLogPage";
import ButtonContainer from "@/Cabinet/components/Common/Button";
import SelectInduction from "@/Cabinet/components/Common/SelectInduction";
-import AdminLentLog from "@/Cabinet/components/LentLog/AdminLentLog";
import AdminItemProvisionModal from "@/Cabinet/components/Modals/StoreModal/AdminItemProvisionModal";
import { ReactComponent as LogoIcon } from "@/Cabinet/assets/images/logo.svg";
import useMenu from "@/Cabinet/hooks/useMenu";
diff --git a/frontend/src/Cabinet/components/Store/CoinLog/CoinLog.tsx b/frontend/src/Cabinet/components/Store/CoinLog/CoinLog.tsx
index b6d867c8c..425692936 100644
--- a/frontend/src/Cabinet/components/Store/CoinLog/CoinLog.tsx
+++ b/frontend/src/Cabinet/components/Store/CoinLog/CoinLog.tsx
@@ -11,6 +11,7 @@ import { ReactComponent as CoinIcon } from "@/Cabinet/assets/images/coinIcon.svg
import { ReactComponent as Select } from "@/Cabinet/assets/images/selectMaincolor.svg";
import { CoinLogToggleType } from "@/Cabinet/types/enum/store.enum";
import { axiosCoinLog } from "@/Cabinet/api/axios/axios.custom";
+import useDebounce from "@/Cabinet/hooks/useDebounce";
import { formatDate } from "@/Cabinet/utils/dateUtils";
const toggleList: toggleItem[] = [
@@ -44,10 +45,11 @@ const CoinLog = () => {
const [userInfo] = useRecoilState(userState);
const size = 5;
// NOTE : size 만큼 데이터 불러옴
+ const { debounce } = useDebounce();
- const getCoinLog = async (type: CoinLogToggleType) => {
+ const getCoinLog = async () => {
try {
- const response = await axiosCoinLog(type, page, size);
+ const response = await axiosCoinLog(toggleType, page, size);
if (page === 0) {
setCoinLogs(response.data.result);
} else {
@@ -71,9 +73,7 @@ const CoinLog = () => {
};
useEffect(() => {
- setTimeout(() => {
- getCoinLog(toggleType);
- }, 333);
+ debounce("coinLog", getCoinLog, 100);
}, [page, toggleType]);
useEffect(() => {
diff --git a/frontend/src/Cabinet/components/Store/Inventory/InventoryItem.tsx b/frontend/src/Cabinet/components/Store/Inventory/InventoryItem.tsx
index e15a09d89..340134de8 100644
--- a/frontend/src/Cabinet/components/Store/Inventory/InventoryItem.tsx
+++ b/frontend/src/Cabinet/components/Store/Inventory/InventoryItem.tsx
@@ -170,8 +170,7 @@ const ItemIconStyled = styled.div<{ itemType: StoreItemType }>`
& > svg > path {
stroke: var(--sys-main-color);
- stroke-width: ${(props) =>
- props.itemType === StoreItemType.EXTENSION ? "2.8px" : "1.5px"};
+ stroke-width: "1.5px";
}
`;
diff --git a/frontend/src/Cabinet/components/Store/ItemUsageLog/ItemLogBlock.tsx b/frontend/src/Cabinet/components/Store/ItemUsageLog/ItemLogBlock.tsx
index b82eacb00..b6a2fae71 100644
--- a/frontend/src/Cabinet/components/Store/ItemUsageLog/ItemLogBlock.tsx
+++ b/frontend/src/Cabinet/components/Store/ItemUsageLog/ItemLogBlock.tsx
@@ -50,14 +50,13 @@ const IconBlockStyled = styled.div<{ itemName: string }>`
svg {
width: 40px;
height: 40px;
+ transform-origin: center;
}
- & > svg > path {
+ & > svg > * {
+ transform: scale(1.25);
stroke: var(--white-text-with-bg-color);
- stroke-width: ${(props) =>
- props.itemName === ItemTypeLabelMap[StoreItemType.EXTENSION]
- ? "3px"
- : "1.5px"};
+ stroke-width: "1.5px";
}
`;
diff --git a/frontend/src/Cabinet/components/Store/StoreCoinPick.tsx b/frontend/src/Cabinet/components/Store/StoreCoinPick.tsx
index 52c130ea8..4bbaddf56 100644
--- a/frontend/src/Cabinet/components/Store/StoreCoinPick.tsx
+++ b/frontend/src/Cabinet/components/Store/StoreCoinPick.tsx
@@ -14,10 +14,12 @@ const StoreCoinPick = () => {
height={"320px"}
>
<>
-
+
+
+
누군가가 매일 흘리는 동전을 주워보세요💰
- 동전은 하루에 한 번씩 획득할 수 있습니다
+ 동전은 하루에 한 번씩 주울 수 있습니다
toggleStore()}>
동전 주우러가기
@@ -27,6 +29,11 @@ const StoreCoinPick = () => {
);
};
+const CoinAnimationStyled = styled.div`
+ min-width: 140px;
+ min-height: 140px;
+`;
+
const CoinSummary = styled.div`
background-color: var(--card-content-bg-color);
font-size: var(--size-base);
diff --git a/frontend/src/Cabinet/components/UserCabinetInfoArea/UserCabinetInfoArea.tsx b/frontend/src/Cabinet/components/UserCabinetInfoArea/UserCabinetInfoArea.tsx
index 67840970f..10071a05d 100644
--- a/frontend/src/Cabinet/components/UserCabinetInfoArea/UserCabinetInfoArea.tsx
+++ b/frontend/src/Cabinet/components/UserCabinetInfoArea/UserCabinetInfoArea.tsx
@@ -59,7 +59,7 @@ const UserCabinetInfoArea: React.FC<{
-
+
{selectedUserInfo.name}
diff --git a/frontend/src/Cabinet/constants/StatusCode.ts b/frontend/src/Cabinet/constants/StatusCode.ts
deleted file mode 100644
index 6452cf27b..000000000
--- a/frontend/src/Cabinet/constants/StatusCode.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export const STATUS_400_BAD_REQUEST = 400;
-export const STATUS_401_UNAUTHORIZED = 401;
diff --git a/frontend/src/Cabinet/hooks/useClubInfo.ts b/frontend/src/Cabinet/hooks/useClubInfo.ts
index 152676f21..35e47e52e 100644
--- a/frontend/src/Cabinet/hooks/useClubInfo.ts
+++ b/frontend/src/Cabinet/hooks/useClubInfo.ts
@@ -1,3 +1,4 @@
+import { HttpStatusCode } from "axios";
import { useEffect, useRef, useState } from "react";
import { useRecoilState, useSetRecoilState } from "recoil";
import {
@@ -11,7 +12,6 @@ import {
} from "@/Cabinet/types/dto/club.dto";
import { axiosGetClubInfo } from "@/Cabinet/api/axios/axios.custom";
import useMenu from "@/Cabinet/hooks/useMenu";
-import { STATUS_400_BAD_REQUEST } from "@/Cabinet/constants/StatusCode";
const useClubInfo = () => {
const [clubState, setClubState] = useState({ clubId: 0, page: 0 });
@@ -54,7 +54,7 @@ const useClubInfo = () => {
}, 500);
} catch {
setTimeout(() => {
- setClubInfo(STATUS_400_BAD_REQUEST);
+ setClubInfo(HttpStatusCode.BadRequest);
}, 500);
}
};
diff --git a/frontend/src/Cabinet/hooks/useMenu.ts b/frontend/src/Cabinet/hooks/useMenu.ts
index 1a47e474a..7e0a31949 100644
--- a/frontend/src/Cabinet/hooks/useMenu.ts
+++ b/frontend/src/Cabinet/hooks/useMenu.ts
@@ -200,7 +200,9 @@ const useMenu = () => {
};
const closeUserStore = () => {
- if (document.getElementById("itemInfo")?.classList.contains("on") == true) {
+ if (
+ document.getElementById("itemInfo")?.classList.contains("on") === true
+ ) {
document.getElementById("itemInfo")?.classList.remove("on");
}
};
diff --git a/frontend/src/Cabinet/pages/AvailablePage.tsx b/frontend/src/Cabinet/pages/AvailablePage.tsx
index 9cd4291a4..9ec0be173 100644
--- a/frontend/src/Cabinet/pages/AvailablePage.tsx
+++ b/frontend/src/Cabinet/pages/AvailablePage.tsx
@@ -29,6 +29,9 @@ const toggleList: toggleItem[] = [
{ name: "공유", key: AvailableCabinetsType.SHARE },
];
+/* TODO: DISABLED_FLOOR 을 환경변수로 넣기 */
+export const DISABLED_FLOOR = ["4"];
+
const AvailablePage = () => {
const [toggleType, setToggleType] = useState(
AvailableCabinetsType.ALL
@@ -98,10 +101,6 @@ const AvailablePage = () => {
useEffect(() => {
deleteRecoilPersistFloorSection();
- setTimeout(() => {
- // 새로고침 광클 방지를 위한 초기 로딩 딜레이
- setIsLoaded(true);
- }, 500);
}, []);
useEffect(() => {
@@ -156,14 +155,16 @@ const AvailablePage = () => {
/>
- {isLoaded && cabinets ? (
- Object.entries(cabinets).map(([key, value]) => (
-
- ))
+ {Object.keys(cabinets).length ? (
+ Object.entries(cabinets)
+ .filter(([key, _]) => !DISABLED_FLOOR.includes(key))
+ .map(([key, value]) => (
+
+ ))
) : (
)}
diff --git a/frontend/src/Cabinet/pages/ItemUsageLogPage.tsx b/frontend/src/Cabinet/pages/ItemUsageLogPage.tsx
index 32a1c2553..455e6d119 100644
--- a/frontend/src/Cabinet/pages/ItemUsageLogPage.tsx
+++ b/frontend/src/Cabinet/pages/ItemUsageLogPage.tsx
@@ -7,6 +7,7 @@ import { ItemIconMap } from "@/Cabinet/assets/data/maps";
import { ReactComponent as DropdownChevron } from "@/Cabinet/assets/images/dropdownChevron.svg";
import { StoreItemType } from "@/Cabinet/types/enum/store.enum";
import { axiosGetItemUsageHistory } from "@/Cabinet/api/axios/axios.custom";
+import useDebounce from "@/Cabinet/hooks/useDebounce";
const mapItemNameToType = (itemName: string): StoreItemType => {
switch (itemName) {
@@ -19,7 +20,7 @@ const mapItemNameToType = (itemName: string): StoreItemType => {
case "페널티 감면권":
return StoreItemType.PENALTY;
default:
- return StoreItemType.PENALTY;
+ return StoreItemType.EXTENSION;
}
};
@@ -55,8 +56,9 @@ const ItemUsageLogPage = () => {
const [isMoreBtnLoading, setIsMoreBtnLoading] = useState(true);
const [isLoading, setIsLoading] = useState(true);
const size = 5;
+ const { debounce } = useDebounce();
- const getItemUsageLog = async (page: number, size: number) => {
+ const getItemUsageLog = async () => {
try {
const data = await axiosGetItemUsageHistory(page, size);
const newLogs = createLogEntries(data);
@@ -72,13 +74,19 @@ const ItemUsageLogPage = () => {
useEffect(() => {
setTimeout(() => {
- getItemUsageLog(page, size);
+ getItemUsageLog();
}, 333);
}, [page]);
const handleMoreClick = () => {
- setPage((prev) => prev + 1);
setIsMoreBtnLoading(true);
+ debounce(
+ "itemUsageLog",
+ () => {
+ setPage((prev) => prev + 1);
+ },
+ 333
+ );
};
return (
@@ -111,7 +119,6 @@ const ItemUsageLogPage = () => {
{isMoreBtnLoading ? (
diff --git a/frontend/src/Cabinet/pages/LogPage.tsx b/frontend/src/Cabinet/pages/LogPage.tsx
index d89840775..9d157d0ad 100644
--- a/frontend/src/Cabinet/pages/LogPage.tsx
+++ b/frontend/src/Cabinet/pages/LogPage.tsx
@@ -1,10 +1,10 @@
+import { HttpStatusCode } from "axios";
import { useEffect, useState } from "react";
import styled from "styled-components";
import LogTable from "@/Cabinet/components/LentLog/LogTable/LogTable";
import { LentHistoryDto } from "@/Cabinet/types/dto/lent.dto";
import { LentLogResponseType } from "@/Cabinet/types/dto/lent.dto";
import { axiosMyLentLog } from "@/Cabinet/api/axios/axios.custom";
-import { STATUS_400_BAD_REQUEST } from "@/Cabinet/constants/StatusCode";
const LogPage = () => {
const [lentLog, setLentLog] = useState(undefined);
@@ -18,7 +18,7 @@ const LogPage = () => {
}, 500);
} catch {
setTimeout(() => {
- setLentLog(STATUS_400_BAD_REQUEST);
+ setLentLog(HttpStatusCode.BadRequest);
}, 500);
}
};
diff --git a/frontend/src/Cabinet/pages/MainPage.tsx b/frontend/src/Cabinet/pages/MainPage.tsx
index 070e57387..c98123f84 100644
--- a/frontend/src/Cabinet/pages/MainPage.tsx
+++ b/frontend/src/Cabinet/pages/MainPage.tsx
@@ -6,14 +6,16 @@ import {
currentBuildingNameState,
currentCabinetIdState,
currentFloorNumberState,
+ currentFloorSectionNamesState,
currentSectionNameState,
isCurrentSectionRenderState,
targetCabinetInfoState,
} from "@/Cabinet/recoil/atoms";
import { currentFloorSectionState } from "@/Cabinet/recoil/selectors";
+import { DISABLED_FLOOR } from "@/Cabinet/pages/AvailablePage";
import CabinetListContainer from "@/Cabinet/components/CabinetList/CabinetList.container";
import LoadingAnimation from "@/Cabinet/components/Common/LoadingAnimation";
-import SectionAlertModal from "@/Cabinet/components/Modals/SectionAlertModal/SectionAlertModal";
+import SectionAlertModal from "@/Cabinet/components/Modals/StoreModal/SectionAlertModal";
import SectionPaginationContainer from "@/Cabinet/components/SectionPagination/SectionPagination.container";
import { clubSectionsData } from "@/Cabinet/assets/data/mapPositionData";
import { ReactComponent as FilledHeartIcon } from "@/Cabinet/assets/images/filledHeart.svg";
@@ -52,6 +54,9 @@ const MainPage = () => {
const [isCurrentSectionRender, setIsCurrentSectionRender] = useRecoilState(
isCurrentSectionRenderState
);
+ const [currentFloorSectionNames] = useRecoilState(
+ currentFloorSectionNamesState
+ );
useEffect(() => {
if (!currentFloor) {
@@ -70,11 +75,9 @@ const MainPage = () => {
}, []);
useEffect(() => {
- const clubSection = clubSectionsData.find((section) => {
+ const clubSection = !!clubSectionsData.find((section) => {
return section === currentSectionName;
- })
- ? true
- : false;
+ });
setIsClubSection(clubSection);
}, [currentSectionName]);
@@ -119,29 +122,25 @@ const MainPage = () => {
setIsCurrentSectionRender(false);
};
- return (
- <>
- {isLoading && }
- {
- touchStartPosX.current = e.changedTouches[0].screenX;
- touchStartPosY.current = e.changedTouches[0].screenY;
- }}
- onTouchEnd={(e: React.TouchEvent) => {
- swipeSection(
- e.changedTouches[0].screenX,
- e.changedTouches[0].screenY
- );
- }}
- >
-
- {!isClubSection && (
+ return isLoading ? (
+
+ ) : (
+ {
+ touchStartPosX.current = e.changedTouches[0].screenX;
+ touchStartPosY.current = e.changedTouches[0].screenY;
+ }}
+ onTouchEnd={(e: React.TouchEvent) => {
+ swipeSection(e.changedTouches[0].screenX, e.changedTouches[0].screenY);
+ }}
+ >
+
+ {currentFloorSectionNames.includes(currentSectionName) &&
+ !isClubSection && (
{sectionList[currentSectionIndex]?.alarmRegistered === true ? (
@@ -150,32 +149,31 @@ const MainPage = () => {
)}
)}
-
-
-
-
- {currentSectionName !== SectionType.elevator &&
- currentSectionName !== SectionType.stairs && (
-
- 새로고침
-
- )}
-
- {showSectionAlertModal && (
-
- )}
-
- >
+
+
+
+
+ {currentSectionName !== SectionType.elevator &&
+ currentSectionName !== SectionType.stairs && (
+
+ 새로고침
+
+ )}
+
+ {showSectionAlertModal && (
+
+ )}
+
);
};
@@ -222,7 +220,11 @@ const IconWrapperStyled = styled.div<{ disabled: boolean }>`
}
`;
-const AlertStyled = styled.div`
+const AlertStyled = styled.div<{ currentFloor: number }>`
+ visibility: ${(props) =>
+ DISABLED_FLOOR.includes(props.currentFloor.toString())
+ ? "hidden"
+ : "visible"};
height: 30px;
display: flex;
justify-content: end;
diff --git a/frontend/src/Cabinet/pages/PostLogin.tsx b/frontend/src/Cabinet/pages/PostLogin.tsx
index c840badad..ef31dbbd8 100644
--- a/frontend/src/Cabinet/pages/PostLogin.tsx
+++ b/frontend/src/Cabinet/pages/PostLogin.tsx
@@ -46,6 +46,7 @@ const PostLogin = (): JSX.Element => {
let time = setTimeout(() => {
navigate("/home");
}, 600);
+
return () => {
clearTimeout(time);
};
diff --git a/frontend/src/Cabinet/pages/admin/AdminMainPage.tsx b/frontend/src/Cabinet/pages/admin/AdminMainPage.tsx
index de410c157..adc495cb1 100644
--- a/frontend/src/Cabinet/pages/admin/AdminMainPage.tsx
+++ b/frontend/src/Cabinet/pages/admin/AdminMainPage.tsx
@@ -93,44 +93,43 @@ const AdminMainPage = () => {
else moveToRightSection();
};
- return (
- <>
- {isLoading && }
- {
- touchStartPosX.current = e.changedTouches[0].screenX;
- touchStartPosY.current = e.changedTouches[0].screenY;
- }}
- onTouchEnd={(e: React.TouchEvent) => {
- swipeSection(
- e.changedTouches[0].screenX,
- e.changedTouches[0].screenY
- );
- }}
- >
-
-
-
-
-
-
+ return isLoading ? (
+
+ ) : (
+ {
+ touchStartPosX.current = e.changedTouches[0].screenX;
+ touchStartPosY.current = e.changedTouches[0].screenY;
+ }}
+ onTouchEnd={(e: React.TouchEvent) => {
+ swipeSection(
+ e.changedTouches[0].screenX,
+ e.changedTouches[0].screenY
+ );
+ }}
+ >
+
+
+
+
+
+
-
- 새로고침
-
-
-
- >
+
+ 새로고침
+
+
+
);
};
diff --git a/frontend/src/Cabinet/pages/admin/AdminSlackNotiPage.tsx b/frontend/src/Cabinet/pages/admin/AdminSlackNotiPage.tsx
index 97885d4af..0fc2ad296 100644
--- a/frontend/src/Cabinet/pages/admin/AdminSlackNotiPage.tsx
+++ b/frontend/src/Cabinet/pages/admin/AdminSlackNotiPage.tsx
@@ -1,5 +1,5 @@
import { useRef, useState } from "react";
-import styled from "styled-components";
+import styled, { css } from "styled-components";
import {
FailResponseModal,
SuccessResponseModal,
@@ -16,6 +16,12 @@ import {
axiosSendSlackNotificationToUser,
} from "@/Cabinet/api/axios/axios.custom";
+const hoverAndClickedBtnStyles = css`
+ background: var(--capsule-btn-hover-bg-color);
+ color: var(--sys-main-color);
+ border: 1px solid var(--sys-main-color);
+`;
+
const AdminSlackNotiPage = () => {
const receiverInputRef = useRef(null);
const msgTextAreaRef = useRef(null);
@@ -24,6 +30,8 @@ const AdminSlackNotiPage = () => {
const [modalContent, setModalContent] = useState("");
const [modalTitle, setModalTitle] = useState("");
const [isLoading, setIsLoading] = useState(false);
+ const [channelBtnIdx, setChannelBtnIdx] = useState(-1);
+ const [templateBtnIdx, setTemplateBtnIdx] = useState(-1);
const renderReceiverInput = (title: string) => {
if (receiverInputRef.current) receiverInputRef.current.value = title;
@@ -40,6 +48,8 @@ const AdminSlackNotiPage = () => {
const initializeInputandTextArea = () => {
if (receiverInputRef.current) receiverInputRef.current.value = "";
if (msgTextAreaRef.current) msgTextAreaRef.current.value = "";
+ if (channelBtnIdx > -1) setChannelBtnIdx(-1);
+ if (templateBtnIdx > -1) setTemplateBtnIdx(-1);
};
const handleSubmitButton = async () => {
@@ -88,7 +98,11 @@ const AdminSlackNotiPage = () => {
return (
renderReceiverInput(channel.title)}
+ onClick={() => {
+ renderReceiverInput(channel.title);
+ if (channelBtnIdx !== idx) setChannelBtnIdx(idx);
+ }}
+ channelBtnIsClicked={channelBtnIdx === idx}
>
{channel.title}
@@ -104,7 +118,11 @@ const AdminSlackNotiPage = () => {
return (
renderTemplateTextArea(template.title)}
+ onClick={() => {
+ renderTemplateTextArea(template.title);
+ if (templateBtnIdx !== idx) setTemplateBtnIdx(idx);
+ }}
+ templateBtnIsClicked={templateBtnIdx === idx}
>
{template.title}
@@ -209,7 +227,10 @@ const CapsuleWrappingStyled = styled.div`
flex-wrap: wrap;
`;
-const CapsuleButtonStyled = styled.span`
+const CapsuleButtonStyled = styled.span<{
+ channelBtnIsClicked?: boolean;
+ templateBtnIsClicked?: boolean;
+}>`
display: flex;
justify-content: center;
align-items: center;
@@ -220,10 +241,14 @@ const CapsuleButtonStyled = styled.span`
cursor: pointer;
:hover {
- background: var(--capsule-btn-hover-bg-color);
- color: var(--sys-main-color);
- border: 1px solid var(--sys-main-color);
+ ${hoverAndClickedBtnStyles}
}
+
+ ${({ channelBtnIsClicked, templateBtnIsClicked }) =>
+ (channelBtnIsClicked || templateBtnIsClicked) &&
+ css`
+ ${hoverAndClickedBtnStyles}
+ `}
`;
const FormWappingStyled = styled.div`
diff --git a/frontend/src/Cabinet/types/dto/admin.dto.ts b/frontend/src/Cabinet/types/dto/admin.dto.ts
index d3b97ee9b..6fa19f058 100644
--- a/frontend/src/Cabinet/types/dto/admin.dto.ts
+++ b/frontend/src/Cabinet/types/dto/admin.dto.ts
@@ -1,4 +1,4 @@
-import { STATUS_400_BAD_REQUEST } from "@/Cabinet/constants/StatusCode";
+import { HttpStatusCode } from "axios";
export interface BannedUserDto {
userId: number;
@@ -78,7 +78,7 @@ export interface ItemLogResponse {
export type ItemLogResponseType =
| ItemLogResponse
- | typeof STATUS_400_BAD_REQUEST
+ | HttpStatusCode.BadRequest
| undefined;
export interface IItemUseCountDto {
diff --git a/frontend/src/Cabinet/types/dto/club.dto.ts b/frontend/src/Cabinet/types/dto/club.dto.ts
index 379462796..eba012415 100644
--- a/frontend/src/Cabinet/types/dto/club.dto.ts
+++ b/frontend/src/Cabinet/types/dto/club.dto.ts
@@ -1,8 +1,8 @@
-import { STATUS_400_BAD_REQUEST } from "@/Cabinet/constants/StatusCode";
+import { HttpStatusCode } from "axios";
export type ClubListReponseType =
| ClubPaginationResponseDto
- | typeof STATUS_400_BAD_REQUEST
+ | HttpStatusCode.BadRequest
| undefined;
export interface ClubPaginationResponseDto {
@@ -18,7 +18,7 @@ export interface ClubResponseDto {
export type ClubInfoResponseType =
| ClubInfoResponseDto
- | typeof STATUS_400_BAD_REQUEST
+ | HttpStatusCode.BadRequest
| undefined;
export interface ClubCabinetInfo {
diff --git a/frontend/src/Cabinet/types/dto/lent.dto.ts b/frontend/src/Cabinet/types/dto/lent.dto.ts
index 05f483c44..23ebf6814 100644
--- a/frontend/src/Cabinet/types/dto/lent.dto.ts
+++ b/frontend/src/Cabinet/types/dto/lent.dto.ts
@@ -1,4 +1,4 @@
-import { STATUS_400_BAD_REQUEST } from "@/Cabinet/constants/StatusCode";
+import { HttpStatusCode } from "axios";
/**
* @interface
@@ -31,7 +31,7 @@ export interface LentHistoryDto {
export type LentLogResponseType =
| LentHistoryDto[]
- | typeof STATUS_400_BAD_REQUEST
+ | HttpStatusCode.BadRequest
| undefined;
export interface ILentLog {
@@ -51,7 +51,7 @@ export interface ClubUserDto {
export type ClubLogResponseType =
| ClubUserDto[]
- | typeof STATUS_400_BAD_REQUEST
+ | HttpStatusCode.BadRequest
| undefined;
export interface IClubLog {
diff --git a/frontend/src/Cabinet/types/enum/content.status.enum.ts b/frontend/src/Cabinet/types/enum/content.status.enum.ts
index cb348bd85..535867bca 100644
--- a/frontend/src/Cabinet/types/enum/content.status.enum.ts
+++ b/frontend/src/Cabinet/types/enum/content.status.enum.ts
@@ -5,6 +5,8 @@ export enum ContentStatus {
PENDING = "PENDING",
IN_SESSION = "IN_SESSION",
EXTENSION = "EXTENSION",
+ COIN = "COIN",
+ STORE = "STORE",
}
export default ContentStatus;
diff --git a/frontend/src/Cabinet/types/enum/error.type.enum.ts b/frontend/src/Cabinet/types/enum/error.type.enum.ts
new file mode 100644
index 000000000..f77f8438b
--- /dev/null
+++ b/frontend/src/Cabinet/types/enum/error.type.enum.ts
@@ -0,0 +1,8 @@
+enum ErrorType {
+ LENT = "LENT",
+ RETURN = "RETURN",
+ STORE = "STORE",
+ INTERNAL_SERVER_ERROR = "INTERNAL_SERVER_ERROR",
+}
+
+export default ErrorType;
diff --git a/frontend/src/Presentation/components/LeftNav/LeftMainNav/LeftMainNav.container.tsx b/frontend/src/Presentation/components/LeftNav/LeftMainNav/LeftMainNav.container.tsx
index 367f83995..6bebb4647 100644
--- a/frontend/src/Presentation/components/LeftNav/LeftMainNav/LeftMainNav.container.tsx
+++ b/frontend/src/Presentation/components/LeftNav/LeftMainNav/LeftMainNav.container.tsx
@@ -30,9 +30,9 @@ const LeftMainNavContainer = ({ isAdmin }: { isAdmin?: boolean }) => {
const onClickPresentationDetailButton = () => {
if (isAdmin) {
- navigator("/presentation/detail");
+ navigator("/admin/presentation/detail");
} else {
- navigator("detail");
+ navigator("/presentation/detail");
}
closeAll();
};
diff --git a/frontend/src/Presentation/components/PresentationLog/LogTable.tsx b/frontend/src/Presentation/components/PresentationLog/LogTable.tsx
index 923beb42e..ba86a64f7 100644
--- a/frontend/src/Presentation/components/PresentationLog/LogTable.tsx
+++ b/frontend/src/Presentation/components/PresentationLog/LogTable.tsx
@@ -1,7 +1,7 @@
+import { HttpStatusCode } from "axios";
import styled from "styled-components";
import LoadingAnimation from "@/Cabinet/components/Common/LoadingAnimation";
import { formatDate } from "@/Cabinet/utils/dateUtils";
-import { STATUS_400_BAD_REQUEST } from "@/Cabinet/constants/StatusCode";
import {
PresentationLocationLabelMap,
PresentationStatusTypeLabelMap,
@@ -26,7 +26,7 @@ const LogTable = ({
상태
- {presentationHistory !== STATUS_400_BAD_REQUEST && (
+ {presentationHistory !== HttpStatusCode.BadRequest && (
{presentationHistory.map(
(
@@ -50,7 +50,7 @@ const LogTable = ({
)}
- {presentationHistory === STATUS_400_BAD_REQUEST ||
+ {presentationHistory === HttpStatusCode.BadRequest ||
(presentationHistory.length === 0 && (
발표기록이 없습니다.
))}
diff --git a/frontend/src/Presentation/pages/LogPage.tsx b/frontend/src/Presentation/pages/LogPage.tsx
index 5bbff678c..86b226140 100644
--- a/frontend/src/Presentation/pages/LogPage.tsx
+++ b/frontend/src/Presentation/pages/LogPage.tsx
@@ -1,6 +1,6 @@
+import { HttpStatusCode } from "axios";
import { useEffect, useState } from "react";
import styled from "styled-components";
-import { STATUS_400_BAD_REQUEST } from "@/Cabinet/constants/StatusCode";
import LogTable from "@/Presentation/components/PresentationLog/LogTable";
import {
PresentationHistoryDto,
@@ -21,7 +21,7 @@ const PresentationLogPage = () => {
}, 500);
} catch {
setTimeout(() => {
- setPresentationLog(STATUS_400_BAD_REQUEST);
+ setPresentationLog(HttpStatusCode.BadRequest);
}, 500);
}
};
diff --git a/frontend/src/Presentation/types/dto/presentation.dto.ts b/frontend/src/Presentation/types/dto/presentation.dto.ts
index 2d995f5c3..390d287a9 100644
--- a/frontend/src/Presentation/types/dto/presentation.dto.ts
+++ b/frontend/src/Presentation/types/dto/presentation.dto.ts
@@ -1,4 +1,4 @@
-import { STATUS_400_BAD_REQUEST } from "@/Cabinet/constants/StatusCode";
+import { HttpStatusCode } from "axios";
import {
PresentationCategoryType,
PresentationLocation,
@@ -18,7 +18,7 @@ export interface PresentationHistoryDto {
export type PresentationHistoryResponseType =
| PresentationHistoryDto[]
- | typeof STATUS_400_BAD_REQUEST
+ | HttpStatusCode.BadRequest
| undefined;
export interface IPresentationInfo {
diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx
index 47dddd284..1f4fddbe7 100644
--- a/frontend/src/main.tsx
+++ b/frontend/src/main.tsx
@@ -1,17 +1,62 @@
-import React from "react";
+import * as Sentry from "@sentry/react";
+import React, { useEffect } from "react";
import ReactDOM from "react-dom/client";
+import {
+ createRoutesFromChildren,
+ matchRoutes,
+ useLocation,
+ useNavigationType,
+} from "react-router-dom";
import { RecoilRoot } from "recoil";
+import "@/Cabinet/assets/css/media.css";
+import "@/Cabinet/assets/css/reset.css";
+import "@/index.css";
+import App from "@/App";
import { GlobalStyle } from "@/Cabinet/assets/data/ColorTheme";
-import App from "./App";
-import "./Cabinet/assets/css/media.css";
-import "./Cabinet/assets/css/reset.css";
-import "./index.css";
+
+Sentry.init({
+ dsn: import.meta.env.VITE_SENTRY_DSN,
+ environment:
+ import.meta.env.VITE_IS_LOCAL === "true" ? "local" : "production",
+ release: "^8.18.0",
+ integrations: [
+ // See docs for support of different versions of variation of react router
+ // https://docs.sentry.io/platforms/javascript/guides/react/configuration/integrations/react-router/
+ Sentry.reactRouterV6BrowserTracingIntegration({
+ useEffect,
+ useLocation,
+ useNavigationType,
+ createRoutesFromChildren,
+ matchRoutes,
+ }),
+ Sentry.replayIntegration(),
+ ],
+
+ // Set tracesSampleRate to 1.0 to capture 100%
+ // of transactions for tracing.
+ tracesSampleRate: 1.0,
+
+ // Set `tracePropagationTargets` to control for which URLs trace propagation should be enabled
+ // tracePropagationTargets: [/^\//, /^https:\/\/yourserver\.io\/api/],
+ tracePropagationTargets: [
+ "localhost",
+ /^https:\/\/cabi\.42seoul\.io/,
+ /^https:\/\/dev\.cabi\.42seoul\.io/,
+ /^https:\/\/api\.cabi\.42seoul\.io/,
+ /^https:\/\/api-dev\.cabi\.42seoul\.io/,
+ ],
+
+ // Capture Replay for 100% of all sessions,
+ // plus for 100% of sessions with an error
+ replaysSessionSampleRate: 1.0,
+ replaysOnErrorSampleRate: 1.0,
+});
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
- //
-
-
-
-
- //
+
+
+
+
+
+
);
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
index d1621437f..7a1007709 100644
--- a/frontend/vite.config.ts
+++ b/frontend/vite.config.ts
@@ -8,7 +8,19 @@ import { defineConfig } from "vite";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
- react(),
+ react({
+ babel: {
+ plugins: [
+ [
+ "babel-plugin-styled-components",
+ {
+ displayName: true,
+ fileName: false,
+ },
+ ],
+ ],
+ },
+ }),
visualizer({ open: true, gzipSize: true, template: "treemap" }),
svgr(),
],