Skip to content

Commit 43c5ef8

Browse files
authored
Merge pull request #156 from prgrms-web-devcourse-final-project/154-feature/enhance-ux
[Feature] #154 UX 개선
2 parents ec0a58d + 2a64959 commit 43c5ef8

File tree

14 files changed

+123
-65
lines changed

14 files changed

+123
-65
lines changed

src/App.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
22
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
3-
import { Suspense, useState } from 'react'
3+
import { useState } from 'react'
44
import { Helmet, HelmetProvider } from 'react-helmet-async'
55
import { RouterProvider } from 'react-router-dom'
66
import styled, { ThemeProvider } from 'styled-components'
77
import PWABadge from '~/PWABadge'
88
import { router } from '~/router'
99
import GlobalStyle from '~/styles/globalStyle'
1010
import { darkTheme, lightTheme } from '~/styles/theme'
11-
import PageLoader from '~components/PageLoader'
1211
import PushNotification from '~components/PushNotification'
1312

1413
const queryClient = new QueryClient()
@@ -31,9 +30,7 @@ function App() {
3130
</button>
3231
<GlobalStyle />
3332
<MobileContainer>
34-
<Suspense fallback={<PageLoader />}>
35-
<RouterProvider router={router} />
36-
</Suspense>
33+
<RouterProvider router={router} />
3734
<PushNotification />
3835
</MobileContainer>
3936
<PWABadge />

src/assets/favicon.svg

Lines changed: 13 additions & 0 deletions
Loading

src/components/Footer/styles.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export const Footer = styled.footer`
1010
bottom: 0;
1111
background-color: ${({ theme }) => theme.colors.grayscale.gc_4};
1212
box-shadow: inset 0 1px 0 0 ${({ theme }) => theme.colors.grayscale.gc_1};
13+
z-index: 900;
1314
`
1415

1516
export const FooterNavList = styled.ul`
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { ReactNode } from 'react'
2+
import useClearModal from '~hooks/useClearModal'
23
import useSubscribe from '~hooks/useSubscribe'
34
import useToken from '~hooks/useToken'
45

56
export default function GlobalHookContainer({ children }: { children: ReactNode }) {
67
useToken()
78
useSubscribe()
9+
useClearModal()
810
return <>{children}</>
911
}

src/components/SendMessageForm/styles.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export const SendMessageForm = styled.form`
1111
display: flex;
1212
align-items: center;
1313
gap: 12px;
14-
z-index: 1;
14+
z-index: 1000;
1515
`
1616
export const ChatInput = styled.input`
1717
flex: 1;

src/hooks/useClearModal.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { useEffect } from 'react'
2+
import { useLocation } from 'react-router-dom'
3+
import { useModalStore } from '~stores/modalStore'
4+
5+
export default function useClearModal() {
6+
const { pathname } = useLocation()
7+
const { clearModal } = useModalStore()
8+
useEffect(() => {
9+
clearModal()
10+
}, [pathname])
11+
}

src/modals/ChatArea/styles.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,19 @@
11
import { styled } from 'styled-components'
2+
import DogHowling from '~assets/dog_howling.svg'
23

34
export const ChatArea = styled.div`
5+
position: relative;
46
height: calc(100% - 64px);
57
overflow: auto;
8+
&::after {
9+
background: url(${DogHowling}) center/cover;
10+
content: '';
11+
width: 190px;
12+
height: 260px;
13+
position: fixed;
14+
bottom: 95px;
15+
left: 50%;
16+
translate: -50%;
17+
}
618
`
719
export const ChatMessageList = styled.div``

src/modals/ChatModal/styles.ts

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,14 @@
11
import { styled } from 'styled-components'
22
import { HEADER_HEIGHT_LG } from '~constants/layout'
3-
import DogHowling from '~assets/dog_howling.svg'
43

54
export const ChatModal = styled.div`
65
position: relative;
76
width: 100%;
87
height: 100%;
98
padding: ${HEADER_HEIGHT_LG}px 20px 0;
109
background-color: ${({ theme }) => theme.colors.brand.lighten_3};
11-
&::after {
12-
background: url(${DogHowling}) center/cover;
13-
content: '';
14-
width: 190px;
15-
height: 260px;
16-
position: fixed;
17-
bottom: 95px;
18-
left: 50%;
19-
translate: -50%;
20-
}
2110
`
11+
2212
export const ProfileWrapper = styled.div`
2313
display: flex;
2414
align-items: center;

src/modals/WalkAnalysisModal/index.tsx

Lines changed: 26 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
1-
import { useEffect, useRef, Suspense } from 'react'
1+
import { useEffect, useRef } from 'react'
2+
import { FamilyMemberWalk } from '~apis/log/fetchFamilyYearlyWalks'
23
import Prev from '~assets/prev.svg'
4+
import { useCurrentMonthWalks, useFamilyWalks, useMonthlyWalks, useTotalWalks } from '~pages/LogPage/useWalkInfo'
35
import { useModalStore } from '~stores/modalStore'
6+
import Statistics from './components/Statistics'
47
import { createBarChart, createLineChart } from './createChart'
58
import * as S from './styles'
6-
import { FamilyMemberWalk } from '~apis/log/fetchFamilyYearlyWalks'
7-
import Statistics from './components/Statistics'
8-
import { useCurrentMonthWalks, useFamilyWalks, useMonthlyWalks, useTotalWalks } from '~pages/LogPage/useWalkInfo'
9-
import { QueryErrorResetBoundary } from '@tanstack/react-query'
10-
import { ErrorBoundary } from 'react-error-boundary'
11-
import ErrorFallback from '~components/ErrorFallback'
12-
import PageLoader from '~components/PageLoader'
139

1410
interface ChartData {
1511
month: string
@@ -55,33 +51,27 @@ export default function WalkAnalysisModal() {
5551
}
5652
}, [monthlyWalks, familyWalks])
5753
return (
58-
<QueryErrorResetBoundary>
59-
{({ reset }) => (
60-
<ErrorBoundary FallbackComponent={ErrorFallback} onReset={reset}>
61-
<Suspense fallback={<PageLoader />}>
62-
<S.Header>
63-
<S.PrevBtn src={Prev} alt='뒤로 가기' onClick={popModal} />
64-
<S.Title>산책 분석</S.Title>
65-
</S.Header>
66-
<S.WalkAnalysisModal>
67-
<S.ChartArea>
68-
<S.ChartWrapper>
69-
<S.ChartTitle>올해 월 별 산책기록</S.ChartTitle>
70-
<S.Chart ref={lineChartRef} width='100%' height='100%'></S.Chart>
71-
</S.ChartWrapper>
72-
<S.ChartWrapper>
73-
<S.ChartTitle>올해 가족별 산책 횟수</S.ChartTitle>
74-
<S.Chart ref={barChartRef} width='100%' height='100%'></S.Chart>
75-
</S.ChartWrapper>
76-
</S.ChartArea>
77-
<S.StatisticsArea>
78-
<Statistics title={'총 산책 내역'} stats={totalWalks} />
79-
<Statistics title={'이번달 통계'} stats={currentMonthWalks} />
80-
</S.StatisticsArea>
81-
</S.WalkAnalysisModal>
82-
</Suspense>
83-
</ErrorBoundary>
84-
)}
85-
</QueryErrorResetBoundary>
54+
<>
55+
<S.Header>
56+
<S.PrevBtn src={Prev} alt='뒤로 가기' onClick={popModal} />
57+
<S.Title>산책 분석</S.Title>
58+
</S.Header>
59+
<S.WalkAnalysisModal>
60+
<S.ChartArea>
61+
<S.ChartWrapper>
62+
<S.ChartTitle>올해 월 별 산책기록</S.ChartTitle>
63+
<S.Chart ref={lineChartRef} width='100%' height='100%'></S.Chart>
64+
</S.ChartWrapper>
65+
<S.ChartWrapper>
66+
<S.ChartTitle>올해 가족별 산책 횟수</S.ChartTitle>
67+
<S.Chart ref={barChartRef} width='100%' height='100%'></S.Chart>
68+
</S.ChartWrapper>
69+
</S.ChartArea>
70+
<S.StatisticsArea>
71+
<Statistics title={'총 산책 내역'} stats={totalWalks} />
72+
<Statistics title={'이번달 통계'} stats={currentMonthWalks} />
73+
</S.StatisticsArea>
74+
</S.WalkAnalysisModal>
75+
</>
8676
)
8777
}

src/pages/HomePage/index.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { FAMILY_ROLE } from '~constants/familyRole'
1818
import NotificationModal from '~modals/NotificationModal'
1919
import { useModalStore } from '~stores/modalStore'
2020
import * as S from './styles'
21+
import { getParticle } from '~utils/getParticle'
2122

2223
function HomeContent() {
2324
const {
@@ -40,7 +41,11 @@ function HomeContent() {
4041
</S.Header>
4142
<S.Visual>
4243
<Typo24 $weight='700' $textAlign='center'>
43-
오늘은 {data?.familyRole ? FAMILY_ROLE[data.familyRole] : ''}
44+
오늘은{' '}
45+
<Typo24 as='span' $color='default' $weight='700'>
46+
{FAMILY_ROLE[data?.familyRole]}
47+
</Typo24>
48+
{getParticle(FAMILY_ROLE[data?.familyRole])}
4449
</Typo24>
4550
<Typo24 $weight='700' $textAlign='center'>
4651
산책가는 날!

src/pages/LogPage/index.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,20 @@ export default function LogPage() {
3535
<S.GraphImage
3636
src={GraphIcon}
3737
alt='산책 기록 그래프'
38-
onClick={() => pushModal(<WalkAnalysisModal />, 'slideLeft')}
38+
onClick={() =>
39+
pushModal(
40+
<QueryErrorResetBoundary>
41+
{({ reset }) => (
42+
<ErrorBoundary FallbackComponent={ErrorFallback} onReset={reset}>
43+
<Suspense fallback={<PageLoader />}>
44+
<WalkAnalysisModal />
45+
</Suspense>
46+
</ErrorBoundary>
47+
)}
48+
</QueryErrorResetBoundary>,
49+
'slideLeft'
50+
)
51+
}
3952
/>
4053
</Header>
4154
<S.CalendarWrapper>

src/pages/LoginPage/index.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as S from './styles'
22
import { Helmet } from 'react-helmet-async'
3-
3+
import Logo from '~assets/favicon.svg?react'
44
const serverUrl = import.meta.env.VITE_SERVER_URL
55
const BACK_URL = new URL(serverUrl).origin
66

@@ -56,7 +56,9 @@ export default function LoginPage() {
5656
<meta name='description' content='DDang 서비스 로그인' />
5757
</Helmet>
5858
<TitleSection />
59-
<S.Logo>로고</S.Logo>
59+
<S.Logo>
60+
<Logo width='90%' height='90%' />
61+
</S.Logo>
6062
<SocialLoginButtons />
6163
</S.LoginPage>
6264
)

src/router.tsx

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
1+
import { Suspense } from 'react'
12
import { createBrowserRouter, Outlet } from 'react-router-dom'
23
import { WebSocketProvider } from '~/WebSocketContext'
34
import Footer from '~components/Footer'
5+
import GlobalHookContainer from '~components/GlobalHookContainer'
6+
import PageLoader from '~components/PageLoader'
47
import ModalContainer from '~modals/ModalContainer'
58
import * as Pages from './components/LazyComponents'
6-
import GlobalHookContainer from '~components/GlobalHookContainer'
79

810
export const router = createBrowserRouter([
911
{
1012
path: '/',
1113
element: (
1214
<WebSocketProvider>
1315
<GlobalHookContainer>
14-
<Outlet />
16+
<Suspense fallback={<PageLoader />}>
17+
<Outlet />
18+
</Suspense>
1519
<Footer />
1620
<ModalContainer />
1721
</GlobalHookContainer>
@@ -59,28 +63,28 @@ export const router = createBrowserRouter([
5963
{
6064
path: '/login',
6165
element: (
62-
<>
66+
<Suspense fallback={<PageLoader />}>
6367
<Pages.LoginPage />
6468
<ModalContainer />
65-
</>
69+
</Suspense>
6670
),
6771
},
6872
{
6973
path: '/register',
7074
element: (
71-
<>
75+
<Suspense fallback={<PageLoader />}>
7276
<Pages.RegisterPage />
7377
<ModalContainer />
74-
</>
78+
</Suspense>
7579
),
7680
},
7781
{
7882
path: '/register/dog',
7983
element: (
80-
<>
84+
<Suspense fallback={<PageLoader />}>
8185
<Pages.RegisterDogPage />
8286
<ModalContainer />
83-
</>
87+
</Suspense>
8488
),
8589
},
8690
])

src/utils/getParticle.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* word에 받침이 있으면 "이랑"
3+
* 받침이 없으면 "랑" 반환
4+
*/
5+
export function getParticle(word: string) {
6+
const lastChar = word.charAt(word.length - 1)
7+
const unicodeValue = lastChar.charCodeAt(0)
8+
9+
// 한글 유니코드 범위 체크
10+
if (unicodeValue < 0xac00 || unicodeValue > 0xd7a3) {
11+
return word + '랑'
12+
}
13+
14+
// 종성 확인
15+
const hasConsonantJongseong = (unicodeValue - 0xac00) % 28 > 0
16+
17+
return hasConsonantJongseong ? '이랑' : '랑'
18+
}

0 commit comments

Comments
 (0)