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

[ 4주차 기본/심화 과제 ] 🌞수수의 기상예보⛱️ #10

Open
wants to merge 31 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
47347ae
[ feat ] 초기세팅
seojisoosoo May 11, 2023
af7b4b4
[ feat ] 페이지 레이아웃 구현
seojisoosoo May 11, 2023
cca13e8
[ feat ] 헤더구현 및 연결
seojisoosoo May 11, 2023
4431bee
[ design ] 디자인 수정
seojisoosoo May 11, 2023
162ad80
[ fix ] 라우터 수정
seojisoosoo May 12, 2023
c47d280
[ feat ] 날씨 api 함수 구현
seojisoosoo May 12, 2023
dda3e7a
[ feat ] 오늘의 날씨 데이터 불러오기 구현
seojisoosoo May 12, 2023
8c8655e
[ feat ] api 검색창 구현
seojisoosoo May 12, 2023
ad6d563
[ design ] 불필요한 글로벌 스타일 삭제
seojisoosoo May 12, 2023
ca3f9f0
[ design ] 글로벌 스타일 수정
seojisoosoo May 12, 2023
9b5121f
[ design ] 도시 입력란 스타일
seojisoosoo May 12, 2023
bd830e6
[ feat ] 날짜옵션과 도시 저장하는 함수 구현
seojisoosoo May 12, 2023
5fb3b32
[ feat ] 날씨 검색 버튼 클릭 함수 구현
seojisoosoo May 12, 2023
29aa6b3
[ feat ] 오늘 날씨 데이터 연결 성공
seojisoosoo May 12, 2023
a1b2e9e
[ feat ] 날씨 카드 구현
seojisoosoo May 12, 2023
5e63ff1
[ feat ] 날씨 카드 이미지 구현
seojisoosoo May 12, 2023
a577eaa
[ style ] 카드 이미지 로직 변경
seojisoosoo May 12, 2023
72e756f
[ style ] 이름 props로 보내는 로직으로 수정
seojisoosoo May 12, 2023
035a345
[ design ] 카드 마진 값 부여
seojisoosoo May 12, 2023
3d1d64a
[ style ] 오늘이면 날씨, 주간이면 날짜 뜨도록 수정
seojisoosoo May 12, 2023
5862c67
[ feat ] 주간 제목 날짜 스플릿으로 넣어주기
seojisoosoo May 12, 2023
1e3acb5
[ etc ] 오타 수정
seojisoosoo May 12, 2023
2a39e06
[ feat ] 주간 날씨 5개로 자르기
seojisoosoo May 12, 2023
e4ddb49
[ style ] 데이터 패칭 함수 커스텀 훅으로 변경
seojisoosoo May 12, 2023
44ebbc5
[ etc ] 불필요 코드 삭제
seojisoosoo May 12, 2023
c5e4d6a
[ feat ] 주간 데이터 커스텀 훅으로 연결
seojisoosoo May 12, 2023
827b174
[ etc ] 스켈레톤 시도
seojisoosoo May 12, 2023
cbda21e
[ design ] 스켈레톤 디자인
seojisoosoo May 12, 2023
6022d6b
[ feat ] 스켈레톤 구현
seojisoosoo May 12, 2023
44ce321
[ feat ] 주간 스켈레톤 구현
seojisoosoo May 12, 2023
7eea641
[ etc ] 제목 설정
seojisoosoo May 12, 2023
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
23 changes: 23 additions & 0 deletions week4/weather/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module.exports = {
parser: "@typescript-eslint/parser",
plugins: ["@typescript-eslint", "prettier"],
extends: [
"airbnb",
"plugin:import/errors",
"plugin:import/warnings",
"plugin:prettier/recommended",
"plugin:@typescript-eslint/recommended",
"prettier/@typescript-eslint",
],
rules: {
"linebreak-style": 0,
"import/prefer-default-export": 0,
"prettier/prettier": 0,
"import/extensions": 0,
"import/no-unresolved": 0,
"import/no-extraneous-dependencies": 0, // 테스트 또는 개발환경을 구성하는 파일에서는 devDependency 사용을 허용
"react/prop-types": 0,
"react/jsx-filename-extension": [2, { extensions: [".js", ".jsx", ".ts", ".tsx"] }],
"jsx-a11y/no-noninteractive-element-interactions": 0,
},
};
25 changes: 25 additions & 0 deletions week4/weather/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.env
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
8 changes: 8 additions & 0 deletions week4/weather/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"semi": true,
"tabWidth": 2,
"printWidth": 120,
"trailingComma": "all",
"bracketSameLine": true,
"endOfLine": "auto"
}
13 changes: 13 additions & 0 deletions week4/weather/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>수수의 기상예보</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
31 changes: 31 additions & 0 deletions week4/weather/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "weather",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint src --ext js,jsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
"dependencies": {
"axios": "^1.4.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-loading-skeleton": "^3.3.1",
"react-query": "^3.39.3",
"react-router-dom": "^6.11.1",
"styled-components": "^6.0.0-rc.1"
},
"devDependencies": {
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"@vitejs/plugin-react": "^4.0.0",
"eslint": "^8.38.0",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.3.4",
"vite": "^4.3.2"
}
}
1 change: 1 addition & 0 deletions week4/weather/public/vite.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions week4/weather/src/@components/common/header.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from "react";
import { styled } from "styled-components";

export default function Header() {
return (
<HeaderWrapper>
<Title>🌞수수의 기상예보⛱️</Title>
</HeaderWrapper>
);
}

const HeaderWrapper = styled.header`
display: flex;
justify-content: space-between;
align-items: center;

width: 100%;
padding: 2rem;

background-color: ${({ theme }) => theme.colors.blue};
`;

const Title = styled.h1`
${({ theme }) => theme.fonts.header};

Choose a reason for hiding this comment

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

font도 theme으로 적용! 깰꼬매요

color: ${({ theme }) => theme.colors.black};
cursor: pointer;
`;
23 changes: 23 additions & 0 deletions week4/weather/src/@components/common/pageLayout.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from "react";
import { styled } from "styled-components";
import Header from "./header";

export default function PageLayout(props) {
const { children } = props;
return (
<PageWrapper>
<Header />
{children}
</PageWrapper>
);
}

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

width: 100%;
height: 100%;
`;
10 changes: 10 additions & 0 deletions week4/weather/src/@components/common/search.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React, { useState } from "react";

export default function Search() {
return (
<>
<input placeholder="영어로 도시명 ex) seoul" />
<button type="button">날씨 검색</button>
</>
);
}
42 changes: 42 additions & 0 deletions week4/weather/src/@components/common/weatherCard.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React, { useEffect, useState } from "react";
import { styled } from "styled-components";
import { WEATHER_TYPE } from "../../core/weatherImg";

export default function WeatherCard(props) {
const { weatherData, title } = props;
const { main, clouds } = weatherData;
const [weatherImg, setWeatherImg] = useState("");

useEffect(() => {
weatherData?.weather &&
setWeatherImg(WEATHER_TYPE.filter((w) => w.description === weatherData?.weather[0]?.description)[0]?.imgURL);
Comment on lines +11 to +12

Choose a reason for hiding this comment

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

크... 옵셔널체이닝 폼 미쳤다 필터도 넘 깔끄매요

}, [weatherData]);

return (
<WeatherCardWrapper>
<h1>{title}</h1>
<img src={weatherImg} alt={title} />

Choose a reason for hiding this comment

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

리액트하면서 자꾸 alt 까먹게 되더라 잊지않고 꼬박꼬박 쓰는거 조하욥

<p>온도 | {main?.temp}</p>
<p>체감 온도 | {main?.feels_like}</p>
<p>
최저/최고 | {main?.temp_min}/{main?.temp_max}
</p>
<p>구름 | {clouds?.all}</p>
Copy link
Member

Choose a reason for hiding this comment

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

| 이거 이런식으로 하는구나!
나는 보통 after: content 처리해서 가상선택자로 만들어주거든!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

오오 이거 좋다!! 오빠는 before after 활용을 참 잘하는 것 같아용!

</WeatherCardWrapper>
);
}

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

margin: 1rem;
padding: 2rem;

border: 0.3rem solid ${({ theme }) => theme.colors.blue};
border-radius: 1rem;
background-color: ${({ theme }) => theme.colors.skyblue};
${({ theme }) => theme.fonts.title}
`;
67 changes: 67 additions & 0 deletions week4/weather/src/@components/skeleton/SkeletonTemplate.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React from "react";
import { keyframes, styled } from "styled-components";

export default function SkeletonTemplate() {
return (
<SkeletonBoxWrapper>
<Title></Title>
<Img></Img>
<Text></Text>
Comment on lines +7 to +9

Choose a reason for hiding this comment

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

질문! 요런건 그냥 어차피 InnerHTML 안들어가니까

<Title/>

이렇게 들어가면 안되는걸까유??

Copy link
Contributor Author

Choose a reason for hiding this comment

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

오 완전 맞아요!! 그렇게 고쳐야징

</SkeletonBoxWrapper>
);
}

const loading = keyframes`
0% {
transform: translateX(0);
}
50%,
100% {
transform: translateX(45rem);
}
`;

const SkeletonBoxWrapper = styled.section`
width: 28rem;
height: 40rem;

margin: 1rem;

background-color: #ddd;
border-radius: 1rem;

overflow: hidden;
`;

const Title = styled.div`
width: 25rem;
height: 3rem;

margin: 1.5rem 0 0.5rem 0;

background-color: rgba(145, 145, 145, 0.1);

animation: ${loading} 4s infinite;
`;

const Img = styled.div`
width: 25rem;
height: 25rem;

margin: 0.5rem;

background-color: rgba(145, 145, 145, 0.1);

animation: ${loading} 4s infinite;
`;

const Text = styled.div`
width: 25rem;
height: 8rem;

margin: 0.5rem;

background-color: rgba(145, 145, 145, 0.1);

animation: ${loading} 4s infinite;
`;
25 changes: 25 additions & 0 deletions week4/weather/src/@components/todayWeather/todayWeatherInfo.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import WeatherCard from "../common/weatherCard";
import useWeather from "../../hooks/useWeather";
import ErrorPage from "../../@pages/errorPage";
import SkeletonTemplate from "../skeleton/skeletonTemplate";

export default function DetailWeatherInfo() {
const { area } = useParams();
const { fetchTodayWeatherInfo, isError, todayData, isLoading } = useWeather();

useEffect(() => {
fetchTodayWeatherInfo(area);
}, []);

useEffect(() => {
fetchTodayWeatherInfo(area);
}, [area]);

if (isError) {
return <ErrorPage />;
}

return <>{isLoading ? <SkeletonTemplate /> : <WeatherCard weatherData={todayData} title={todayData.name} />}</>;
}
Comment on lines +20 to +25

Choose a reason for hiding this comment

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

오오오 여기 리턴으로 isError 조건까지 한번에 처리해줄 수 잇지 아늘까?!

Suggested change
if (isError) {
return <ErrorPage />;
}
return <>{isLoading ? <SkeletonTemplate /> : <WeatherCard weatherData={todayData} title={todayData.name} />}</>;
}
return <>{isError? <ErrorPage /> :
isLoading ? <SkeletonTemplate /> : <WeatherCard weatherData={todayData} title={todayData.name} />}</>;
}

요런 늑낌스로.. 소심한 제안

Copy link
Contributor Author

Choose a reason for hiding this comment

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

이 방법도 죠타! 보통 공식문서들에서

  if (isError) {
    return <ErrorPage />;
  }

이렇게 많이들 쓰길래 이렇게 표현해보았는데, 숭희 제안대로 써보는 것도 좋은 것 같아용!!

45 changes: 45 additions & 0 deletions week4/weather/src/@components/weekWeather/weekWeatherInfo.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React, { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import WeatherCard from "../common/weatherCard";
import { styled } from "styled-components";
import useWeather from "../../hooks/useWeather";
import ErrorPage from "../../@pages/errorPage";
import SkeletonTemplate from "../skeleton/skeletonTemplate";

export default function WeekWeatherInfo() {
const { area } = useParams();
const { fetchWeekWeatherInfo, isError, weekDatas, isLoading } = useWeather();

useEffect(() => {
fetchWeekWeatherInfo(area);
}, []);

useEffect(() => {
fetchWeekWeatherInfo(area);
}, [area]);

if (isError) {
return <ErrorPage />;
}
Copy link
Member

Choose a reason for hiding this comment

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

뭔가 이렇게 미리 돌리는게 좋은가?!
뭔가 가독성 적으로는 early return 같은 느낌이라 좋은거같네!
나도 한번 이렇게 짜봐야겟다 나는 맨날

isError ? : isLoading ? : 약간 이런식으로 했거든!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

오호! 둘 다 좋은 방법인 것 같긴 해용! 공식 문서들에서 보통 저렇게 미리 돌리길래 따라해봐쎠!


return (
<CardWrapper>
{weekDatas.list?.slice(0, 5).map((weatherData, i) => (
<>
{isLoading ? (
<SkeletonTemplate />
) : (
<WeatherCard key={i} weatherData={weatherData} title={weatherData?.dt_txt?.split(" ")[0]} />
)}
</>
))}
</CardWrapper>
);
}

const CardWrapper = styled.section`
display: flex;
flex-wrap: wrap;

width: 100rem;
`;
21 changes: 21 additions & 0 deletions week4/weather/src/@pages/errorPage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from "react";
import { styled } from "styled-components";

export default function ErrorPage() {
return (
<ErrorPageWrapper>
<ErrorMessage>Error</ErrorMessage>
</ErrorPageWrapper>
);
}

const ErrorMessage = styled.h1`
${({ theme }) => theme.fonts.header}
`;

const ErrorPageWrapper = styled.div`
width: 100%;
height: 100vh;

background-color: ${({ theme }) => theme.fonts.blue};
`;
Loading