Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] #154 UX 개선 #156

Merged
merged 8 commits into from
Dec 9, 2024
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
7 changes: 2 additions & 5 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
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'
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()
Expand All @@ -31,9 +30,7 @@ function App() {
</button>
<GlobalStyle />
<MobileContainer>
<Suspense fallback={<PageLoader />}>
<RouterProvider router={router} />
</Suspense>
<RouterProvider router={router} />
<PushNotification />
</MobileContainer>
<PWABadge />
Expand Down
13 changes: 13 additions & 0 deletions src/assets/favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/components/Footer/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
2 changes: 2 additions & 0 deletions src/components/GlobalHookContainer/index.tsx
Original file line number Diff line number Diff line change
@@ -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}</>
}
2 changes: 1 addition & 1 deletion src/components/SendMessageForm/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
11 changes: 11 additions & 0 deletions src/hooks/useClearModal.ts
Original file line number Diff line number Diff line change
@@ -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])

Check warning on line 10 in src/hooks/useClearModal.ts

View workflow job for this annotation

GitHub Actions / lighthouse

React Hook useEffect has a missing dependency: 'clearModal'. Either include it or remove the dependency array
}
12 changes: 12 additions & 0 deletions src/modals/ChatArea/styles.ts
Original file line number Diff line number Diff line change
@@ -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``
12 changes: 1 addition & 11 deletions src/modals/ChatModal/styles.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,14 @@
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;
width: 100%;
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;
Expand Down
62 changes: 26 additions & 36 deletions src/modals/WalkAnalysisModal/index.tsx
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -55,33 +51,27 @@ export default function WalkAnalysisModal() {
}
}, [monthlyWalks, familyWalks])
return (
<QueryErrorResetBoundary>
{({ reset }) => (
<ErrorBoundary FallbackComponent={ErrorFallback} onReset={reset}>
<Suspense fallback={<PageLoader />}>
<S.Header>
<S.PrevBtn src={Prev} alt='뒤로 가기' onClick={popModal} />
<S.Title>산책 분석</S.Title>
</S.Header>
<S.WalkAnalysisModal>
<S.ChartArea>
<S.ChartWrapper>
<S.ChartTitle>올해 월 별 산책기록</S.ChartTitle>
<S.Chart ref={lineChartRef} width='100%' height='100%'></S.Chart>
</S.ChartWrapper>
<S.ChartWrapper>
<S.ChartTitle>올해 가족별 산책 횟수</S.ChartTitle>
<S.Chart ref={barChartRef} width='100%' height='100%'></S.Chart>
</S.ChartWrapper>
</S.ChartArea>
<S.StatisticsArea>
<Statistics title={'총 산책 내역'} stats={totalWalks} />
<Statistics title={'이번달 통계'} stats={currentMonthWalks} />
</S.StatisticsArea>
</S.WalkAnalysisModal>
</Suspense>
</ErrorBoundary>
)}
</QueryErrorResetBoundary>
<>
<S.Header>
<S.PrevBtn src={Prev} alt='뒤로 가기' onClick={popModal} />
<S.Title>산책 분석</S.Title>
</S.Header>
<S.WalkAnalysisModal>
<S.ChartArea>
<S.ChartWrapper>
<S.ChartTitle>올해 월 별 산책기록</S.ChartTitle>
<S.Chart ref={lineChartRef} width='100%' height='100%'></S.Chart>
</S.ChartWrapper>
<S.ChartWrapper>
<S.ChartTitle>올해 가족별 산책 횟수</S.ChartTitle>
<S.Chart ref={barChartRef} width='100%' height='100%'></S.Chart>
</S.ChartWrapper>
</S.ChartArea>
<S.StatisticsArea>
<Statistics title={'총 산책 내역'} stats={totalWalks} />
<Statistics title={'이번달 통계'} stats={currentMonthWalks} />
</S.StatisticsArea>
</S.WalkAnalysisModal>
</>
)
}
7 changes: 6 additions & 1 deletion src/pages/HomePage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -40,7 +41,11 @@ function HomeContent() {
</S.Header>
<S.Visual>
<Typo24 $weight='700' $textAlign='center'>
오늘은 {data?.familyRole ? FAMILY_ROLE[data.familyRole] : ''}랑
오늘은{' '}
<Typo24 as='span' $color='default' $weight='700'>
{FAMILY_ROLE[data?.familyRole]}
</Typo24>
{getParticle(FAMILY_ROLE[data?.familyRole])}
</Typo24>
<Typo24 $weight='700' $textAlign='center'>
산책가는 날!
Expand Down
15 changes: 14 additions & 1 deletion src/pages/LogPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,20 @@ export default function LogPage() {
<S.GraphImage
src={GraphIcon}
alt='산책 기록 그래프'
onClick={() => pushModal(<WalkAnalysisModal />, 'slideLeft')}
onClick={() =>
pushModal(
<QueryErrorResetBoundary>
{({ reset }) => (
<ErrorBoundary FallbackComponent={ErrorFallback} onReset={reset}>
<Suspense fallback={<PageLoader />}>
<WalkAnalysisModal />
</Suspense>
</ErrorBoundary>
)}
</QueryErrorResetBoundary>,
'slideLeft'
)
}
/>
</Header>
<S.CalendarWrapper>
Expand Down
6 changes: 4 additions & 2 deletions src/pages/LoginPage/index.tsx
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -56,7 +56,9 @@ export default function LoginPage() {
<meta name='description' content='DDang 서비스 로그인' />
</Helmet>
<TitleSection />
<S.Logo>로고</S.Logo>
<S.Logo>
<Logo width='90%' height='90%' />
</S.Logo>
<SocialLoginButtons />
</S.LoginPage>
)
Expand Down
20 changes: 12 additions & 8 deletions src/router.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
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([
{
path: '/',
element: (
<WebSocketProvider>
<GlobalHookContainer>
<Outlet />
<Suspense fallback={<PageLoader />}>
<Outlet />
</Suspense>
<Footer />
<ModalContainer />
</GlobalHookContainer>
Expand Down Expand Up @@ -59,28 +63,28 @@ export const router = createBrowserRouter([
{
path: '/login',
element: (
<>
<Suspense fallback={<PageLoader />}>
<Pages.LoginPage />
<ModalContainer />
</>
</Suspense>
),
},
{
path: '/register',
element: (
<>
<Suspense fallback={<PageLoader />}>
<Pages.RegisterPage />
<ModalContainer />
</>
</Suspense>
),
},
{
path: '/register/dog',
element: (
<>
<Suspense fallback={<PageLoader />}>
<Pages.RegisterDogPage />
<ModalContainer />
</>
</Suspense>
),
},
])
18 changes: 18 additions & 0 deletions src/utils/getParticle.ts
Original file line number Diff line number Diff line change
@@ -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 ? '이랑' : '랑'
}
Loading