86 lines
2.8 kB
1
defmodule BlogWeb.PostLive.Index do
2
use BlogWeb, :live_view
3
alias BlogWeb.Presence
4
alias Blog.Content
5
6
@presence_topic "blog_presence"
7
8
# TODO add meta tags
9
def mount(_params, _session, socket) do
10
if connected?(socket) do
11
reader_id = "reader_#{:crypto.strong_rand_bytes(8) |> Base.encode16()}"
12
13
{:ok, _} =
14
Presence.track(self(), @presence_topic, reader_id, %{
15
page: "index",
16
joined_at: DateTime.utc_now()
17
})
18
19
Phoenix.PubSub.subscribe(Blog.PubSub, @presence_topic)
20
end
21
22
posts = Blog.Content.Post.all()
23
%{tech: tech_posts, non_tech: non_tech_posts} = Content.categorize_posts(posts)
24
total_readers = Presence.list(@presence_topic) |> map_size()
25
26
{:ok,
27
assign(socket,
28
tech_posts: tech_posts,
29
non_tech_posts: non_tech_posts,
30
total_readers: total_readers
31
)}
32
end
33
34
def handle_info(%{event: "presence_diff"}, socket) do
35
total_readers = Presence.list(@presence_topic) |> map_size()
36
{:noreply, assign(socket, total_readers: total_readers)}
37
end
38
39
def render(assigns) do
40
~H"""
41
<div class="px-8 py-12">
42
<div class="max-w-7xl mx-auto">
43
<div class="mb-4 text-sm text-gray-500">
44
{@total_readers} {if @total_readers == 1, do: "person", else: "people"} browsing the blog
45
</div>
46
47
<div class="grid grid-cols-1 md:grid-cols-2 gap-8">
48
<%!-- Tech Posts Column --%>
49
<div>
50
<h2 class="text-2xl font-bold mb-6 pb-2 border-b">Tech & Programming</h2>
51
<div class="space-y-6">
52
<div :for={post <- @tech_posts} class="mb-8">
53
<.link navigate={~p"/post/#{post.slug}"}>
54
<h3 class="text-xl font-bold hover:text-blue-600 transition-colors">
55
{post.title}
56
</h3>
57
<p class="text-sm text-gray-600 mt-1">
58
{post.tags |> Enum.map(& &1.name) |> Enum.join(", ")}
59
</p>
60
</.link>
61
</div>
62
</div>
63
</div>
64
65
<%!-- Non-Tech Posts Column --%>
66
<div>
67
<h2 class="text-2xl font-bold mb-6 pb-2 border-b">Life & Everything Else</h2>
68
<div class="space-y-6">
69
<div :for={post <- @non_tech_posts} class="mb-8">
70
<.link navigate={~p"/post/#{post.slug}"}>
71
<h3 class="text-xl font-bold hover:text-blue-600 transition-colors">
72
{post.title}
73
</h3>
74
<p class="text-sm text-gray-600 mt-1">
75
{post.tags |> Enum.map(& &1.name) |> Enum.join(", ")}
76
</p>
77
</.link>
78
</div>
79
</div>
80
</div>
81
</div>
82
</div>
83
</div>
84
"""
85
end
86
end
87