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

메인 화면 figma 프로토 타입 초기 퍼블리싱 / 컴포넌트 구조 설계 작업 #6

Merged
merged 12 commits into from
Nov 5, 2024
Merged
24 changes: 21 additions & 3 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
<!doctype html>
<html lang="en">
<html lang="ko">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<!-- Preconnect and DNS Prefetch for Faster Font Loading -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link rel="preconnect" href="https://cdn.jsdelivr.net" />
<link rel="dns-prefetch" href="https://fonts.googleapis.com" />
<link rel="dns-prefetch" href="https://fonts.gstatic.com" />
<link rel="dns-prefetch" href="https://cdn.jsdelivr.net" />

<!-- Google Fonts: Roboto, Noto Sans KR with Display Swap -->
<link
href="https://fonts.googleapis.com/css2?family=Roboto&family=Noto+Sans+KR&display=swap"
rel="stylesheet"
/>

<!-- Pretendard via JSDelivr CDN -->
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css"
/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
<title>세모 - 세종대의 모든 것</title>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

title 깔끔하게 잘 설정된 것 같아요!

</head>
<body>
<div id="root"></div>
Expand Down
23 changes: 23 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"@tanstack/react-query-devtools": "^5.59.8",
"axios": "^1.7.7",
"jotai": "^2.10.0",
"overlay-kit": "^1.4.1",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이번에 처음 알게되었습니다. 덕분에 좋은 것 하나 배웁니다.

"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.26.2",
Expand Down
Binary file added public/images/image.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 15 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
import { RouterProvider } from 'react-router-dom';
import { ReactOverlayProvider } from './configs/react/providers/OverlayProvider';
import { QueryProvider } from './configs/react/providers/QueryProvider';
import { routes } from './pages/routes';
import { SemoGlobalStyles } from './ui/styles/SemoGlobalStyles';
import { SemoThemeProvider } from './ui/styles/SemoThemeProvider';

function App() {
return (
<div className='App'>
<h1>Hello World</h1>
</div>
<ReactOverlayProvider>
<QueryProvider>
<RouterProvider router={routes} />
<SemoThemeProvider>
<SemoGlobalStyles />
</SemoThemeProvider>
</QueryProvider>
</ReactOverlayProvider>
);
}

Expand Down
3 changes: 0 additions & 3 deletions src/configs/react/libs/ReactToastify.tsx

This file was deleted.

3 changes: 3 additions & 0 deletions src/configs/react/libs/overlay-kit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { overlay } from 'overlay-kit';

export const overlayKit = overlay;
9 changes: 9 additions & 0 deletions src/configs/react/providers/OverlayProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { OverlayProvider } from 'overlay-kit';

export const ReactOverlayProvider = ({
children,
}: {
children: React.ReactNode;
}) => {
return <OverlayProvider>{children}</OverlayProvider>;
};
13 changes: 1 addition & 12 deletions src/configs/react/providers/QueryProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ import {
QueryClientProvider,
} from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import {
SpecificHttpException,
UnauthorizedException,
} from '@semo-client/configs/http-client/httpErrors';

export const QueryProvider = ({ children }: { children: ReactNode }) => {
const queryClient = useRef(
Expand All @@ -24,14 +20,7 @@ export const QueryProvider = ({ children }: { children: ReactNode }) => {
},
},
queryCache: new QueryCache({
onError: (error: unknown) => {
if (error instanceof UnauthorizedException) {
return;
}
if (error instanceof SpecificHttpException) {
return;
}
},
onError: () => {},
}),
}),
);
Expand Down
2 changes: 2 additions & 0 deletions src/features/background-image/model/backgroundImages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const FALLBACK_BACKGROUND_URL = 'images/image.jpg';
export const backgroundImagePaths: string[] = ['images/image.jpg'];
16 changes: 16 additions & 0 deletions src/features/background-image/service/fetchImageWithFallback.ts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이미지 불러오는 기능 분리 좋은 것 같아요.

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
interface FetchImageWithFallbackParams {
imageUrl: string;
onSuccess: () => void;
onError: () => void;
}

export const fetchImageWithFallback = ({
imageUrl,
onSuccess,
onError,
}: FetchImageWithFallbackParams) => {
const img = new Image();
img.src = imageUrl;
img.onload = onSuccess;
img.onerror = onError;
};
7 changes: 7 additions & 0 deletions src/features/background-image/service/getRandomImageUrl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { backgroundImagePaths } from '../model/backgroundImages';

export const getRandomImageUrl = () => {
return backgroundImagePaths[
Math.floor(Math.random() * backgroundImagePaths.length)
];
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import styled, { css } from 'styled-components';
import { fadeIn } from '@semo-client/ui/styles/keyframes/fades';
import { useBackgroundImageLoader } from '../hooks/useBackgroundImageLoader';

export const BackgroundImageView = () => {
const { backgroundImageUrl, isImageReady } = useBackgroundImageLoader();

return (
<>
<FullScreenBackground
imageUrl={backgroundImageUrl}
isImageReady={isImageReady}
>
<Overlay />
</FullScreenBackground>
</>
);
};

const FullScreenBackground = styled.div<{
imageUrl: string;
isImageReady: boolean;
}>`
width: 100vw;
height: 100vh;

background-image: ${({ imageUrl }) => `url(${imageUrl})`};
opacity: ${({ isImageReady }) => (isImageReady ? 1 : 0)};

${({ isImageReady }) =>
isImageReady &&
css`
animation: ${fadeIn} 0.35s linear;
`};

background-size: cover;
background-position: center;
background-repeat: no-repeat;

position: fixed;
top: 0;
left: 0;
z-index: -1;
`;

const Overlay = styled.div`
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.35);
position: absolute;
top: 0;
left: 0;
`;
25 changes: 25 additions & 0 deletions src/features/background-image/ui/hooks/useBackgroundImageLoader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { useState, useEffect } from 'react';
import { FALLBACK_BACKGROUND_URL } from '../../model/backgroundImages';
import { fetchImageWithFallback } from '../../service/fetchImageWithFallback';
import { getRandomImageUrl } from '../../service/getRandomImageUrl';

export const useBackgroundImageLoader = () => {
const [backgroundImageUrl, setBackgroundImageUrl] = useState<string>('');
const [isImageReady, setIsImageReady] = useState<boolean>(false);

useEffect(() => {
const imageUrl = getRandomImageUrl();
setBackgroundImageUrl(imageUrl);

fetchImageWithFallback({
imageUrl,
onSuccess: () => setIsImageReady(true),
onError: () => {
setBackgroundImageUrl(FALLBACK_BACKGROUND_URL);
setIsImageReady(true);
},
});
}, []);
Comment on lines +14 to +22
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍👍


return { backgroundImageUrl, isImageReady };
};
5 changes: 5 additions & 0 deletions src/features/clock/model/greetingMessageTemplates.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const greetingMessageTemplates = [
'길동 님은 잠 안 자시나요? A+ 자신 있으시겠죠? 😊',
'님! 오늘도 즐코하세요 😊',
'님! 오늘도 화이팅 😊',
];
11 changes: 11 additions & 0 deletions src/features/clock/service/formatDate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export const formatDate = (date: Date): string => {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');

const weekday = new Intl.DateTimeFormat('ko-KR', { weekday: 'short' }).format(
date,
);

return `${year}년 ${month}월 ${day}일 (${weekday})`;
};
7 changes: 7 additions & 0 deletions src/features/clock/service/formatTime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const formatTime = (date: Date): string => {
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');

return `${hours} ${minutes} ${seconds}`;
};
7 changes: 7 additions & 0 deletions src/features/clock/service/getRadomGreetingMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { greetingMessageTemplates } from '../model/greetingMessageTemplates';

export const getRandomGreetingMessage = () => {
return greetingMessageTemplates[
Math.floor(Math.random() * greetingMessageTemplates.length)
];
};
41 changes: 41 additions & 0 deletions src/features/clock/ui/components/Clock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import styled from 'styled-components';
import { formatDate } from '../../service/formatDate';
import { formatTime } from '../../service/formatTime';
import { useTimeTick } from '../hooks/useTimeTick';
import { GreetingMessage } from './GreetingMessage';

export const Clock = () => {
const { time } = useTimeTick();

return (
<ClockContainer>
<DateDisplay>{formatDate(time)}</DateDisplay>
<TimeDisplay>{formatTime(time)}</TimeDisplay>
<GreetingMessage />
</ClockContainer>
);
};

const ClockContainer = styled.div`
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;

margin: 88px auto 56px;
`;

const DateDisplay = styled.div`
font-size: 24px;
color: rgba(255, 255, 255, 0.7);
font-weight: 400;
`;

const TimeDisplay = styled.div`
width: 700px;
text-align: center;
font-size: 160px;
font-weight: 100;
line-height: 214.8px;
color: #ffffff;
`;
13 changes: 13 additions & 0 deletions src/features/clock/ui/components/GreetingMessage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import styled from 'styled-components';
import { useGreetingMessage } from '../hooks/useGreetingMessage';

export const GreetingMessage = () => {
const { greetingMessage } = useGreetingMessage();
return <StyledMessage>{greetingMessage}</StyledMessage>;
};

const StyledMessage = styled.div`
font-size: 24px;
color: #fff;
font-weight: 400;
`;
10 changes: 10 additions & 0 deletions src/features/clock/ui/hooks/useGreetingMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { useRef } from 'react';
import { getRandomGreetingMessage } from '../../service/getRadomGreetingMessage';

export const useGreetingMessage = () => {
const greetringMessageRef = useRef(getRandomGreetingMessage());

return {
greetingMessage: greetringMessageRef.current,
};
};
12 changes: 12 additions & 0 deletions src/features/clock/ui/hooks/useTimeTick.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { useEffect, useState } from 'react';

export const useTimeTick = () => {
const [time, setTime] = useState(new Date());

useEffect(() => {
const intervalId = setInterval(() => setTime(new Date()), 1000);
return () => clearInterval(intervalId);
}, []);

return { time };
};
Loading
Loading