196 lines
9.1 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
page_title: "Tidbits & Thoughts - A Retro Hacker Blog",
32
cursor_position: nil
33
)}
34
end
35
36
def handle_info(%{event: "presence_diff"}, socket) do
37
total_readers = Presence.list(@presence_topic) |> map_size()
38
{:noreply, assign(socket, total_readers: total_readers)}
39
end
40
41
def handle_event("mousemove", %{"x" => x, "y" => y}, socket) do
42
{:noreply, assign(socket, cursor_position: %{x: x, y: y})}
43
end
44
45
def render(assigns) do
46
~H"""
47
<div
48
class="py-12 px-4 sm:px-6 lg:px-8 min-h-screen"
49
id="cursor-tracker-container"
50
phx-hook="CursorTracker"
51
>
52
<%= if @cursor_position do %>
53
<div class="fixed top-4 right-4 bg-gradient-to-r from-fuchsia-500 to-cyan-500 text-white px-3 py-1 rounded-lg shadow-md text-sm font-mono z-50">
54
x: <%= @cursor_position.x %>, y: <%= @cursor_position.y %>
55
</div>
56
57
<!-- Full screen crosshair with gradient and smooth transitions -->
58
<div class="fixed inset-0 pointer-events-none z-40">
59
<!-- Horizontal line across entire screen with gradient -->
60
<div
61
class="absolute w-full h-0.5 opacity-40 transition-all duration-200 ease-out"
62
style={"top: #{@cursor_position.y}px; background: linear-gradient(to right, #d946ef, #0891b2);"}
63
></div>
64
65
<!-- Vertical line across entire screen with gradient -->
66
<div
67
class="absolute h-full w-0.5 opacity-40 transition-all duration-200 ease-out"
68
style={"left: #{@cursor_position.x}px; background: linear-gradient(to bottom, #d946ef, #0891b2);"}
69
></div>
70
</div>
71
<% end %>
72
<div class="max-w-7xl mx-auto">
73
<!-- Header with retro styling -->
74
<header class="mb-12 text-center">
75
<div class="inline-block p-1 bg-gradient-to-r from-fuchsia-500 to-cyan-500 rounded-lg shadow-lg mb-6">
76
<h1 class="text-4xl md:text-5xl font-bold bg-white px-6 py-3 rounded-md">
77
<span class="text-transparent bg-clip-text bg-gradient-to-r from-fuchsia-600 to-cyan-600">
78
Thoughts & Tidbits
79
</span>
80
</h1>
81
</div>
82
83
<div class="flex justify-center items-center space-x-2 text-sm text-gray-600 mb-4">
84
<div class="inline-flex items-center px-3 py-1 rounded-full bg-gradient-to-r from-fuchsia-100 to-cyan-100 border border-fuchsia-200">
85
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mr-1 text-fuchsia-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
86
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z" />
87
</svg>
88
<span><%= @total_readers %> <%= if @total_readers == 1, do: "person", else: "people" %> browsing</span>
89
</div>
90
</div>
91
92
<p class="text-gray-600 max-w-2xl mx-auto">
93
A collection of thoughts on technology, life, and weird little things I make.
94
</p>
95
</header>
96
97
<!-- Two column layout for posts -->
98
<div class="grid grid-cols-1 md:grid-cols-3 gap-8">
99
<!-- Tech Posts Column -->
100
<div class="bg-gradient-to-br from-fuchsia-50 to-cyan-50 rounded-xl p-6 shadow-lg border border-fuchsia-100">
101
<div class="flex items-center mb-6">
102
<div class="w-3 h-3 rounded-full bg-fuchsia-400 mr-2"></div>
103
<div class="w-3 h-3 rounded-full bg-cyan-400 mr-2"></div>
104
<div class="w-3 h-3 rounded-full bg-indigo-400 mr-4"></div>
105
<h2 class="text-2xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-fuchsia-600 to-cyan-600">
106
Tech & Programming
107
</h2>
108
</div>
109
110
<div class="space-y-4">
111
<%= for post <- @tech_posts do %>
112
<div class="group bg-white rounded-lg p-4 shadow-sm hover:shadow-md transition-all duration-300 border-l-4 border-fuchsia-400">
113
<.link navigate={~p"/post/#{post.slug}"} class="block">
114
<h3 class="text-xl font-bold text-gray-800 group-hover:text-fuchsia-600 transition-colors">
115
<%= post.title %>
116
</h3>
117
<div class="flex flex-wrap gap-2 mt-2">
118
<%= for tag <- post.tags do %>
119
<span class="inline-block px-2 py-1 bg-gradient-to-r from-fuchsia-100 to-cyan-100 rounded-full text-xs font-medium text-gray-700">
120
<%= tag.name %>
121
</span>
122
<% end %>
123
</div>
124
</.link>
125
</div>
126
<% end %>
127
</div>
128
</div>
129
130
<!-- Non-Tech Posts Column -->
131
<div class="bg-gradient-to-br from-cyan-50 to-fuchsia-50 rounded-xl p-6 shadow-lg border border-cyan-100">
132
<div class="flex items-center mb-6">
133
<div class="w-3 h-3 rounded-full bg-cyan-400 mr-2"></div>
134
<div class="w-3 h-3 rounded-full bg-fuchsia-400 mr-2"></div>
135
<div class="w-3 h-3 rounded-full bg-indigo-400 mr-4"></div>
136
<h2 class="text-2xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-cyan-600 to-fuchsia-600">
137
Life & Everything Else
138
</h2>
139
</div>
140
141
<div class="space-y-4">
142
<%= for post <- @non_tech_posts do %>
143
<div class="group bg-white rounded-lg p-4 shadow-sm hover:shadow-md transition-all duration-300 border-l-4 border-cyan-400">
144
<.link navigate={~p"/post/#{post.slug}"} class="block">
145
<h3 class="text-xl font-bold text-gray-800 group-hover:text-cyan-600 transition-colors">
146
<%= post.title %>
147
</h3>
148
<div class="flex flex-wrap gap-2 mt-2">
149
<%= for tag <- post.tags do %>
150
<span class="inline-block px-2 py-1 bg-gradient-to-r from-cyan-100 to-fuchsia-100 rounded-full text-xs font-medium text-gray-700">
151
<%= tag.name %>
152
</span>
153
<% end %>
154
</div>
155
</.link>
156
</div>
157
<% end %>
158
</div>
159
</div>
160
161
<!-- Non-Tech Posts Column -->
162
<div class="bg-gradient-to-br from-cyan-50 to-fuchsia-50 rounded-xl p-6 shadow-lg border border-cyan-100">
163
<div class="flex items-center mb-6">
164
<div class="w-3 h-3 rounded-full bg-cyan-400 mr-2"></div>
165
<div class="w-3 h-3 rounded-full bg-fuchsia-400 mr-2"></div>
166
<div class="w-3 h-3 rounded-full bg-indigo-400 mr-4"></div>
167
<h2 class="text-2xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-cyan-600 to-fuchsia-600">
168
Tech Demos
169
</h2>
170
</div>
171
172
<div class="space-y-4">
173
<%= for post <- @non_tech_posts do %>
174
<div class="group bg-white rounded-lg p-4 shadow-sm hover:shadow-md transition-all duration-300 border-l-4 border-cyan-400">
175
<.link navigate={~p"/post/#{post.slug}"} class="block">
176
<h3 class="text-xl font-bold text-gray-800 group-hover:text-cyan-600 transition-colors">
177
<%= "Reddit Links Feed" %>
178
</h3>
179
</.link>
180
</div>
181
<% end %>
182
</div>
183
</div>
184
</div>
185
</div>
186
187
<!-- Retro footer -->
188
<footer class="mt-16 text-center">
189
<div class="inline-block px-4 py-2 bg-gradient-to-r from-fuchsia-100 to-cyan-100 rounded-full text-sm text-gray-700">
190
<span class="font-mono">/* Crafted with ♥ and Elixir */</span>
191
</div>
192
</footer>
193
</div>
194
"""
195
end
196
end
197