diff --git a/src/App.tsx b/src/App.tsx
index d503728..8904cca 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,6 +1,6 @@
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
-import { Suspense, useState } from 'react'
+import { useState } from 'react'
import { Helmet, HelmetProvider } from 'react-helmet-async'
import { RouterProvider } from 'react-router-dom'
import styled, { ThemeProvider } from 'styled-components'
@@ -8,7 +8,6 @@ import PWABadge from '~/PWABadge'
import { router } from '~/router'
import GlobalStyle from '~/styles/globalStyle'
import { darkTheme, lightTheme } from '~/styles/theme'
-import PageLoader from '~components/PageLoader'
import PushNotification from '~components/PushNotification'
const queryClient = new QueryClient()
@@ -31,9 +30,7 @@ function App() {
- }>
-
-
+
diff --git a/src/assets/favicon.svg b/src/assets/favicon.svg
new file mode 100644
index 0000000..dfef3a3
--- /dev/null
+++ b/src/assets/favicon.svg
@@ -0,0 +1,13 @@
+
diff --git a/src/components/Footer/styles.ts b/src/components/Footer/styles.ts
index b922fa1..3d96a0b 100644
--- a/src/components/Footer/styles.ts
+++ b/src/components/Footer/styles.ts
@@ -10,6 +10,7 @@ export const Footer = styled.footer`
bottom: 0;
background-color: ${({ theme }) => theme.colors.grayscale.gc_4};
box-shadow: inset 0 1px 0 0 ${({ theme }) => theme.colors.grayscale.gc_1};
+ z-index: 900;
`
export const FooterNavList = styled.ul`
diff --git a/src/components/GlobalHookContainer/index.tsx b/src/components/GlobalHookContainer/index.tsx
index 57e66ca..665ff93 100644
--- a/src/components/GlobalHookContainer/index.tsx
+++ b/src/components/GlobalHookContainer/index.tsx
@@ -1,9 +1,11 @@
import { ReactNode } from 'react'
+import useClearModal from '~hooks/useClearModal'
import useSubscribe from '~hooks/useSubscribe'
import useToken from '~hooks/useToken'
export default function GlobalHookContainer({ children }: { children: ReactNode }) {
useToken()
useSubscribe()
+ useClearModal()
return <>{children}>
}
diff --git a/src/components/SendMessageForm/styles.ts b/src/components/SendMessageForm/styles.ts
index 450b0fa..9d17204 100644
--- a/src/components/SendMessageForm/styles.ts
+++ b/src/components/SendMessageForm/styles.ts
@@ -11,7 +11,7 @@ export const SendMessageForm = styled.form`
display: flex;
align-items: center;
gap: 12px;
- z-index: 1;
+ z-index: 1000;
`
export const ChatInput = styled.input`
flex: 1;
diff --git a/src/hooks/useClearModal.ts b/src/hooks/useClearModal.ts
new file mode 100644
index 0000000..14b7172
--- /dev/null
+++ b/src/hooks/useClearModal.ts
@@ -0,0 +1,11 @@
+import { useEffect } from 'react'
+import { useLocation } from 'react-router-dom'
+import { useModalStore } from '~stores/modalStore'
+
+export default function useClearModal() {
+ const { pathname } = useLocation()
+ const { clearModal } = useModalStore()
+ useEffect(() => {
+ clearModal()
+ }, [pathname])
+}
diff --git a/src/modals/ChatArea/styles.ts b/src/modals/ChatArea/styles.ts
index c974fd1..db4b004 100644
--- a/src/modals/ChatArea/styles.ts
+++ b/src/modals/ChatArea/styles.ts
@@ -1,7 +1,19 @@
import { styled } from 'styled-components'
+import DogHowling from '~assets/dog_howling.svg'
export const ChatArea = styled.div`
+ position: relative;
height: calc(100% - 64px);
overflow: auto;
+ &::after {
+ background: url(${DogHowling}) center/cover;
+ content: '';
+ width: 190px;
+ height: 260px;
+ position: fixed;
+ bottom: 95px;
+ left: 50%;
+ translate: -50%;
+ }
`
export const ChatMessageList = styled.div``
diff --git a/src/modals/ChatModal/styles.ts b/src/modals/ChatModal/styles.ts
index 213b492..aa6cd57 100644
--- a/src/modals/ChatModal/styles.ts
+++ b/src/modals/ChatModal/styles.ts
@@ -1,6 +1,5 @@
import { styled } from 'styled-components'
import { HEADER_HEIGHT_LG } from '~constants/layout'
-import DogHowling from '~assets/dog_howling.svg'
export const ChatModal = styled.div`
position: relative;
@@ -8,17 +7,8 @@ export const ChatModal = styled.div`
height: 100%;
padding: ${HEADER_HEIGHT_LG}px 20px 0;
background-color: ${({ theme }) => theme.colors.brand.lighten_3};
- &::after {
- background: url(${DogHowling}) center/cover;
- content: '';
- width: 190px;
- height: 260px;
- position: fixed;
- bottom: 95px;
- left: 50%;
- translate: -50%;
- }
`
+
export const ProfileWrapper = styled.div`
display: flex;
align-items: center;
diff --git a/src/modals/WalkAnalysisModal/index.tsx b/src/modals/WalkAnalysisModal/index.tsx
index ae65574..7b02e08 100644
--- a/src/modals/WalkAnalysisModal/index.tsx
+++ b/src/modals/WalkAnalysisModal/index.tsx
@@ -1,15 +1,11 @@
-import { useEffect, useRef, Suspense } from 'react'
+import { useEffect, useRef } from 'react'
+import { FamilyMemberWalk } from '~apis/log/fetchFamilyYearlyWalks'
import Prev from '~assets/prev.svg'
+import { useCurrentMonthWalks, useFamilyWalks, useMonthlyWalks, useTotalWalks } from '~pages/LogPage/useWalkInfo'
import { useModalStore } from '~stores/modalStore'
+import Statistics from './components/Statistics'
import { createBarChart, createLineChart } from './createChart'
import * as S from './styles'
-import { FamilyMemberWalk } from '~apis/log/fetchFamilyYearlyWalks'
-import Statistics from './components/Statistics'
-import { useCurrentMonthWalks, useFamilyWalks, useMonthlyWalks, useTotalWalks } from '~pages/LogPage/useWalkInfo'
-import { QueryErrorResetBoundary } from '@tanstack/react-query'
-import { ErrorBoundary } from 'react-error-boundary'
-import ErrorFallback from '~components/ErrorFallback'
-import PageLoader from '~components/PageLoader'
interface ChartData {
month: string
@@ -55,33 +51,27 @@ export default function WalkAnalysisModal() {
}
}, [monthlyWalks, familyWalks])
return (
-
- {({ reset }) => (
-
- }>
-
-
- 산책 분석
-
-
-
-
- 올해 월 별 산책기록
-
-
-
- 올해 가족별 산책 횟수
-
-
-
-
-
-
-
-
-
-
- )}
-
+ <>
+
+
+ 산책 분석
+
+
+
+
+ 올해 월 별 산책기록
+
+
+
+ 올해 가족별 산책 횟수
+
+
+
+
+
+
+
+
+ >
)
}
diff --git a/src/pages/HomePage/index.tsx b/src/pages/HomePage/index.tsx
index 460c49e..ea5cafe 100644
--- a/src/pages/HomePage/index.tsx
+++ b/src/pages/HomePage/index.tsx
@@ -18,6 +18,7 @@ import { FAMILY_ROLE } from '~constants/familyRole'
import NotificationModal from '~modals/NotificationModal'
import { useModalStore } from '~stores/modalStore'
import * as S from './styles'
+import { getParticle } from '~utils/getParticle'
function HomeContent() {
const {
@@ -40,7 +41,11 @@ function HomeContent() {
- 오늘은 {data?.familyRole ? FAMILY_ROLE[data.familyRole] : ''}랑
+ 오늘은{' '}
+
+ {FAMILY_ROLE[data?.familyRole]}
+
+ {getParticle(FAMILY_ROLE[data?.familyRole])}
산책가는 날!
diff --git a/src/pages/LogPage/index.tsx b/src/pages/LogPage/index.tsx
index 8f1aba1..3787410 100644
--- a/src/pages/LogPage/index.tsx
+++ b/src/pages/LogPage/index.tsx
@@ -35,7 +35,20 @@ export default function LogPage() {
pushModal(, 'slideLeft')}
+ onClick={() =>
+ pushModal(
+
+ {({ reset }) => (
+
+ }>
+
+
+
+ )}
+ ,
+ 'slideLeft'
+ )
+ }
/>
diff --git a/src/pages/LoginPage/index.tsx b/src/pages/LoginPage/index.tsx
index 2f27cca..2991fab 100644
--- a/src/pages/LoginPage/index.tsx
+++ b/src/pages/LoginPage/index.tsx
@@ -1,6 +1,6 @@
import * as S from './styles'
import { Helmet } from 'react-helmet-async'
-
+import Logo from '~assets/favicon.svg?react'
const serverUrl = import.meta.env.VITE_SERVER_URL
const BACK_URL = new URL(serverUrl).origin
@@ -56,7 +56,9 @@ export default function LoginPage() {
- 로고
+
+
+
)
diff --git a/src/router.tsx b/src/router.tsx
index d2252e6..4e3b45f 100644
--- a/src/router.tsx
+++ b/src/router.tsx
@@ -1,9 +1,11 @@
+import { Suspense } from 'react'
import { createBrowserRouter, Outlet } from 'react-router-dom'
import { WebSocketProvider } from '~/WebSocketContext'
import Footer from '~components/Footer'
+import GlobalHookContainer from '~components/GlobalHookContainer'
+import PageLoader from '~components/PageLoader'
import ModalContainer from '~modals/ModalContainer'
import * as Pages from './components/LazyComponents'
-import GlobalHookContainer from '~components/GlobalHookContainer'
export const router = createBrowserRouter([
{
@@ -11,7 +13,9 @@ export const router = createBrowserRouter([
element: (
-
+ }>
+
+
@@ -59,28 +63,28 @@ export const router = createBrowserRouter([
{
path: '/login',
element: (
- <>
+ }>
- >
+
),
},
{
path: '/register',
element: (
- <>
+ }>
- >
+
),
},
{
path: '/register/dog',
element: (
- <>
+ }>
- >
+
),
},
])
diff --git a/src/utils/getParticle.ts b/src/utils/getParticle.ts
new file mode 100644
index 0000000..fdb2580
--- /dev/null
+++ b/src/utils/getParticle.ts
@@ -0,0 +1,18 @@
+/**
+ * word에 받침이 있으면 "이랑"
+ * 받침이 없으면 "랑" 반환
+ */
+export function getParticle(word: string) {
+ const lastChar = word.charAt(word.length - 1)
+ const unicodeValue = lastChar.charCodeAt(0)
+
+ // 한글 유니코드 범위 체크
+ if (unicodeValue < 0xac00 || unicodeValue > 0xd7a3) {
+ return word + '랑'
+ }
+
+ // 종성 확인
+ const hasConsonantJongseong = (unicodeValue - 0xac00) % 28 > 0
+
+ return hasConsonantJongseong ? '이랑' : '랑'
+}