From 45525c08d62d34a77d9ce7b971d2f7fb08743343 Mon Sep 17 00:00:00 2001 From: Digi <marton@szabomarci.hu> Date: Sun, 30 Mar 2025 10:24:28 +0200 Subject: [PATCH] finished weather app --- 20250327/my-app/app/_layout.tsx | 5 - 20250327/my-app/app/index.jsx | 317 +++++++++++++++++++++++++++--- 20250327/my-app/package-lock.json | 9 + 20250327/my-app/package.json | 1 + 4 files changed, 296 insertions(+), 36 deletions(-) delete mode 100644 20250327/my-app/app/_layout.tsx diff --git a/20250327/my-app/app/_layout.tsx b/20250327/my-app/app/_layout.tsx deleted file mode 100644 index d2a8b0b..0000000 --- a/20250327/my-app/app/_layout.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { Stack } from "expo-router"; - -export default function RootLayout() { - return <Stack />; -} diff --git a/20250327/my-app/app/index.jsx b/20250327/my-app/app/index.jsx index 7b3e3e4..b2ec029 100644 --- a/20250327/my-app/app/index.jsx +++ b/20250327/my-app/app/index.jsx @@ -1,43 +1,298 @@ import { useEffect, useState } from "react"; -import { View, Text, TextInput, Button, FlatList, StyleSheet, Alert } from "react-native"; +import { View, Text, TextInput, StyleSheet, Image, ScrollView, SafeAreaView, StatusBar, TouchableOpacity} from "react-native"; +import { Droplets, Droplet, Wind, Gauge, Eye, ThermometerSunIcon } from 'lucide-react'; const baseUrl = "http://api.weatherapi.com/v1/current.json?key=1232eaa82978466da1f81125252703&q="; -export default function Index() { - const [city, setCity] = useState(""); - - - const handlePress = () => { - console.log(city); +const WeatherScreen = ({ weatherData }) => { + if (!weatherData){ + return ( + <SafeAreaView style={styles.container}> + <View style={styles.locationContainer}> + <Text style={styles.loading}> + Adatok betöltése + </Text> + </View> + </SafeAreaView> + ) } - useEffect(() => { - async function fetchData() { - try { - const response = await fetch(`${baseUrl}Békéscsaba`); - const data = await response.json(); - console.log(data); - } catch (error) { - console.error(error); - } + const formatDateTime = (dateTimeStr) => { + const date = new Date(dateTimeStr) + const options = { + weekday: "long", + year: "numeric", + month: "long", + day: "numeric", + hour: "2-digit", + minute: "2-digit", } - fetchData(); - }, []); + return date.toLocaleDateString("hu-HU", options) + } return ( - <View> - <Text> - Időjárás app - </Text> - <Button - title="Keresés" - onPress={handlePress} /> - <TextInput - placeholder="Város" - value={city} - onChangeText={setCity} /> - </View> - ); + <SafeAreaView style={styles.container}> + <StatusBar/> + <ScrollView contentContainerStyle={styles.scrollContainer}> + <View style={styles.locationContainer}> + <Text style={styles.locationName}>{weatherData.location.name}</Text> + <Text style={styles.locationDetail}>{weatherData.location.country}</Text> + <Text style={styles.dateTime}>{formatDateTime(weatherData.location.localtime)}</Text> + </View> + + <View style={styles.mainWeatherContainer}> + <Image + source={{ uri: `https:${weatherData.current.condition.icon}`.replace("64x64", "128x128") }} + style={styles.weatherIcon} + /> + <Text style={styles.temperature}>{weatherData.current.temp_c}°C</Text> + <Text style={styles.weatherCondition}>{weatherData.current.condition.text}</Text> + <Text style={styles.feelsLike}>Hőérzet: {weatherData.current.feelslike_c}°C</Text> + </View> + + <View style={styles.detailsContainer}> + <View style={styles.detailRow}> + <View style={styles.detailItem}> + <Droplet style={styles.icon}/> + <Text style={styles.detailTitle}>Páratartalom</Text> + <Text style={styles.detailValue}>{weatherData.current.humidity}%</Text> + </View> + <View style={styles.detailItem}> + <Wind style={styles.icon} /> + <Text style={styles.detailTitle}>Szél</Text> + <Text style={styles.detailValue}>{weatherData.current.wind_kph} km/h</Text> + <Text style={styles.detailSubValue}>{weatherData.current.wind_dir}</Text> + </View> + </View> + + <View style={styles.detailRow}> + <View style={styles.detailItem}> + <Gauge style={styles.icon} /> + <Text style={styles.detailTitle}>Légnyomás</Text> + <Text style={styles.detailValue}>{weatherData.current.pressure_mb} mb</Text> + </View> + <View style={styles.detailItem}> + <Eye style={styles.icon} /> + <Text style={styles.detailTitle}>Látótávolság</Text> + <Text style={styles.detailValue}>{weatherData.current.vis_km} km</Text> + </View> + </View> + + <View style={styles.detailRow}> + <View style={styles.detailItem}> + <ThermometerSunIcon style={styles.icon} /> + <Text style={styles.detailTitle}>UV Index</Text> + <Text style={styles.detailValue}>{weatherData.current.uv}</Text> + </View> + <View style={styles.detailItem}> + <Droplets style={styles.icon}/> + <Text style={styles.detailTitle}>Csapadék</Text> + <Text style={styles.detailValue}>{weatherData.current.precip_mm} mm</Text> + </View> + </View> + </View> + </ScrollView> + </SafeAreaView> + ) } +const styles = StyleSheet.create({ + body: { + backgroundColor: "#1F2937", + }, + icon: { + color: "#8CBBF1" + }, + loading: { + color: "#FFFFFF", + fontSize: 25 + }, + container: { + flex: 1, + backgroundColor: "#1F2937", + }, + scrollContainer: { + padding: 20, + }, + locationContainer: { + alignItems: "center", + marginBottom: 20, + }, + locationName: { + fontSize: 32, + fontWeight: "bold", + color: "#FFFFFF", + }, + locationDetail: { + fontSize: 18, + color: "#E5E7EB", + marginTop: 4, + }, + dateTime: { + fontSize: 14, + color: "#9CA3AF", + marginTop: 8, + }, + mainWeatherContainer: { + alignItems: "center", + marginBottom: 30, + }, + weatherIcon: { + width: 128, + height: 128, + marginBottom: 10, + }, + temperature: { + fontSize: 64, + fontWeight: "bold", + color: "#FFFFFF", + }, + weatherCondition: { + fontSize: 24, + color: "#E5E7EB", + marginTop: 4, + }, + feelsLike: { + fontSize: 16, + color: "#9CA3AF", + marginTop: 8, + }, + detailsContainer: { + backgroundColor: "#374151", + borderRadius: 20, + padding: 20, + marginBottom: 20, + }, + detailRow: { + flexDirection: "row", + justifyContent: "space-between", + marginBottom: 20, + }, + detailItem: { + flex: 1, + alignItems: "center", + padding: 10, + }, + detailTitle: { + fontSize: 14, + color: "#9CA3AF", + marginTop: 8, + }, + detailValue: { + fontSize: 18, + fontWeight: "bold", + color: "#FFFFFF", + marginTop: 4, + }, + detailSubValue: { + fontSize: 14, + color: "#E5E7EB", + }, + headerContainer: { + backgroundColor: "#111827", + padding: 20, + borderBottomWidth: 1, + borderBottomColor: "#374151", + marginBottom: 10, + }, + headerTitle: { + fontSize: 28, + fontWeight: "bold", + color: "#FFFFFF", + textAlign: "center", + marginBottom: 20, + textShadowColor: "rgba(0, 0, 0, 0.75)", + textShadowOffset: { width: 1, height: 1 }, + textShadowRadius: 3, + }, + searchContainer: { + flexDirection: "row", + alignItems: "center", + marginBottom: 10, + }, + searchInput: { + flex: 1, + backgroundColor: "#374151", + borderRadius: 10, + padding: 12, + color: "#FFFFFF", + marginRight: 10, + fontSize: 16, + }, + searchButton: { + backgroundColor: "#3B82F6", + borderRadius: 10, + paddingVertical: 12, + paddingHorizontal: 20, + elevation: 2, + }, + searchButtonText: { + color: "#FFFFFF", + fontWeight: "bold", + fontSize: 16, + }, +}) + + + +// Example usage +export default function App() { + +async function fetchData(city) { + try { + const response = await fetch(`${baseUrl}${city}`); + const data = await response.json(); + if (response.status == 200){ + setWeatherData(data); + console.log(data); + } + + } catch (error) { + console.error(error); + } +} +// Sample data based on the provided object + const [weatherData, setWeatherData] = useState(null); + + const [city, setCity] = useState("Békéscsaba"); + + const handlePress = () => { + if (city){ + try { + fetchData(city); + } catch (error){ + console.error(error); + } + } + } + + useEffect(() => { + fetchData(city); + }, []); + + + return ( + <SafeAreaView style={styles.container}> + <View style={styles.headerContainer}> + <Text style={styles.headerTitle}>Időjárás app</Text> + + <View style={styles.searchContainer}> + <TextInput + style={styles.searchInput} + placeholder="Város" + placeholderTextColor="#9CA3AF" + value={city} + onChangeText={setCity} + /> + <TouchableOpacity style={styles.searchButton} onPress={handlePress}> + <Text style={styles.searchButtonText}>Keresés</Text> + </TouchableOpacity> + </View> + </View> + + <WeatherScreen weatherData={weatherData} /> + </SafeAreaView> + ) +} + diff --git a/20250327/my-app/package-lock.json b/20250327/my-app/package-lock.json index 1e90948..bf2e6e3 100644 --- a/20250327/my-app/package-lock.json +++ b/20250327/my-app/package-lock.json @@ -24,6 +24,7 @@ "expo-system-ui": "~4.0.8", "expo-web-browser": "~14.0.2", "firebase": "^11.5.0", + "lucide-react": "^0.485.0", "next": "^15.2.4", "react": "18.3.1", "react-dom": "18.3.1", @@ -10288,6 +10289,14 @@ "yallist": "^3.0.2" } }, + "node_modules/lucide-react": { + "version": "0.485.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.485.0.tgz", + "integrity": "sha512-NvyQJ0LKyyCxL23nPKESlr/jmz8r7fJO1bkuptSNYSy0s8VVj4ojhX0YAgmE1e0ewfxUZjIlZpvH+otfTnla8Q==", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", diff --git a/20250327/my-app/package.json b/20250327/my-app/package.json index f3366be..07f5bc9 100644 --- a/20250327/my-app/package.json +++ b/20250327/my-app/package.json @@ -31,6 +31,7 @@ "expo-system-ui": "~4.0.8", "expo-web-browser": "~14.0.2", "firebase": "^11.5.0", + "lucide-react": "^0.485.0", "next": "^15.2.4", "react": "18.3.1", "react-dom": "18.3.1",