Skip to content

Instantly share code, notes, and snippets.

@st3fan
Created April 29, 2023 13:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save st3fan/d4b0f6be0f513e75990ff76f98e7f25e to your computer and use it in GitHub Desktop.
Save st3fan/d4b0f6be0f513e75990ff76f98e7f25e to your computer and use it in GitHub Desktop.
defmodule WeatherWeb.WeatherLive do
use WeatherWeb, :live_view
@owm_url "https://api.openweathermap.org/data/2.5/weather?units=metric&lat=43.8999464&lon=-78.9408778&appid=XXX"
defmodule WeatherWeb.WeatherLive.WeatherSummary do
defstruct [:temperature, :name, :description, :icon]
end
alias WeatherWeb.WeatherLive.WeatherSummary
def parse_weather(body) do
case Jason.decode(body) do
{:ok, %{"name" => name, "main" => %{"temp" => temp }, "weather" => [%{"description" => description, "main" => icon} | _]}}
-> {:ok, %WeatherSummary{temperature: temp, name: name, description: description, icon: icon}}
{:error, _}
-> {:error, "Error decoding"}
end
end
def fetch_weather(url) do
case Finch.build(:get, url) |> Finch.request(Weather.Finch) do
{:ok, %Finch.Response{status: 200, body: body}}
-> {:ok, body}
{_, _}
-> {:error, "Error fetching"}
end
end
def get_weather() do
with {:ok, body} <- fetch_weather(@owm_url), {:ok, weather} <- parse_weather(body) do
{:ok, weather}
end
end
#
def mount(_params, _session, socket) do
Task.async(fn ->
{:get_weather, get_weather()}
end)
{:ok, assign(socket, loading: true, weather: nil, error: nil)}
end
def handle_info({ref, {:get_weather, result}}, socket) do
Process.demonitor(ref, [:flush])
IO.inspect(result)
case result do
{:ok, weather}
-> {:noreply, assign(socket, loading: false, weather: weather, date: "April 28", error: nil)}
{:error, error}
-> {:noreply, assign(socket, loading: false, weather: nil, error: error)}
end
end
attr :icon, :string, required: true
def weather_icon(%{:icon => "Clouds"} = assigns) do
~H"""
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="w-32 h-32 p-6 dark:text-yellow-400 fill-current">
<path d="M256,104c-83.813,0-152,68.187-152,152s68.187,152,152,152,152-68.187,152-152S339.813,104,256,104Zm0,272A120,120,0,1,1,376,256,120.136,120.136,0,0,1,256,376Z"></path>
<rect width="32" height="48" x="240" y="16"></rect>
<rect width="32" height="48" x="240" y="448"></rect>
<rect width="48" height="32" x="448" y="240"></rect>
<rect width="48" height="32" x="16" y="240"></rect>
<rect width="32" height="45.255" x="400" y="393.373" transform="rotate(-45 416 416)"></rect>
<rect width="32.001" height="45.255" x="80" y="73.373" transform="rotate(-45 96 96)"></rect>
<rect width="45.255" height="32" x="73.373" y="400" transform="rotate(-45.001 96.002 416.003)"></rect>
<rect width="45.255" height="32.001" x="393.373" y="80" transform="rotate(-45 416 96)"></rect>
</svg>
"""
end
def weather_icon(assigns) do
~H"""
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="w-32 h-32 p-6 dark:text-yellow-400 fill-current">
<path d="M256,104c-83.813,0-152,68.187-152,152s68.187,152,152,152,152-68.187,152-152S339.813,104,256,104Zm0,272A120,120,0,1,1,376,256,120.136,120.136,0,0,1,256,376Z"></path>
<rect width="32" height="48" x="240" y="16"></rect>
<rect width="32" height="48" x="240" y="448"></rect>
<rect width="48" height="32" x="448" y="240"></rect>
<rect width="48" height="32" x="16" y="240"></rect>
<rect width="32" height="45.255" x="400" y="393.373" transform="rotate(-45 416 416)"></rect>
<rect width="32.001" height="45.255" x="80" y="73.373" transform="rotate(-45 96 96)"></rect>
<rect width="45.255" height="32" x="73.373" y="400" transform="rotate(-45.001 96.002 416.003)"></rect>
<rect width="45.255" height="32.001" x="393.373" y="80" transform="rotate(-45 416 96)"></rect>
</svg>
"""
end
def render(assigns) do
~H"""
<div :if={@weather} class="flex flex-col items-center p-8 rounded-md w-60 sm:px-12 bg-gray-200 text-gray-900">
<div class="text-center">
<h2 class="text-xl font-semibold"><%= @weather.name %></h2>
<p class="text-sm dark:text-gray-400"><%= @date %></p>
</div>
<.weather_icon icon={@weather.icon}/>
<div class="mb-2 text-3xl font-semibold">
<%= round(@weather.temperature) %>°
<span class="mx-1 font-normal">/</span>
<%= round(@weather.temperature) %>°
</div>
<p class="dark:text-gray-400"><%= @weather.description %></p>
</div>
"""
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment