diff --git a/src/App.tsx b/src/App.tsx index 7f4eb07..57362f7 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -15,6 +15,7 @@ import Button from "@/components/Button" import ToastMessage from "@/components/ToastMessage" import Chip from "@components/Chip" import Modal from "@/components/Modal" +import Notification from "@/components/List/Notification" import LinkCalendar from "@/components/LinkCalendar" import Video from "@/components/Video" @@ -23,13 +24,13 @@ import LogoutSvg from "@assets/icons/out.svg" import Withdraw from "@assets/icons/withdraw.svg" import Youtube from "@assets/icons/youtube.svg" import Link from "@assets/icons/link.svg" - import SpacewakTextLogo from "@assets/logo/spacewak-text-logo.svg" import WaktaplayTextLogo from "@assets/logo/waktaplay-text-logo.svg" - import ChunsikSVG from "@assets/icons/members/gwakchunsik.svg" import WaktaverseSVG from "@assets/icons/group/waktaverse.svg" +import { IElementProps } from "@components/List/types" + // TODO : 아래 더미데이터들은 원하는 내용으로 바꾸시면 되고 unit은 지우셔도 무방합니다. const TABS = [ { @@ -100,6 +101,36 @@ const UNITS = [ }, ] +const notificationSample: IElementProps[] = [ + { + icon: SpacewakTextLogo, + content: "왁타버스 시작", + view: false, + createdAt: "2시간 전", + category: "게시판", + type: "favorite", + time: null, + }, + { + icon: SpacewakTextLogo, + content: "왁타버스 1 이렇게 길게 만들어 보면 어떻게 될까요 한번 가시보죠", + view: true, + createdAt: "2시간 전", + category: "왁타플레이", + time: "오후 12시 45분", + type: "calendar", + }, + { + icon: SpacewakTextLogo, + content: '"왁타버스" 님이 "스페이스왁"을 친구 추가 했습니다.', + view: true, + createdAt: "2시간 전", + category: "왁타플레이", + link: "https://www.youtube.com/@waktaverse", + type: "favorite", + }, +] + const App = () => { //해당 selectedTabIndex,isShowedMore 두개의 state 들은 tabs UI 와 사용되는 state 입니다. const [selectedTabIndex, setSelectedTabIndex] = useState(0) @@ -405,6 +436,12 @@ const App = () => { alert("link click")} /> alert("link click")} /> + +
+

Notification

+ + +
diff --git a/src/assets/icons/popup.svg b/src/assets/icons/popup.svg new file mode 100644 index 0000000..0acd8e7 --- /dev/null +++ b/src/assets/icons/popup.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/schedule_calendar.svg b/src/assets/icons/schedule_calendar.svg new file mode 100644 index 0000000..980387d --- /dev/null +++ b/src/assets/icons/schedule_calendar.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/components/List/Element.tsx b/src/components/List/Element.tsx new file mode 100644 index 0000000..2cb4b1d --- /dev/null +++ b/src/components/List/Element.tsx @@ -0,0 +1,156 @@ +import styled from "styled-components" + +import PopupSVG from "@/assets/icons/popup.svg" +import Calender from "@/assets/icons/schedule_calendar.svg" + +import { IElementProps } from "./types" + +const ElementWrapper = styled.div` + height: 40px; + align-items: center; + display: flex; + flex-direction: row; + gap: 18px; + padding: 22px 18px; + overflow: hidden; + + &:hover { + background: rgba(255, 255, 255, 0.1); + } + + &:active { + background: rgba(255, 255, 255, 0.2); + } +` + +const IconWrapper = styled.div` + flex: 0 0 40px; + height: 40px; + position: relative; +` + +const DotWrapper = styled.div` + width: 4px; + height: 4px; + background: #47f998; + border-radius: 50%; + position: absolute; + top: 0; + right: 0; + z-index: 10; +` + +const IconBgWrapper = styled.div` + background: #303133; + border-radius: 50%; + height: 40px; + + img { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + } +` + +const BodyWrapper = styled.div` + flex: 0 0 260px; + display: flex; + flex-direction: column; + gap: 12px; + height: 40px; + overflow: hidden; +` + +const InformationsWrapper = styled.div` + display: flex; + flex: 0 0 12px; + flex-direction: row; + justify-content: space-between; + font-weight: 500; + + .category { + flex: 0 0 fit-content; + font-size: 10px; + color: #d3d5db; + } + + .createdAt { + flex: 0 0 fit-content; + font-size: 9px; + color: #b4b8c2; + } +` + +const DescriptionsWrapper = styled.div` + display: flex; + flex-direction: row; + gap: 10px; + font-weight: 600; + justify-content: flex-start; + height: 18px; + font-size: 16px; + + .time { + color: #95ffad; + flex: 0 0 fit-content; + } + + .content { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + margin: 0; + font-weight: 600; + font-size: 16px; + } + + .link { + flex: 0 0 18px; + &:hover { + cursor: pointer; + } + } +` + +const NotificationElement = ({ icon, content, view, createdAt, category, type, time, link }: IElementProps) => { + // link icon click event - move to link + const onClickLink = () => { + location.href = link + } + + return ( + + + {!view && } + + {type === "calendar" && } + {type === "favorite" && } + + + + + +
+ {category} +
+
{createdAt}
+
+ + + {/* type이 "calendar일 때 <시간>이 보임" */} + {type === "calendar" &&
{time}
} +
+ {content} +
+ {/* [type]이 "favorite"이고, [link]값이 있으면 바로가기 아이콘이 보임 */} + {link && type === "favorite" && ( + + )} +
+
+
+ ) +} + +export default NotificationElement diff --git a/src/components/List/Notification.tsx b/src/components/List/Notification.tsx new file mode 100644 index 0000000..0106012 --- /dev/null +++ b/src/components/List/Notification.tsx @@ -0,0 +1,45 @@ +import styled from "styled-components" +import NotificationElement from "./Element" + +const NotificationWrapper = styled.div` + width: 354px; + display: flex; + flex-direction: column; +` + +interface IElementProps { + itemList: { + icon: string + content: string + view: boolean + createdAt: string + category: string + type: "calendar" | "favorite" + time?: string | null + link?: string + }[] +} + +const Notification = ({ itemList }: IElementProps) => { + return ( + + {itemList.map((item, i) => { + return ( + + ) + })} + + ) +} + +export default Notification diff --git a/src/components/List/types.ts b/src/components/List/types.ts new file mode 100644 index 0000000..6db3a1a --- /dev/null +++ b/src/components/List/types.ts @@ -0,0 +1,10 @@ +export interface IElementProps { + icon: string + content: string + view: boolean + createdAt: string + category: string + type: "calendar" | "favorite" + time?: string | null + link?: string +} diff --git a/src/components/index.ts b/src/components/index.ts index dcf9db4..35b1406 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -1,19 +1,22 @@ -export { default as Button } from "./Button"; -export { default as CheckBox } from "./CheckBox"; +export { default as Button } from "./Button" +export { default as CheckBox } from "./CheckBox" -export { default as Card } from "./Card"; -export type { ICardLink } from "./Card/types"; +export { default as Card } from "./Card" +export type { ICardLink } from "./Card/types" -export { default as Chip } from "./Chip"; +export { default as Chip } from "./Chip" export type { IChipBaseProps, IChipMediumProps, IChipSmallProps } from "./Chip/types" -export { default as Filter } from "./Filter"; -export { default as Footer } from "./Footer"; +export { default as Filter } from "./Filter" +export { default as Footer } from "./Footer" -export { default as Menu } from "./Menu"; -export { default as Tabs } from "./Tabs"; -export { default as Video } from "./Video"; -export { default as LinkCalendar } from "./LinkCalendar"; +export { default as Menu } from "./Menu" +export { default as Tabs } from "./Tabs" +export { default as Video } from "./Video" +export { default as LinkCalendar } from "./LinkCalendar" -export { default as Modal } from "./Modal"; -export { default as ToastMessage } from "./ToastMessage"; +export { default as Modal } from "./Modal" +export { default as ToastMessage } from "./ToastMessage" + +export { default as ListNotification } from "./List/Notification" +export type { IElementProps } from "./List/types"