From 5276f4fa080309212ddff958737c46ab668d2989 Mon Sep 17 00:00:00 2001 From: JunSeong Date: Tue, 24 Sep 2024 16:57:27 +0900 Subject: [PATCH 1/2] =?UTF-8?q?[FE]=20BUG:=20=EB=AA=A8=EB=8B=AC=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EB=A7=81=ED=81=AC=EB=A1=9C=20=EC=9D=B4=EB=8F=99=20?= =?UTF-8?q?=EC=8B=9C=20=EB=AA=A8=EB=93=A0=20=EC=B0=BD=EC=9D=84=20=EB=8B=AB?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20closeAll=20=EC=B6=94=EA=B0=80=20#1668?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/Cabinet/components/Modals/Modal.tsx | 3 +++ 1 file changed, 3 insertions(+) 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); }} > From 9720bc6f2ac4fb8b9b80feb6d271b5848e9497fd Mon Sep 17 00:00:00 2001 From: jimchoi9 <146968639+jimchoi9@users.noreply.github.com> Date: Tue, 8 Oct 2024 14:52:24 +0900 Subject: [PATCH 2/2] =?UTF-8?q?[FE]=20FEAT:=20MAIN=ED=99=94=EB=A9=B4=20?= =?UTF-8?q?=EC=9E=AC=ED=99=94=20=EC=86=8C=EA=B0=9C=20=EC=B6=94=EA=B0=80#16?= =?UTF-8?q?81=20(#1686)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [FE] FEAT: main layout 설정 #1681 * [FE] FEAT: coinDolar.svg 아이콘 추가 #1681 * Co-authored-by: Gyeong A Koh * FE] FEAT: ManualModal 동전 사용법 모달 수정 #1681 * [FE] FEAT: main ui 티켓 디자인 v1 #1681 * FE] FEAT: ManualModal 아이템 내용추가 #1681 * [FE] FEAT: CSS clip-path 를 사용해 STORE MandualContentBox 생성 #1681 * [FE] FIX: ManualContentBox 의 CSS 모듈화 #1681 * [FE] FIX: ManualContentBox 의 CSS Map 생성 #1681 * [FE] FIX: CSS Map 을 사용해 ManualContentBoxStyled 간소화 #1681 * [FE] FEAT: 티켓 이미지 그림자 적용 #1681 * [FE] FEAT: ManualModal 아이콘 호버 효과 적용 #1681 * [FE] FEAT: 티켓 이미지 반응형 적용 #1681 * [FE] FEAT: coin manual color 적용 #1681 * [FE] FEAT: ItemContentsStyled width 수정 #1681 * [FE] FEAT: new! #1681 * [FE] FEAT: 아이콘 resizing #1681 * [FE] DOCS: 바뀐 정책에 따라 슬랙 알림 연체 문구 수정#1681 * [FE] DOCS: 슬랙 알림 문구 볼드체 적용되게 띄어쓰기 #1681 * [FE] FEAT: 사물함 대여 모달에 연체주의사항 문구 추가 #1681 * [FE] FEAT: 사물함 대여 모달에 연체주의사항 문구 띄어쓰기 수정 #1681 * [FE] FEAT: 불필요한 파일 및 코드 삭제, storeItems 배열을 manualItemsData 객체로 수정 및 적용 #1681 * [FE] FIX: ManualModal 아이템 아이콘 그림자 잘림 해결, 오타 수정 #1681 * [FE] FEAT: 사용 안하는 css 제거 #1681 --------- Co-authored-by: Minkyu01 Co-authored-by: gykoh42 Co-authored-by: jiminChoi Co-authored-by: jusohn Eddie Sohn Co-authored-by: jnkeniaem --- config | 2 +- .../src/Cabinet/assets/data/ManualContent.ts | 113 +++++++++++++++++ .../src/Cabinet/assets/data/SlackAlarm.ts | 10 +- frontend/src/Cabinet/assets/data/maps.ts | 24 +++- .../src/Cabinet/assets/images/coinDolar.svg | 5 + .../src/Cabinet/assets/images/storeAlarm.svg | 6 +- .../Cabinet/assets/images/storeExtension.svg | 10 +- .../src/Cabinet/assets/images/storeMove.svg | 12 +- .../Cabinet/assets/images/storePenalty.svg | 8 +- .../Card/StoreItemCard/StoreItemCard.tsx | 2 - .../components/Home/ManualContentBox.tsx | 91 ++++++-------- .../components/Home/ManualContentBoxStyles.ts | 97 ++++++++++++++ .../Cabinet/components/Home/ServiceManual.tsx | 68 +++++----- .../components/Modals/LentModal/LentModal.tsx | 8 +- .../Modals/ManualModal/ManualModal.tsx | 118 +++++++++++++++--- .../Store/Inventory/InventoryItem.tsx | 3 +- .../Store/ItemUsageLog/ItemLogBlock.tsx | 9 +- .../Cabinet/types/enum/content.status.enum.ts | 2 + 18 files changed, 449 insertions(+), 139 deletions(-) create mode 100644 frontend/src/Cabinet/assets/images/coinDolar.svg create mode 100644 frontend/src/Cabinet/components/Home/ManualContentBoxStyles.ts diff --git a/config b/config index dd72d80cc..93674bce3 160000 --- a/config +++ b/config @@ -1 +1 @@ -Subproject commit dd72d80cce8800e34f3938f3da0dfeb4ef9eb8eb +Subproject commit 93674bce354efe9ad8fb3a7a934bdbf5acd1d162 diff --git a/frontend/src/Cabinet/assets/data/ManualContent.ts b/frontend/src/Cabinet/assets/data/ManualContent.ts index 7e92e6370..8b39bebca 100644 --- a/frontend/src/Cabinet/assets/data/ManualContent.ts +++ b/frontend/src/Cabinet/assets/data/ManualContent.ts @@ -1,9 +1,13 @@ +import { ItemIconMap } from "@/Cabinet/assets/data/maps"; import { ReactComponent as ClockImg } from "@/Cabinet/assets/images/clock.svg"; import { ReactComponent as ClubIcon } from "@/Cabinet/assets/images/clubIcon.svg"; +import { ReactComponent as DollarImg } from "@/Cabinet/assets/images/coinDolar.svg"; import { ReactComponent as ExtensionIcon } from "@/Cabinet/assets/images/extension.svg"; import { ReactComponent as PrivateIcon } from "@/Cabinet/assets/images/privateIcon.svg"; import { ReactComponent as ShareIcon } from "@/Cabinet/assets/images/shareIcon.svg"; +import { ReactComponent as StoreImg } from "@/Cabinet/assets/images/storeIconGray.svg"; import ContentStatus from "@/Cabinet/types/enum/content.status.enum"; +import { StoreItemType } from "@/Cabinet/types/enum/store.enum"; interface ContentStatusData { contentTitle: string; @@ -15,6 +19,12 @@ interface ContentStatusData { pointColor: string; } +interface ItemStatusData { + icon: React.FunctionComponent>; + title: string; + content: string; +} + export const manualContentData: Record = { [ContentStatus.PRIVATE]: { contentTitle: "개인 사물함", @@ -153,4 +163,107 @@ export const manualContentData: Record = { `, pointColor: "var(--normal-text-color)", }, + [ContentStatus.COIN]: { + contentTitle: `코인 사용법`, + iconComponent: DollarImg, + background: "var(--card-bg-color)", + contentText: `◦ 160시간 출석하기
+
+ 42 출석 160시간을 채운다면 다음달 2일에 2000까비가 지급됩니다.
+
+
+ ◦ 동전줍기
+
+ Cabi 홈페이지에 접속해, 하루에 한 번 동전을 주울 수 있습니다.
+ 한 달 동안 20개의 코인을 모두 줍는다면 랜덤 보상이 주어집니다.
+
+
+ ◦ 수요지식회 발표하기
+
+ 수요지식회 발표자 분께 1000까비를 지급해 드립니다.
+ 수요지식회 신청은 왼쪽 상단의수요지식회 홈페이지에서 신청할 수 있습니다.
+
+ + `, + pointColor: "var(--sys-default-main-color)", + }, + [ContentStatus.STORE]: { + contentTitle: "까비 상점 OPEN!", + iconComponent: StoreImg, + background: + "linear-gradient(to bottom, var(--ref-purple-400), var(--ref-purple-600))", + contentText: ` + `, + pointColor: "var(--white-text-with-bg-color)", + }, +}; + +export const manualItemsData: Record = { + [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 514b7e654..3def9e28e 100644 --- a/frontend/src/Cabinet/assets/data/SlackAlarm.ts +++ b/frontend/src/Cabinet/assets/data/SlackAlarm.ts @@ -27,7 +27,7 @@ export const SlackAlarmTemplates: ISlackAlarmTemplate[] = [ :happy_ccabi: 안녕하세요. Cabi 팀입니다! :happy_ccabi: :sad_ccabi: 서비스 개선을 위해, 서버를 점검하게 되었습니다. :sad_ccabi: :file_cabinet: 서비스 개선과 관련한 사항은 Cabi 채널 에서, :file_cabinet: -:hammer_and_wrench: 보관물 관련 사항은 *데스크에 직접 문의*해주세요! :hammer_and_wrench: +:hammer_and_wrench: 보관물 관련 사항은 *데스크에 직접 문의* 해주세요! :hammer_and_wrench: 점검 일자 : 2024년 04월 02일 (화요일) 점검 시간 : 15시 10분 ~ 완료 공지 시점까지 @@ -179,9 +179,9 @@ export const SlackAlarmTemplates: ISlackAlarmTemplate[] = [ { 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/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/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..ccf8c876c 100644 --- a/frontend/src/Cabinet/components/Home/ServiceManual.tsx +++ b/frontend/src/Cabinet/components/Home/ServiceManual.tsx @@ -1,6 +1,6 @@ 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 ContentStatus from "@/Cabinet/types/enum/content.status.enum"; @@ -36,62 +36,53 @@ const ServiceManual = ({

- 가능성의 확장 + 당신의 사물함
- 개인, 공유, 동아리 사물함. + 당신의 방식으로,

+
openModal(ContentStatus.PRIVATE)} - > - -
-
openModal(ContentStatus.SHARE)} - > - -
-
openModal(ContentStatus.CLUB)} + onClick={() => openModal(ContentStatus.COIN)} > - + +

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 +98,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; 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/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/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;