EARLY ACCESS
Shared Project
Open in bitrigDownload Code
import SwiftUI
@main
struct WeatherApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct Weather {
let location: String
let temperature: Int
let condition: String
let icon: String
let high: Int
let low: Int
let humidity: Int
let windSpeed: Int
}
struct ContentView: View {
@State private var currentWeather = Weather(
location: "San Francisco",
temperature: 72,
condition: "Partly Cloudy",
icon: "cloud.sun.fill",
high: 75,
low: 62,
humidity: 65,
windSpeed: 8
)
@State private var forecast: [Weather] = [
Weather(location: "Today", temperature: 75, condition: "Sunny", icon: "sun.max.fill", high: 75, low: 62, humidity: 60, windSpeed: 5),
Weather(location: "Tomorrow", temperature: 68, condition: "Cloudy", icon: "cloud.fill", high: 70, low: 58, humidity: 75, windSpeed: 12),
Weather(location: "Wednesday", temperature: 74, condition: "Partly Cloudy", icon: "cloud.sun.fill", high: 76, low: 60, humidity: 55, windSpeed: 7),
Weather(location: "Thursday", temperature: 69, condition: "Rain", icon: "cloud.rain.fill", high: 71, low: 55, humidity: 85, windSpeed: 15),
Weather(location: "Friday", temperature: 73, condition: "Sunny", icon: "sun.max.fill", high: 78, low: 61, humidity: 45, windSpeed: 6)
]
var body: some View {
NavigationStack {
ScrollView {
VStack(spacing: 25) {
// Current Weather
VStack(spacing: 20) {
HStack {
Image(systemName: "location.fill")
.foregroundColor(.blue)
Text(currentWeather.location)
.font(.title2)
.fontWeight(.medium)
Spacer()
}
VStack(spacing: 10) {
Image(systemName: currentWeather.icon)
.font(.system(size: 80))
.foregroundColor(.blue)
Text("\(currentWeather.temperature)°")
.font(.system(size: 60, weight: .light))
Text(currentWeather.condition)
.font(.title3)
.foregroundColor(.secondary)
}
HStack(spacing: 40) {
VStack {
Text("H:\(currentWeather.high)°")
Text("L:\(currentWeather.low)°")
}
.font(.title3)
}
}
.padding(30)
.background(Color(.systemGray6))
.cornerRadius(20)
// Weather Details
LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 2), spacing: 15) {
WeatherDetailCard(title: "Humidity", value: "\(currentWeather.humidity)%", icon: "humidity")
WeatherDetailCard(title: "Wind", value: "\(currentWeather.windSpeed) mph", icon: "wind")
WeatherDetailCard(title: "UV Index", value: "3", icon: "sun.max")
WeatherDetailCard(title: "Visibility", value: "10 mi", icon: "eye")
}
// 5-Day Forecast
VStack(alignment: .leading, spacing: 15) {
HStack {
Image(systemName: "calendar")
.foregroundColor(.blue)
Text("5-Day Forecast")
.font(.headline)
Spacer()
}
VStack(spacing: 12) {
ForEach(forecast.indices, id: \.self) { index in
ForecastRow(weather: forecast[index])
if index < (forecast.count - 1) {
Divider()
}
}
}
}
.padding(20)
.background(Color(.systemGray6))
.cornerRadius(20)
}
.padding()
}
.navigationTitle("Weather")
.navigationBarTitleDisplayMode(.large)
}
}
}
struct WeatherDetailCard: View {
let title: String
let value: String
let icon: String
var body: some View {
VStack(spacing: 10) {
Image(systemName: icon)
.font(.title2)
.foregroundColor(.blue)
Text(value)
.font(.title2)
.fontWeight(.semibold)
Text(title)
.font(.caption)
.foregroundColor(.secondary)
}
.padding()
.background(Color(.systemBackground))
.cornerRadius(15)
.shadow(color: .black.opacity(0.1), radius: 5)
}
}
struct ForecastRow: View {
let weather: Weather
var body: some View {
HStack {
Text(weather.location)
.font(.body)
.fontWeight(.medium)
.frame(width: 80, alignment: .leading)
Spacer()
Image(systemName: weather.icon)
.font(.title3)
.foregroundColor(.blue)
.frame(width: 30)
Spacer()
HStack(spacing: 8) {
Text("\(weather.low)°")
.foregroundColor(.secondary)
Text("\(weather.high)°")
.fontWeight(.medium)
}
.font(.body)
}
.padding(.vertical, 4)
}
}