Skip to content

Commit

Permalink
Feat/weather detail screen (#18)
Browse files Browse the repository at this point in the history
* feat(): add weather details screen

* feat(): small tweaks

* chore(): remove catch error in thunk

* feat(): Gemfile tweak, cocoapods version bump
  • Loading branch information
Dawqss authored Nov 16, 2024
1 parent a8f903f commit 4eb3ee4
Show file tree
Hide file tree
Showing 11 changed files with 205 additions and 45 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ module.exports = {
'no-param-reassign': 'off',
'prefer-arrow-callback': 'off',
'react/prop-types': 'off',
'react/jsx-props-no-spreading': 'off'
'react/jsx-props-no-spreading': 'off',
camelcase: 'off'
},
globals: {
__DEV__: true
Expand Down
2 changes: 2 additions & 0 deletions app/http/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ interface Snow {

interface Clouds {
today: number;
all: number;
}

interface WeatherDescription {
Expand All @@ -50,6 +51,7 @@ export interface WeatherItem {
snow: Snow | null;
clouds: Clouds;
weather: WeatherDescription[];
sys: { country: string };
}

export interface WeatherResponse {
Expand Down
29 changes: 21 additions & 8 deletions app/navigation/MainRouter.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import {
createStaticNavigation,
StaticParamList
} from '@react-navigation/native';
import { createStaticNavigation } from '@react-navigation/native';
import { MapCityListScreen } from '@screens/MapCityListScreen/MapCityListScreen.tsx';
import { WeatherDetailsScreen } from '@screens/WeatherDetailsScreen/WeatherDetailsScreen.tsx';
import { RootStackParamList, RouteNames } from '@navigation/types.ts';

/**
* Vars are used but airbnb config doesnt respect ts - TODO: tweak/fix eslint plugins
*/
export enum RouteNames {
// eslint-disable-next-line no-unused-vars
MapCityList = 'MapCityList',
// eslint-disable-next-line no-unused-vars
WeatherDetails = 'WeatherDetails'
}
/**
* Add here types for the screens that are passed by navigation
*/
export type RootStackParamList = {
[RouteNames.MapCityList]: {};
[RouteNames.WeatherDetails]: {
cityEntityId: number;
};
};

const RootStack = createNativeStackNavigator<RootStackParamList>({
screens: {
Expand All @@ -19,8 +34,6 @@ const RootStack = createNativeStackNavigator<RootStackParamList>({
}
});

type RootStackStaticParamList = StaticParamList<typeof RootStack>;

/**
* Override static props for navigation purposes
* useNavigation use it for checking possible routes
Expand All @@ -29,7 +42,7 @@ declare global {
// eslint-disable-next-line no-unused-vars
namespace ReactNavigation {
// eslint-disable-next-line no-unused-vars
interface RootParamList extends RootStackStaticParamList {}
interface RootParamList extends RootStackParamList {}
}
}

Expand Down
16 changes: 0 additions & 16 deletions app/navigation/types.ts

This file was deleted.

4 changes: 2 additions & 2 deletions app/screens/MapCityListScreen/MapCityListScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ export function MapCityListScreen() {
fetchCitiesWeatherInRadiusByLatLngThunk({
lat: FallbackLatLng.lat,
lon: FallbackLatLng.lng,
numberOfCities: 20,
radiusInKm: 20
numberOfCities: 50,
radiusInKm: 150
})
);
}, []);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { MapCityListItem } from '@screens/MapCityListScreen/components/MapCityLi
import type { ListRenderItem } from '@react-native/virtualized-lists';
import { WeatherItem } from '@http/types.ts';

const keyExtractor = (item: WeatherItem) => String(item.id);

export function MapCityListBottomSheet() {
const cities = useAppSelector(weatherCityListSelector);

Expand All @@ -20,7 +22,11 @@ export function MapCityListBottomSheet() {
return (
<BottomSheet snapPoints={['20%', '50%', '90%']}>
<BottomSheetView style={mapCityListScreenStyles.contentContainer}>
<FlatList data={cities} renderItem={renderItem} />
<FlatList
data={cities}
renderItem={renderItem}
keyExtractor={keyExtractor}
/>
</BottomSheetView>
</BottomSheet>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,31 @@
import React, { useCallback } from 'react';
import React, { useCallback, useMemo } from 'react';
import { Image, Text, View, ListRenderItemInfo } from 'react-native';
import { TouchableOpacity } from 'react-native-gesture-handler';

import { WeatherItem } from '@http/types.ts';
import { mapCityListItemStyles } from '@screens/MapCityListScreen/components/MapCityListBottomSheet/MapCityListItem/mapCityListItemStyles.ts';
import { getWeatherIconUri } from '@screens/MapCityListScreen/components/MapCityListBottomSheet/MapCityListItem/utils/getWeatherIconUri.ts';
import { useNavigation } from '@react-navigation/native';
import { RouteNames } from '@navigation/types.ts';
import { RouteNames } from '@navigation/MainRouter.tsx';

export function MapCityListItem({
item
}: ListRenderItemInfo<WeatherItem>): React.ReactElement {
const { navigate } = useNavigation();
const {
id: cityEntityId,
name,
main: { temp },
weather: [{ main: weatherType, icon }]
} = item;

const source = { uri: getWeatherIconUri(icon) };
const source = useMemo(() => ({ uri: getWeatherIconUri(icon) }), [icon]);

const onItemPress = useCallback(() => {
navigate(RouteNames.WeatherDetails);
navigate({
name: RouteNames.WeatherDetails,
params: { cityEntityId }
});
}, []);

return (
Expand Down
118 changes: 113 additions & 5 deletions app/screens/WeatherDetailsScreen/WeatherDetailsScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,118 @@
import React from 'react';
import { View, Text } from 'react-native';
import React, { useMemo } from 'react';
import { View, Text, Image, ScrollView } from 'react-native';

import { RootStackParamList, RouteNames } from '@navigation/MainRouter.tsx';
import { NativeStackScreenProps } from '@react-navigation/native-stack';
import { weatherCityListEntitySelectors } from '@state/features/weatherCityList/weatherCityListSelectors.ts';
import { useAppSelector } from '@state/hooks.ts';
import { weatherDetailsScreensStyles } from '@screens/WeatherDetailsScreen/weatherDetailsScreensStyles.ts';
import { getWeatherIconUri } from '@screens/MapCityListScreen/components/MapCityListBottomSheet/MapCityListItem/utils/getWeatherIconUri.ts';

export function WeatherDetailsScreen({
route: {
params: { cityEntityId }
}
}: NativeStackScreenProps<RootStackParamList, RouteNames.WeatherDetails>) {
const {
clouds,
name,
weather: [{ description, icon }],
main: {
feels_like,
grnd_level,
humidity,
pressure,
sea_level,
temp,
temp_min,
temp_max
},
wind: { deg: windDeg, speed: windSpeed },
sys: { country }
} = useAppSelector((state) =>
weatherCityListEntitySelectors.selectById(state, cityEntityId)
);

const table = useMemo(
() => [
{
name: 'Feels Like',
value: `${feels_like} °C`
},
{
name: 'Ground Level Pressure',
value: `${grnd_level} hPa`
},
{
name: 'Humidity',
value: `${humidity} %`
},
{
name: 'Pressure',
value: `${pressure} hPa`
},
{
name: 'Sea Level Pressure',
value: `${sea_level} hPa`
},
{
name: 'Temperature',
value: `${temp} °C`
},
{
name: 'Maximum Temperature',
value: `${temp_max} °C`
},
{
name: 'Minimum Temperature',
value: `${temp_min} °C`
},
{
name: 'Wind Direction',
value: `${windDeg} °`
},
{
name: 'Wind Speed',
value: `${windSpeed} m/s`
},
{
name: 'Country',
value: `${country}`
},
{
name: 'Cloudiness',
value: `${clouds.all || clouds.today} %`
}
],
[]
);

const source = useMemo(() => ({ uri: getWeatherIconUri(icon) }), [icon]);

export function WeatherDetailsScreen() {
return (
<View>
<Text>Konichiwa I am Weather Detail Screen</Text>
<View style={weatherDetailsScreensStyles.container}>
<View style={weatherDetailsScreensStyles.titleContainer}>
<View>
<Text style={weatherDetailsScreensStyles.title}>{name}</Text>
<Text style={weatherDetailsScreensStyles.subTitle}>
{description}
</Text>
</View>
<Image style={weatherDetailsScreensStyles.image} source={source} />
</View>
<ScrollView>
{table.map(({ name: rowName, value }) => (
<View
style={weatherDetailsScreensStyles.rowNameValue}
key={rowName + value}
>
<Text style={weatherDetailsScreensStyles.textValueName}>
{rowName}
</Text>
<Text style={weatherDetailsScreensStyles.textValue}>{value}</Text>
</View>
))}
</ScrollView>
</View>
);
}
42 changes: 42 additions & 0 deletions app/screens/WeatherDetailsScreen/weatherDetailsScreensStyles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { StyleSheet } from 'react-native';

export const weatherDetailsScreensStyles = StyleSheet.create({
container: {
flex: 1,
paddingHorizontal: 6,
paddingVertical: 18
},
titleContainer: {
flexDirection: 'row',
alignItems: 'center'
},
rowNameValue: {
height: 60,
padding: 12,
borderBottomWidth: 1,
borderColor: 'grey',
flexDirection: 'row'
},
title: {
fontSize: 25,
fontWeight: 'bold'
},
subTitle: {
paddingTop: 4,
fontSize: 16,
color: 'grey'
},
textValueName: {
fontSize: 18
},
textValue: {
fontSize: 18,
fontWeight: 'bold',
marginLeft: 'auto'
},
image: {
width: 70,
height: 70,
marginLeft: 'auto'
}
});
2 changes: 1 addition & 1 deletion ios/Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ source "https://rubygems.org"

gem "fastlane", '~> 2.224.0'
gem "dotenv"
gem "cocoapods", '~> 1.13.0'
gem "cocoapods", '~> 1.16.2'
14 changes: 7 additions & 7 deletions ios/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ GEM
benchmark (0.4.0)
bigdecimal (3.1.8)
claide (1.1.0)
cocoapods (1.13.0)
cocoapods (1.16.2)
addressable (~> 2.8)
claide (>= 1.0.2, < 2.0)
cocoapods-core (= 1.13.0)
cocoapods-core (= 1.16.2)
cocoapods-deintegrate (>= 1.0.3, < 2.0)
cocoapods-downloader (>= 1.6.0, < 2.0)
cocoapods-downloader (>= 2.1, < 3.0)
cocoapods-plugins (>= 1.0.0, < 2.0)
cocoapods-search (>= 1.0.0, < 2.0)
cocoapods-trunk (>= 1.6.0, < 2.0)
Expand All @@ -62,8 +62,8 @@ GEM
molinillo (~> 0.8.0)
nap (~> 1.0)
ruby-macho (>= 2.3.0, < 3.0)
xcodeproj (>= 1.23.0, < 2.0)
cocoapods-core (1.13.0)
xcodeproj (>= 1.27.0, < 2.0)
cocoapods-core (1.16.2)
activesupport (>= 5.0, < 8)
addressable (~> 2.8)
algoliasearch (~> 1.0)
Expand All @@ -74,7 +74,7 @@ GEM
public_suffix (~> 4.0)
typhoeus (~> 1.0)
cocoapods-deintegrate (1.0.5)
cocoapods-downloader (1.6.3)
cocoapods-downloader (2.1)
cocoapods-plugins (1.0.0)
nap
cocoapods-search (1.0.1)
Expand Down Expand Up @@ -287,7 +287,7 @@ PLATFORMS
arm64-darwin-23

DEPENDENCIES
cocoapods (~> 1.13.0)
cocoapods (~> 1.16.2)
dotenv
fastlane (~> 2.224.0)

Expand Down

0 comments on commit 4eb3ee4

Please sign in to comment.