Skip to content

Commit

Permalink
Merge pull request #547 from peer-42seoul/feat/widget/notice
Browse files Browse the repository at this point in the history
[D-TP] 공지사항 위젯
  • Loading branch information
yoouyeon authored Jan 27, 2024
2 parents b2c25c6 + d8c00ea commit 4aaa374
Show file tree
Hide file tree
Showing 7 changed files with 251 additions and 23 deletions.
6 changes: 2 additions & 4 deletions src/app/teams/[id]/panel/WidgetList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { SizeType, WidgetType } from '@/types/ITeamDnDLayout'
import TmpTextWidget from '@/app/teams/[id]/panel/widgets/TextWidget'
import { useCallback, useState } from 'react'
import { sizeRatio } from '@/app/teams/[id]/panel/TeamDnD'
import TmpNoticeWidget from '@/app/teams/[id]/panel/widgets/TmpNoticeWidget'
import TmpBoardWidget from '@/app/teams/[id]/panel/widgets/TmpBoardWidget'
import CalenderWidget from '@/app/teams/[id]/panel/widgets/CalenderWidget'
import TmpAttendWidget from '@/app/teams/[id]/panel/widgets/TmpAttendWidget'
import TmpImageWidget from '@/app/teams/[id]/panel/widgets/ImageWidget'
import TmpLinkWidget from '@/app/teams/[id]/panel/widgets/TmpLinkWidget'
import BoardWidget from './widgets/BoardWidget'
import Slider from 'react-slick'
import 'slick-carousel/slick/slick.css'
import 'slick-carousel/slick/slick-theme.css'
Expand Down Expand Up @@ -82,9 +82,7 @@ const WidgetList = ({
(typeValue: WidgetType) => {
switch (typeValue) {
case 'notice':
return (
<TmpNoticeWidget data={null} size={toolSize[typeValue] ?? 'S'} />
)
return <BoardWidget size={toolSize[typeValue] ?? 'S'} />
case 'board':
return (
<TmpBoardWidget data={null} size={toolSize[typeValue] ?? 'S'} />
Expand Down
4 changes: 2 additions & 2 deletions src/app/teams/[id]/panel/WidgetsRender.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Box, IconButton, Stack, useMediaQuery } from '@mui/material'
import TmpNoticeWidget from '@/app/teams/[id]/panel/widgets/TmpNoticeWidget'
import BoardWidget from './widgets/BoardWidget'
import TmpBoardWidget from '@/app/teams/[id]/panel/widgets/TmpBoardWidget'
import CalenderWidget from '@/app/teams/[id]/panel/widgets/CalenderWidget'
import TmpAttendWidget from '@/app/teams/[id]/panel/widgets/TmpAttendWidget'
Expand Down Expand Up @@ -81,7 +81,7 @@ const WidgetsRender = ({
(type: WidgetType, wgData: any, wgSize: SizeType) => {
switch (type) {
case 'notice':
return <TmpNoticeWidget data={wgData} size={wgSize} />
return <BoardWidget size={wgSize} />
case 'board':
return <TmpBoardWidget data={wgData} size={wgSize} />
case 'calender':
Expand Down
43 changes: 43 additions & 0 deletions src/app/teams/[id]/panel/widgets/BoardWidget/PreviewModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// 게시판과 공지사항 미리보기 모달을 함께 쓸 계획...

import CuButton from '@/components/CuButton'
import CuModal from '@/components/CuModal'
import { ListItem } from '@/components/board/ListPanel'
import { ITeamNotice } from '@/types/TeamBoardTypes'
import { Stack } from '@mui/material'
import { useRouter } from 'next/navigation'

interface IPreviewModalProps {
open: boolean
onClose: () => void
data: ITeamNotice[]
teamId?: string | string[]
}

const PreviewModal = ({ open, onClose, data, teamId }: IPreviewModalProps) => {
const router = useRouter()

return (
<CuModal open={open} onClose={onClose} title={'공지사항'}>
<Stack spacing={'1rem'}>
<>
{data.map((item) => (
<ListItem
key={crypto.randomUUID()}
title={item.title}
authorNickname={item.authorNickname}
createdAt={item.createdAt}
/>
))}
</>
<CuButton
action={() => router.push(`/teams/${teamId}/board`)}
message={'모든 공지사항 보기'}
variant={'text'}
/>
</Stack>
</CuModal>
)
}

export default PreviewModal
13 changes: 13 additions & 0 deletions src/app/teams/[id]/panel/widgets/BoardWidget/index.style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Theme } from '@mui/material'

export const widgetContent = {
padding: '1.5rem 1.5rem 2rem 1.5rem',
}

export const mobileWidgetContent = {
padding: '1.25rem 1.25rem 1.5rem 1.25rem',
}

export const titleIcon = {
color: (theme: Theme) => theme.palette.text.normal,
}
190 changes: 190 additions & 0 deletions src/app/teams/[id]/panel/widgets/BoardWidget/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
'use client'

import { useParams } from 'next/navigation'
import dayjs from 'dayjs'
import useSWR from 'swr'
import { Stack, Typography } from '@mui/material'
import useAxiosWithAuth from '@/api/config'
import CuCircularProgress from '@/components/CuCircularProgress'
import useModal from '@/hook/useModal'
import useMedia from '@/hook/useMedia'
import { NoticeIcon } from '@/icons/TeamPage'
import { SizeType } from '@/types/ITeamDnDLayout'
import { ITeamNotice } from '@/types/TeamBoardTypes'
import PreviewModal from './PreviewModal'
import WidgetCard from '../WidgetCard'
import * as style from './index.style'

type TBoardWidgetRenderProps = Partial<{
isPc: boolean
teamId: string | string[]
postId: number
listData: ITeamNotice[]
}>

interface IBoardWidgetContainerProps {
modalData?: ITeamNotice[]
isPc: boolean
children: React.ReactNode
teamId?: string | string[]
}

interface IBoardWidgetItemProps {
title: string
authorNickname: string
createdAt: Date
content?: string
}

const BoardWidget = ({ size }: { size: SizeType }) => {
const { isPc } = useMedia()
const { id } = useParams()
const axiosWithAuth = useAxiosWithAuth()
const { data, isLoading, error } = useSWR(
`/api/v1/team/notice/${id}?pageSize=${8}page=${1}keyword=`,
(url: string) => axiosWithAuth.get(url).then((res) => res.data),
)

if (isLoading)
return (
<BoardWidgetContainer isPc={isPc}>
<CuCircularProgress color={'secondary'} />
</BoardWidgetContainer>
)
if (!data || error)
return (
<BoardWidgetContainer isPc={isPc}>
<StatusMessage message={'글을 불러오는 중 문제가 발생했습니다.'} />
</BoardWidgetContainer>
)
if (!data?.content.length)
return (
<BoardWidgetContainer isPc={isPc} modalData={data?.content} teamId={id}>
<StatusMessage message={'등록된 글이 없습니다.'} />
</BoardWidgetContainer>
)

return (
<BoardWidgetContainer isPc={isPc} modalData={data.content} teamId={id}>
{size === 'L' ? (
<BoardWidgetList isPc={isPc} listData={data.content} />
) : (
<BoardWidgetSingle postId={data.content[0].postId} />
)}
</BoardWidgetContainer>
)
}

const BoardWidgetContainer = ({
teamId,
modalData,
isPc,
children,
}: IBoardWidgetContainerProps) => {
const { isOpen, openModal, closeModal } = useModal()

return (
<>
<WidgetCard
onClick={modalData ? openModal : undefined}
contentSx={isPc ? style.widgetContent : style.mobileWidgetContent}
>
<Stack spacing={isPc ? '1.5rem' : '0.5rem'}>
<Stack direction={'row'} spacing={'0.25rem'}>
<NoticeIcon sx={style.titleIcon} />
<Typography variant={'Title3Emphasis'}>공지사항</Typography>
</Stack>
{children}
</Stack>
</WidgetCard>
{modalData && (
<PreviewModal
open={isOpen}
onClose={closeModal}
data={modalData}
teamId={teamId}
/>
)}
</>
)
}

const BoardWidgetList = ({ isPc, listData }: TBoardWidgetRenderProps) => {
// size l
return (
<Stack spacing={isPc ? '1rem' : '0,5rem'}>
{listData
?.slice(0, 4)
.map((item) => (
<BoardWidgetItem
key={item.postId}
title={item.title}
authorNickname={item.authorNickname}
createdAt={item.createdAt}
/>
))}
</Stack>
)
}

const BoardWidgetSingle = ({ postId }: TBoardWidgetRenderProps) => {
// size m
const axiosWithAuth = useAxiosWithAuth()
const { data, isLoading, error } = useSWR(
`/api/v1/team/notice/${postId}`,
(url: string) => axiosWithAuth.get(url).then((res) => res.data),
)
if (isLoading) return <CuCircularProgress color={'secondary'} />
if (!data || error)
return <StatusMessage message="글을 불러오는 중 문제가 발생했습니다." />
return (
<BoardWidgetItem
title={data.title}
authorNickname={data.authorNickname}
createdAt={data.createdAt}
content={data.content}
/>
)
}

const StatusMessage = ({ message }: { message: string }) => {
return (
<Typography variant={'Body2'} color={'text.alternative'}>
{message}
</Typography>
)
}

const BoardWidgetItem = ({
title,
authorNickname,
content,
createdAt,
}: IBoardWidgetItemProps) => {
return (
<Stack spacing={'0.25rem'}>
<Typography variant={'Body1'} color={'text.normal'}>
{title}
</Typography>
{content && (
<Typography
variant={'Body2'}
color={'text.alternative'}
sx={{ marginBottom: '0.75rem' }}
>
{content}
</Typography>
)}
<Stack direction={'row'} spacing={'0.5rem'}>
<Typography variant={'Body2'} color={'text.alternative'}>
{authorNickname}
</Typography>
<Typography variant={'Body2'} color={'text.alternative'}>
{dayjs(createdAt).format('MM월 DD일')}
</Typography>
</Stack>
</Stack>
)
}

export default BoardWidget
16 changes: 0 additions & 16 deletions src/app/teams/[id]/panel/widgets/TmpNoticeWidget.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion src/components/board/ListPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ interface IListItemProps {
title: string
authorNickname: string
createdAt: Date
onClick: () => void
onClick?: () => void
hit?: number
}

Expand Down

0 comments on commit 4aaa374

Please sign in to comment.