-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
235 additions
and
0 deletions.
There are no files selected for viewing
141 changes: 141 additions & 0 deletions
141
video/ai-extensions/video-109-weather/AiExtensions.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
|
||
import SwiftUI | ||
|
||
struct GlowbyScreen: View { | ||
// This is a designated area where the OpenAI model can add or modify code. | ||
// To enable the screen, set this value to true | ||
// If it is false, the screen won't be visible in the app | ||
static let enabled = true | ||
|
||
// Change the title according to the assigned task | ||
// This will be the name of the screen in the app | ||
static let title = "Weather App" | ||
|
||
// Replace this with the generated SwiftUI view | ||
// Ensure the generated content shows up in the center of the screen | ||
// within a frame with a maximum width of 360.0. | ||
var body: some View { | ||
VStack { | ||
Spacer() | ||
HStack { | ||
Spacer() | ||
// This is where the AI-generated SwiftUI view will go | ||
VStack(alignment: .leading, spacing: 16) { | ||
// Header with Temperature | ||
HStack { | ||
Text("Weather App") | ||
.font(.largeTitle) | ||
.fontWeight(.bold) | ||
.foregroundColor(Color.gray.opacity(0.8)) | ||
Spacer() | ||
Text("30°C") | ||
.font(.title) | ||
.fontWeight(.semibold) | ||
.foregroundColor(.indigo) | ||
} | ||
.padding() | ||
.background(Color.white) | ||
.cornerRadius(8) | ||
.shadow(radius: 3) | ||
|
||
// City List with Animated Bars | ||
VStack(spacing: 16) { | ||
CityTemperatureView(city: "SF", percentage: 0.7, color: .blue) | ||
CityTemperatureView(city: "LA", percentage: 0.5, color: .green) | ||
CityTemperatureView(city: "NYC", percentage: 0.8, color: .red) | ||
CityTemperatureView(city: "EL PASO", percentage: 0.3, color: .yellow) | ||
} | ||
|
||
// Images from Lorem Picsum | ||
VStack(spacing: 16) { | ||
HStack(spacing: 16) { | ||
CityImageView(cityName: "San Francisco", imageURL: "https://picsum.photos/seed/sf/400/300") | ||
CityImageView(cityName: "Los Angeles", imageURL: "https://picsum.photos/seed/la/400/300") | ||
} | ||
HStack(spacing: 16) { | ||
CityImageView(cityName: "New York City", imageURL: "https://picsum.photos/seed/nyc/400/300") | ||
CityImageView(cityName: "El Paso", imageURL: "https://picsum.photos/seed/elpaso/400/300") | ||
} | ||
} | ||
} | ||
.frame(maxWidth: 360) | ||
Spacer() | ||
} | ||
Spacer() | ||
} | ||
} | ||
} | ||
|
||
struct CityTemperatureView: View { | ||
let city: String | ||
let percentage: CGFloat // Range from 0.0 to 1.0 | ||
let color: Color | ||
|
||
@State private var animatedPercentage: CGFloat = 0 | ||
|
||
var body: some View { | ||
HStack { | ||
Text(city) | ||
.font(.title2) | ||
.fontWeight(.medium) | ||
.foregroundColor(Color.gray.opacity(0.7)) | ||
.frame(width: 80, alignment: .leading) | ||
GeometryReader { geometry in | ||
ZStack(alignment: .leading) { | ||
Capsule() | ||
.frame(height: 10) | ||
.foregroundColor(Color.gray.opacity(0.3)) | ||
Capsule() | ||
.frame(width: geometry.size.width * animatedPercentage, height: 10) | ||
.foregroundColor(color) | ||
.animation(.easeOut(duration: 2), value: animatedPercentage) | ||
} | ||
.onAppear { | ||
self.animatedPercentage = percentage | ||
} | ||
} | ||
.frame(height: 10) | ||
} | ||
.padding(.horizontal) | ||
} | ||
} | ||
|
||
struct CityImageView: View { | ||
let cityName: String | ||
let imageURL: String | ||
|
||
@State private var showOverlay = false | ||
|
||
var body: some View { | ||
ZStack { | ||
AsyncImage(url: URL(string: imageURL)) { image in | ||
image.resizable() | ||
} placeholder: { | ||
Color.gray.opacity(0.2) | ||
} | ||
.aspectRatio(4/3, contentMode: .fill) | ||
.frame(width: 150, height: 100) | ||
.clipped() | ||
.cornerRadius(10) | ||
.shadow(radius: 5) | ||
.overlay( | ||
Group { | ||
if showOverlay { | ||
Color.black.opacity(0.5) | ||
.cornerRadius(10) | ||
Text(cityName) | ||
.font(.headline) | ||
.fontWeight(.semibold) | ||
.foregroundColor(.white) | ||
} | ||
} | ||
.animation(.easeInOut, value: showOverlay) | ||
) | ||
.onTapGesture { | ||
withAnimation { | ||
showOverlay.toggle() | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
<html> | ||
<head> | ||
<title>Weather App with Animations</title> | ||
<!-- Tailwind CSS CDN --> | ||
<script src="https://cdn.tailwindcss.com"></script> | ||
</head> | ||
<body class="bg-gray-100 min-h-screen"> | ||
<!-- Header with Temperature --> | ||
<div class="flex justify-between items-center p-6 bg-white shadow-md"> | ||
<h1 class="text-3xl font-bold text-gray-800">Weather App</h1> | ||
<div class="text-2xl font-semibold text-indigo-600">30°C</div> | ||
</div> | ||
<!-- City List with Animated Bars --> | ||
<div class="p-6"> | ||
<!-- SF --> | ||
<div class="mb-6"> | ||
<div class="flex items-center"> | ||
<div class="w-24 text-xl font-medium text-gray-700">SF</div> | ||
<div class="relative w-full h-4 bg-gray-300 rounded-full overflow-hidden ml-4"> | ||
<div class="absolute top-0 left-0 h-full bg-blue-500" data-percentage="70%"></div> | ||
</div> | ||
</div> | ||
</div> | ||
<!-- LA --> | ||
<div class="mb-6"> | ||
<div class="flex items-center"> | ||
<div class="w-24 text-xl font-medium text-gray-700">LA</div> | ||
<div class="relative w-full h-4 bg-gray-300 rounded-full overflow-hidden ml-4"> | ||
<div class="absolute top-0 left-0 h-full bg-green-500" data-percentage="50%"></div> | ||
</div> | ||
</div> | ||
</div> | ||
<!-- NYC --> | ||
<div class="mb-6"> | ||
<div class="flex items-center"> | ||
<div class="w-24 text-xl font-medium text-gray-700">NYC</div> | ||
<div class="relative w-full h-4 bg-gray-300 rounded-full overflow-hidden ml-4"> | ||
<div class="absolute top-0 left-0 h-full bg-red-500" data-percentage="80%"></div> | ||
</div> | ||
</div> | ||
</div> | ||
<!-- EL PASO --> | ||
<div class="mb-6"> | ||
<div class="flex items-center"> | ||
<div class="w-24 text-xl font-medium text-gray-700">EL PASO</div> | ||
<div class="relative w-full h-4 bg-gray-300 rounded-full overflow-hidden ml-4"> | ||
<div class="absolute top-0 left-0 h-full bg-yellow-500" data-percentage="30%"></div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
<!-- Images from Lorem Picsum --> | ||
<div class="p-6 grid grid-cols-2 gap-6"> | ||
<div class="relative group"> | ||
<img src="https://picsum.photos/seed/sf/400/300" alt="SF" class="w-full h-full object-cover rounded-lg shadow-lg"> | ||
<div class="absolute inset-0 bg-black bg-opacity-50 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity"> | ||
<span class="text-white text-xl font-semibold">San Francisco</span> | ||
</div> | ||
</div> | ||
<div class="relative group"> | ||
<img src="https://picsum.photos/seed/la/400/300" alt="LA" class="w-full h-full object-cover rounded-lg shadow-lg"> | ||
<div class="absolute inset-0 bg-black bg-opacity-50 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity"> | ||
<span class="text-white text-xl font-semibold">Los Angeles</span> | ||
</div> | ||
</div> | ||
<div class="relative group"> | ||
<img src="https://picsum.photos/seed/nyc/400/300" alt="NYC" class="w-full h-full object-cover rounded-lg shadow-lg"> | ||
<div class="absolute inset-0 bg-black bg-opacity-50 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity"> | ||
<span class="text-white text-xl font-semibold">New York City</span> | ||
</div> | ||
</div> | ||
<div class="relative group"> | ||
<img src="https://picsum.photos/seed/elpaso/400/300" alt="EL PASO" class="w-full h-full object-cover rounded-lg shadow-lg"> | ||
<div class="absolute inset-0 bg-black bg-opacity-50 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity"> | ||
<span class="text-white text-xl font-semibold">El Paso</span> | ||
</div> | ||
</div> | ||
</div> | ||
<!-- JavaScript for Animations --> | ||
<script> | ||
document.addEventListener('DOMContentLoaded', () => { | ||
const bars = document.querySelectorAll('[data-percentage]'); | ||
bars.forEach(bar => { | ||
const percentage = bar.getAttribute('data-percentage'); | ||
bar.style.width = '0'; | ||
setTimeout(() => { | ||
bar.style.transition = 'width 2s ease'; | ||
bar.style.width = percentage; | ||
}, 100); | ||
}); | ||
}); | ||
</script> | ||
</body> | ||
</html> |