Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/(business)/business/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { AppProviders } from 'app/providers'
import { pretendard } from 'app/styles'
import { GoogleAnalytics } from 'shared/config/google-analytics'
import { cn } from 'shared/lib'
import { BusinessGNB } from 'shared/ui'
import { BusinessGNB } from 'widgets/gnb'

import '../../globals.css'

Expand Down
2 changes: 1 addition & 1 deletion app/(guest)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ReactNode } from 'react'
import { pretendard } from 'app/styles'
import { GoogleAnalytics } from 'shared/config/google-analytics'
import { cn } from 'shared/lib'
import { GuestGNB } from 'shared/ui'
import { GuestGNB } from 'widgets/gnb'

import '../globals.css'

Expand Down
2 changes: 1 addition & 1 deletion app/(user)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { AppProviders } from 'app/providers'
import { pretendard } from 'app/styles'
import { GoogleAnalytics } from 'shared/config/google-analytics'
import { cn } from 'shared/lib'
import { GNB } from 'shared/ui'
import { GNB } from 'widgets/gnb'

import '../globals.css'

Expand Down
File renamed without changes
34 changes: 34 additions & 0 deletions src/entities/notification/api/get-notification-unread-count.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
'use server'

import { getTeacherSession, getBusinessSession } from 'entities/auth'
import { apiClient } from 'shared/api'

import { NotificationUnreadCount } from '../model/setting'

type GetNotificationUnreadCountResponse = NotificationUnreadCount

export const getTeacherNotificationUnreadCount = async () => {
const { accessToken } = await getTeacherSession()

const response = await apiClient.get<GetNotificationUnreadCountResponse>({
endpoint: `/notifications/unread-count`,
option: {
authorization: `Bearer ${accessToken}`,
},
})

return response
}

export const getBusinessNotificationUnreadCount = async () => {
const { accessToken } = await getBusinessSession()

const response = await apiClient.get<GetNotificationUnreadCountResponse>({
endpoint: `/notifications/unread-count`,
option: {
authorization: `Bearer ${accessToken}`,
},
})

return response
}
42 changes: 42 additions & 0 deletions src/entities/notification/api/get-notifications.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use server'

import { getBusinessSession, getTeacherSession } from 'entities/auth'
import { apiClient, Pagination, PaginationParams } from 'shared/api'

import { Notification } from '../model/notification'

export type GetNotificationsRequest = PaginationParams<object>

type GetNotificationsResponse = Pagination<Notification>

export const getTeacherNotifications = async (
queryParams: GetNotificationsRequest,
) => {
const { accessToken } = await getTeacherSession()

const response = await apiClient.get<GetNotificationsResponse>({
endpoint: '/notifications',
queryParams,
option: {
authorization: `Bearer ${accessToken}`,
},
})

return response
}

export const getBusinessNotifications = async (
queryParams: GetNotificationsRequest,
) => {
const { accessToken } = await getBusinessSession()

const response = await apiClient.get<GetNotificationsResponse>({
endpoint: '/notifications',
queryParams,
option: {
authorization: `Bearer ${accessToken}`,
},
})

return response
}
49 changes: 49 additions & 0 deletions src/entities/notification/api/query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { infiniteQueryOptions, queryOptions } from '@tanstack/react-query'

import {
getBusinessNotificationUnreadCount,
getTeacherNotificationUnreadCount,
} from './get-notification-unread-count'
import {
getBusinessNotifications,
getTeacherNotifications,
} from './get-notifications'

export const notificationQueries = {
all: () => ['notification'],
lists: () => [...notificationQueries.all(), 'list'],
teacherList: () =>
infiniteQueryOptions({
queryKey: [...notificationQueries.lists(), 'teacher'],
queryFn: ({ pageParam = 0 }) =>
getTeacherNotifications({ pageNumber: pageParam, rowCount: 10 }),
initialPageParam: 0,
getNextPageParam: lastPage => {
if (lastPage.last) return undefined

return lastPage.pageable.pageNumber + 1
},
}),
businessList: () =>
infiniteQueryOptions({
queryKey: [...notificationQueries.lists(), 'business'],
queryFn: ({ pageParam = 0 }) =>
getBusinessNotifications({ pageNumber: pageParam, rowCount: 10 }),
initialPageParam: 0,
getNextPageParam: lastPage => {
if (lastPage.last) return undefined

return lastPage.pageable.pageNumber + 1
},
}),
teacherUnreadCount: () =>
queryOptions({
queryKey: [...notificationQueries.lists(), 'teacher', 'unread-count'],
queryFn: getTeacherNotificationUnreadCount,
}),
businessUnreadCount: () =>
queryOptions({
queryKey: [...notificationQueries.lists(), 'business', 'unread-count'],
queryFn: getBusinessNotificationUnreadCount,
}),
}
1 change: 1 addition & 0 deletions src/entities/notification/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ export {
updateTeacherNotificationSetting,
updateBusinessNotificationSetting,
} from './api/update-notification-setting'
export { notificationQueries } from './api/query'
export type { NotificationSetting } from './model/setting'
9 changes: 9 additions & 0 deletions src/entities/notification/model/notification.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export type Notification = {
id: number
title: string
titleEn: string
content: string
contentEn: string
targetUrl: string
createdAt: string
}
5 changes: 5 additions & 0 deletions src/entities/notification/model/setting.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
export type NotificationSetting = {
allowEmail: boolean
}

export type NotificationUnreadCount = {
hasUnreadNotification: boolean
count: number
}
3 changes: 0 additions & 3 deletions src/shared/ui/gnb/index.ts

This file was deleted.

1 change: 0 additions & 1 deletion src/shared/ui/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ export { DatePicker } from './date-picker'
export { Dropdown } from './dropdown'
export { ErrorPage } from './error/error-page'
export { Filter, type FilterValue } from './filter'
export { GNB, BusinessGNB, GuestGNB } from './gnb'
export { Heading } from './heading'
export { HelperText, type HelperTextProps } from './helper-text'
export { Icon } from './icon'
Expand Down
8 changes: 5 additions & 3 deletions src/shared/ui/layout/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ export const Layout = ({
children,
}: PropsWithChildren<Props>) => {
return (
<div className={cn(css.outerWrapper({ wide }))}>
<div className={cn(css.innerWrapper({ wide, className }))}>
{children}
<div className="overflow-y-auto">
<div className={cn(css.outerWrapper({ wide }))}>
<div className={cn(css.innerWrapper({ wide, className }))}>
{children}
</div>
</div>
</div>
)
Expand Down
2 changes: 1 addition & 1 deletion src/shared/ui/layout/variants.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { cva, VariantProps } from 'class-variance-authority'

export const outerWrapper = cva('h-fit w-fit flex-grow', {
export const outerWrapper = cva('h-[calc(100dvh-65px)] w-fit flex-grow', {
variants: {
wide: {
true: 'mx-auto my-0 flex',
Expand Down
4 changes: 2 additions & 2 deletions src/shared/ui/modal/modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const ModalOverlay = forwardRef<
<DialogPrimitive.Overlay
ref={ref}
className={cn(
'fixed inset-0 z-50 bg-black/50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
'fixed inset-0 z-modal bg-black/50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
className,
)}
{...props}
Expand All @@ -70,7 +70,7 @@ const ModalContent = forwardRef<
<DialogPrimitive.Content
ref={ref}
className={cn(
'fixed left-[50%] top-[50%] z-50 grid w-full translate-x-[-50%] translate-y-[-50%] gap-3 border bg-white p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
'fixed left-[50%] top-[50%] z-modal grid w-full translate-x-[-50%] translate-y-[-50%] gap-3 border bg-white p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
className,
)}
{...props}
Expand Down
12 changes: 12 additions & 0 deletions src/widgets/gnb/api/get-business-notification-unread-count.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { useQuery } from '@tanstack/react-query'

import { notificationQueries } from 'entities/notification'

export const useBusinessNotificationUnreadCount = () => {
const { data, refetch } = useQuery(notificationQueries.businessUnreadCount())

return {
hasUnreadNotification: data?.hasUnreadNotification,
refetch,
}
}
15 changes: 15 additions & 0 deletions src/widgets/gnb/api/get-business-notifications.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { useInfiniteQuery } from '@tanstack/react-query'

import { notificationQueries } from 'entities/notification'
import { useEmptyBoundary } from 'shared/api'

export const useBusinessNotifications = () => {
const result = useInfiniteQuery({
...notificationQueries.businessList(),
select: data => data?.pages.flatMap(page => page.content),
})

useEmptyBoundary(result.data)

return result
}
12 changes: 12 additions & 0 deletions src/widgets/gnb/api/get-teacher-notification-unread-count.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { useQuery } from '@tanstack/react-query'

import { notificationQueries } from 'entities/notification'

export const useTeacherNotificationUnreadCount = () => {
const { data, refetch } = useQuery(notificationQueries.teacherUnreadCount())

return {
hasUnreadNotification: data?.hasUnreadNotification,
refetch,
}
}
15 changes: 15 additions & 0 deletions src/widgets/gnb/api/get-teacher-notifications.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { useInfiniteQuery } from '@tanstack/react-query'

import { notificationQueries } from 'entities/notification'
import { useEmptyBoundary } from 'shared/api'

export const useTeacherNotifications = () => {
const result = useInfiniteQuery({
...notificationQueries.teacherList(),
select: data => data?.pages.flatMap(page => page.content),
})

useEmptyBoundary(result.data)

return result
}
3 changes: 3 additions & 0 deletions src/widgets/gnb/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { GNB } from './ui/gnb'
export { BusinessGNB } from './ui/business-gnb'
export { GuestGNB } from './ui/guest-gnb'
28 changes: 28 additions & 0 deletions src/widgets/gnb/lib/format-date.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { format, differenceInMinutes, differenceInHours } from 'date-fns'
import { enUS, ko } from 'date-fns/locale'

export const formatNotificationDate = (
createdAt: string | Date,
locale: 'ko' | 'en' = 'ko',
): string => {
const now = new Date()
const created =
typeof createdAt === 'string' ? new Date(createdAt) : createdAt

const diffMinutes = differenceInMinutes(now, created)
const diffHours = differenceInHours(now, created)

if (diffMinutes < 1) {
return locale === 'ko' ? '1분 전' : '1minute ago'
}
if (diffMinutes < 60) {
return locale === 'ko' ? `${diffMinutes}분 전` : `${diffMinutes}minutes ago`
}
if (diffHours < 24) {
return locale === 'ko' ? `${diffHours}시간 전` : `${diffHours}hours ago`
}

return format(created, 'yyyy.MM.dd(eee)', {
locale: locale === 'ko' ? ko : enUS,
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ import { businessSignOut } from 'entities/auth'
import { colors, type Locale } from 'shared/config'
import { useDropdown } from 'shared/lib'
import { setLocale } from 'shared/server-lib'

import { Dropdown } from '../dropdown'
import { Icon } from '../icon'
import { Dropdown, Icon } from 'shared/ui'

export const BusinessButton = () => {
const router = useRouter()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import { useRouter } from 'next/navigation'
import { useSession } from 'next-auth/react'
import { useTranslations } from 'next-intl'

import Logo from 'public/images/logo.svg'
import { cn } from 'shared/lib'
import { Button } from 'shared/ui'

import { Button } from '../button'
import Logo from './assets/Logo.svg'
import { BusinessButton } from './business-button'
import { NotificationButton } from './business-notification/button'
import * as Navigation from './navigation'
import { NotificationButton } from './notification'
import * as css from './variants'

export const BusinessGNB = () => {
Expand All @@ -19,8 +19,6 @@ export const BusinessGNB = () => {

const t = useTranslations()

const isDev = process.env.NODE_ENV === 'development'

const handleLogoClick = () => {
router.push('/business')
}
Expand Down
Loading
Loading