Skip to content

Commit

Permalink
Merge pull request #15 from h-yoshikawa44/feature/14-open_weather_map…
Browse files Browse the repository at this point in the history
…_api

APIをMetaWeather APIからOpenWeather APIへ移行
  • Loading branch information
h-yoshikawa44 authored Oct 28, 2023
2 parents 11ce24a + 2ea679a commit 139fb72
Show file tree
Hide file tree
Showing 43 changed files with 1,165 additions and 402 deletions.
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NEXT_PUBLIC_OPEN_WEATHER_MAP_API_KEY=
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ yarn-debug.log*
yarn-error.log*

# local env files
.env
.env.local
.env.development.local
.env.test.local
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Other major libraries
- [wicg-inert](https://github.com/WICG/inert)

API
- [MetaWeather API](https://www.metaweather.com/api/)
- [OpenWeather API](https://openweathermap.org/)

## Features

Expand Down Expand Up @@ -114,6 +114,9 @@ git clone https://github.com/h-yoshikawa44/ch-weather-app.git
or
git clone git@github.com:h-yoshikawa44/ch-weather-app.git

# Setting Env(Set each value according to your environment.)
cp .env.example .env

# Install dependencies
npm install

Expand Down
Binary file modified screenshots/desktop-menu.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified screenshots/desktop.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified screenshots/mobile-menu.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified screenshots/mobile.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 9 additions & 11 deletions src/components/model/weather/WeatherDay/WeatherDay.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
import { FC } from 'react';
import Image from 'next/image';
import { css } from '@emotion/react';
import { WeatherCode, TemperatureType } from '@/models/Weather';
import {
weatherIcons,
weatherNames,
temperatureUnits,
} from '@/constants/weather';
import { TemperatureType } from '@/models/Weather';
import { temperatureUnits } from '@/constants/weather';
import { colors } from '@/styles/constants';
import { raleway } from '@/styles/fonts';
import { dateFormat } from '@/utils/date';
Expand All @@ -15,7 +11,8 @@ import { convertCelsiusToFahrenheit } from '@/utils/weather';
type Props = {
date: string;
isTomorrow?: boolean;
weatherCode: WeatherCode;
weatherIconSrc: string;
weatherName: string;
minTemp: number;
maxTemp: number;
mode: TemperatureType;
Expand All @@ -24,7 +21,8 @@ type Props = {
const WeatherDayCard: FC<Props> = ({
date,
isTomorrow = false,
weatherCode,
weatherIconSrc,
weatherName,
minTemp,
maxTemp,
mode,
Expand All @@ -41,15 +39,15 @@ const WeatherDayCard: FC<Props> = ({
return (
<div css={weatherDay}>
<h4 css={weatherDayDate}>
<time dateTime={date}>
<time dateTime={date.toLocaleString()}>
{isTomorrow ? 'Tomorrow' : dateFormat(date)}
</time>
</h4>
<p css={weatherDayImgBlock}>
<Image
css={weatherDayImg}
src={weatherIcons[weatherCode]}
alt={weatherNames[weatherCode]}
src={weatherIconSrc}
alt={weatherName}
fill
/>
</p>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { css } from '@emotion/react';
import Card from '@/components/common/Card';
import { colors } from '@/styles/constants';
import { raleway } from '@/styles/fonts';
import { convertKmToMile } from '@/utils/weather';

const title = {
visibility: 'Visibility',
Expand All @@ -23,7 +24,7 @@ const WeatherHighlightCommon: FC<Props> = ({ type, value }) => {
let roundValue;
if (value) {
if (type === 'visibility') {
roundValue = Math.round(value * 10) / 10;
roundValue = Math.round(convertKmToMile(value)) / 10;
} else if (type === 'airPressure') {
roundValue = Math.round(value);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,18 @@ const WeatherLocationMenu: FC<Props> = ({
)}
<ul css={weatherLocationMenuLocationList}>
{locations?.map((location) => (
<li key={`${location.woeid}`}>
<li key={`${location.lat} - ${location.lon}`}>
<button
css={locationListItemButton}
onClick={() => {
handleSelectLocation(location);
handleLocationMenuClose();
}}
>
<span css={locationListItemButtonText}>{location.title}</span>
{/* OpenWeather API だと同都市名が複数返ることがあるので、苦肉の策で緯度経度も表示する */}
<span
css={locationListItemButtonText}
>{`${location.country} - ${location.name} (${location.lat}. ${location.lon})`}</span>
<NavigateNext size={24} />
</button>
</li>
Expand All @@ -85,7 +88,7 @@ const WeatherLocationMenu: FC<Props> = ({
);

// クライアント側の処理になるので、Next.js でのサーバ側ではポータルを使わないようにする
if (!process.browser) {
if (typeof window === 'undefined') {
return dom;
}
return createPortal(dom, document.body);
Expand Down
24 changes: 10 additions & 14 deletions src/components/model/weather/WeatherTop/WeatherTop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,17 @@ import { MyLocation } from '@emotion-icons/material-rounded/MyLocation';
import { Place } from '@emotion-icons/material-rounded/Place';
import Button from '@/components/common/Button';
import CircleButton from '@/components/common/CircleButton';
import { WeatherCode, TemperatureType } from '@/models/Weather';
import {
weatherIcons,
weatherNames,
temperatureUnits,
} from '@/constants/weather';
import { TemperatureType } from '@/models/Weather';
import { temperatureUnits } from '@/constants/weather';
import { breakPoint, colors } from '@/styles/constants';
import { raleway } from '@/styles/fonts';
import { dateFormat } from '@/utils/date';
import { convertCelsiusToFahrenheit } from '@/utils/weather';

type Props = {
today?: string;
weatherCode?: WeatherCode;
weatherIconSrc?: string;
weatherName?: string;
temperature?: number;
location?: string;
mode: TemperatureType;
Expand All @@ -28,7 +25,8 @@ type Props = {

const WeatherTop: FC<Props> = ({
today,
weatherCode,
weatherIconSrc,
weatherName,
temperature,
location,
mode,
Expand Down Expand Up @@ -59,11 +57,11 @@ const WeatherTop: FC<Props> = ({
<div css={[watherTopContents, watherTopContentLayout]}>
<div css={contentsBgImgBlock}>
<p css={contentsImgBlock}>
{weatherCode && (
{weatherIconSrc && weatherName && (
<Image
css={contentsImg}
src={weatherIcons[weatherCode]}
alt={weatherNames[weatherCode]}
src={weatherIconSrc}
alt={weatherName}
fill
/>
)}
Expand All @@ -73,9 +71,7 @@ const WeatherTop: FC<Props> = ({
<em>{roundTemp}</em>
{temperatureUnits[mode]}
</p>
<p css={contentsWeather}>
{weatherCode ? weatherNames[weatherCode] : '-'}
</p>
<p css={contentsWeather}>{weatherName ? weatherName : '-'}</p>
<div css={contentsSubTextBlock}>
<small css={contentsDate}>
Today -{' '}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,28 @@ import { FC } from 'react';
import { css } from '@emotion/react';
import { Navigation } from '@emotion-icons/material-rounded/Navigation';
import Card from '@/components/common/Card';
import { WindDirectionCompass } from '@/models/Weather';
import { windAngles } from '@/constants/weather';
import { colors } from '@/styles/constants';
import { raleway } from '@/styles/fonts';
import { convertDegToDirection, convertMpsToMph } from '@/utils/weather';

type Props = {
speed?: number;
compass?: WindDirectionCompass;
deg?: number;
};

const WeatherWindStatus: FC<Props> = ({ speed, compass }) => {
const WeatherWindStatus: FC<Props> = ({ speed, deg }) => {
return (
<Card>
<div css={weatherWindStatusLayout}>
<h4 css={weatherWindStatusTitle}>Wind status</h4>
<p css={weatherWindStatusSpeed}>
<em>{speed ? Math.round(speed) : '-'}</em>mph
<em>{speed ? Math.round(convertMpsToMph(speed)) : '-'}</em>mph
</p>
<p css={weatherWindStatusCompassBlock}>
<span css={compassBlockIconBg}>
<Navigation
css={compass ? compassBlockIcon(compass) : 'N'}
size={14}
/>
<Navigation css={compassBlockIcon(deg ?? 0)} size={14} />
</span>
<i css={compassBlockValue}>{compass}</i>
<i css={compassBlockValue}>{convertDegToDirection(deg ?? 0)}</i>
</p>
</div>
</Card>
Expand Down Expand Up @@ -79,10 +75,10 @@ const compassBlockIconBg = css`
border-radius: 50%;
`;

const compassBlockIcon = (compass: WindDirectionCompass) => {
const compassBlockIcon = (windDeg: number) => {
return css`
color: ${colors.gray6};
transform: rotate(${windAngles[compass]}deg);
transform: rotate(${windDeg}deg);
`;
};

Expand Down
49 changes: 24 additions & 25 deletions src/components/page/Home/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ import useLocationMenu from '@/hooks/useLocationMenu';
const Home: FC = () => {
const {
isLoading: isLoadingSetting,
errorMessage: errorMessageSetting,
currentLocation,
currentGeoLocation,
temperatureMode,
handleInitialCurrentLocation,
handleSelectLocation,
handleSwitchTemperatureMode,
} = useWeatherSetting();

const { isLoading, errorMessage, weather } = useWeather(
currentLocation?.woeId,
const { isLoading, errorMessage, weather, forecastWeather } = useWeather(
currentGeoLocation?.lat,
currentGeoLocation?.lon,
);

const {
Expand All @@ -52,20 +52,17 @@ const Home: FC = () => {
);
}

if (errorMessageSetting || errorMessage) {
if (errorMessage) {
return (
<main css={darkBgColor}>
<p css={guideMessageBlock}>
<small css={guideMessageText}>
{errorMessageSetting ? errorMessageSetting : errorMessage}
</small>
<small css={guideMessageText}>{errorMessage}</small>
</p>
</main>
);
}

const today = weather?.consolidated_weather[0];
const week = weather?.consolidated_weather.slice(1);
const today = new Date(Date.now()).toLocaleDateString();

return (
<Fragment>
Expand All @@ -79,10 +76,11 @@ const Home: FC = () => {
}
>
<WeatherTop
today={today?.applicable_date}
weatherCode={today?.weather_state_abbr}
temperature={today?.the_temp}
location={weather?.title}
today={today}
weatherIconSrc={weather?.weatherIcon}
weatherName={weather?.weatherName}
temperature={weather?.temp}
location={weather?.city}
mode={temperatureMode}
handleLocationMenuOpen={handleLocationMenuOpen}
handleInitialCurrentLocation={handleInitialCurrentLocation}
Expand Down Expand Up @@ -121,14 +119,15 @@ const Home: FC = () => {
</header>
<section css={rightAreaWeekSection}>
<div css={rightAreaWeekSectionLayout}>
{week?.map((day, index) => (
{forecastWeather?.map((day, index) => (
<WeatherDay
key={day.applicable_date}
date={day.applicable_date}
key={day.date}
date={day.date}
isTomorrow={index === 0}
weatherCode={day.weather_state_abbr}
minTemp={day.min_temp}
maxTemp={day.max_temp}
weatherIconSrc={day.weatherIcon}
weatherName={day.weatherName}
minTemp={day.minTemp}
maxTemp={day.maxTemp}
mode={temperatureMode}
/>
))}
Expand All @@ -141,17 +140,17 @@ const Home: FC = () => {
<div css={highlightSectionCardBlock}>
<div css={highlightSectionCardBlockLayout}>
<WeatherWindStatus
speed={today?.wind_speed}
compass={today?.wind_direction_compass}
speed={weather?.windSpeed}
deg={weather?.windDeg}
/>
<WeatherHumidity humidity={today?.humidity} />
<WeatherHumidity humidity={weather?.humidity} />
<WeatherHighlightCommon
type="visibility"
value={today?.visibility}
value={weather?.visibility}
/>
<WeatherHighlightCommon
type="airPressure"
value={today?.air_pressure}
value={weather?.airPressure}
/>
</div>
</div>
Expand Down
21 changes: 14 additions & 7 deletions src/config/ky.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import { Options } from 'ky-universal';
import ky, { Options } from 'ky-universal';

export type ApiType = 'inner' | 'outer';

const prefixUrls = {
const prefixUrls: { [key in ApiType]: string } = {
inner: 'api',
outer: 'https://www.metaweather.com/api',
outer: 'https://api.openweathermap.org',
};

export const getDefaultApiOptions = (apiType: ApiType) => {
return {
const api = ky.create({
retry: 0,
searchParams: {
appid: process.env.NEXT_PUBLIC_OPEN_WEATHER_MAP_API_KEY ?? '',
},
});

export const getExtendKy = (apiType: ApiType, options?: Options) => {
return api.extend({
prefixUrl: prefixUrls[apiType],
retry: 0,
} as Options;
...options,
});
};
Loading

1 comment on commit 139fb72

@vercel
Copy link

@vercel vercel bot commented on 139fb72 Oct 28, 2023

Choose a reason for hiding this comment

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

Please sign in to comment.