tangled
alpha
login
or
join now
arabica.social
/
arabica
7
fork
atom
Coffee journaling on ATProto (alpha)
alpha.arabica.social
coffee
7
fork
atom
overview
issues
pulls
pipelines
feat: show variety in brew card
pdewey.com
1 week ago
6c3c2b12
11c8ac0b
verified
This commit was signed with the committer's
known signature
.
pdewey.com
SSH Key Fingerprint:
SHA256:ePOVkJstqVLchGK8m9/OGQG+aFNHD5XN3xjvW9wKCA4=
+58
-86
3 changed files
expand all
collapse all
unified
split
internal
web
components
profile_brew_card.templ
shared.templ
pages
feed.templ
+4
-28
internal/web/components/profile_brew_card.templ
···
126
<!-- Bean info with rating -->
127
<div class="flex items-start justify-between gap-3 mb-3">
128
<div class="flex-1 min-w-0">
129
-
if brew.Bean != nil {
130
-
<div class="font-bold text-brown-900 text-base">
131
-
if brew.Bean.Name != "" {
132
-
{ brew.Bean.Name }
133
-
} else {
134
-
{ brew.Bean.Origin }
135
-
}
136
-
</div>
137
-
if brew.Bean.Roaster != nil && brew.Bean.Roaster.Name != "" {
138
-
<div class="text-sm text-brown-700 mt-0.5">
139
-
<span class="font-medium">🏭 { brew.Bean.Roaster.Name }</span>
140
-
</div>
141
-
}
142
-
<div class="text-xs text-brown-600 mt-1 flex flex-wrap gap-x-2 gap-y-0.5">
143
-
if brew.Bean.Origin != "" {
144
-
<span class="inline-flex items-center gap-0.5">📍 { brew.Bean.Origin }</span>
145
-
}
146
-
if brew.Bean.RoastLevel != "" {
147
-
<span class="inline-flex items-center gap-0.5">🔥 { brew.Bean.RoastLevel }</span>
148
-
}
149
-
if brew.Bean.Process != "" {
150
-
<span class="inline-flex items-center gap-0.5">🌱 { brew.Bean.Process }</span>
151
-
}
152
-
if brew.CoffeeAmount > 0 {
153
-
<span class="inline-flex items-center gap-0.5">⚖️ { fmt.Sprintf("%dg", brew.CoffeeAmount) }</span>
154
-
}
155
-
</div>
156
-
}
157
</div>
158
if brew.Rating > 0 {
159
<span class="badge-rating">
···
126
<!-- Bean info with rating -->
127
<div class="flex items-start justify-between gap-3 mb-3">
128
<div class="flex-1 min-w-0">
129
+
@BeanSummary(BeanSummaryProps{
130
+
Bean: brew.Bean,
131
+
CoffeeAmount: brew.CoffeeAmount,
132
+
})
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
133
</div>
134
if brew.Rating > 0 {
135
<span class="badge-rating">
+47
-1
internal/web/components/shared.templ
···
1
package components
2
3
-
import "arabica/internal/web/bff"
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
4
5
// EmptyStateProps defines properties for empty state messaging
6
type EmptyStateProps struct {
···
1
package components
2
3
+
import (
4
+
"arabica/internal/models"
5
+
"arabica/internal/web/bff"
6
+
"fmt"
7
+
)
8
+
9
+
// BeanSummaryProps defines props for displaying bean metadata inline.
10
+
// Used in both bean feed cards and brew feed cards.
11
+
type BeanSummaryProps struct {
12
+
Bean *models.Bean
13
+
CoffeeAmount int // if > 0, shows "⚖️ Xg" (brew context)
14
+
}
15
+
16
+
// BeanSummary renders the bean name, roaster, and attribute tags.
17
+
templ BeanSummary(props BeanSummaryProps) {
18
+
if props.Bean != nil {
19
+
<div class="font-bold text-brown-900 text-base">
20
+
if props.Bean.Name != "" {
21
+
{ props.Bean.Name }
22
+
} else {
23
+
{ props.Bean.Origin }
24
+
}
25
+
</div>
26
+
if props.Bean.Roaster != nil && props.Bean.Roaster.Name != "" {
27
+
<div class="text-sm text-brown-700 mt-0.5">
28
+
<span class="font-medium">🏭 { props.Bean.Roaster.Name }</span>
29
+
</div>
30
+
}
31
+
<div class="text-xs text-brown-600 mt-1 flex flex-wrap gap-x-2 gap-y-0.5">
32
+
if props.Bean.Origin != "" {
33
+
<span class="inline-flex items-center gap-0.5">📍 { props.Bean.Origin }</span>
34
+
}
35
+
if props.Bean.RoastLevel != "" {
36
+
<span class="inline-flex items-center gap-0.5">🔥 { props.Bean.RoastLevel }</span>
37
+
}
38
+
if props.Bean.Variety != "" {
39
+
<span class="inline-flex items-center gap-0.5">🌿 { props.Bean.Variety }</span>
40
+
}
41
+
if props.Bean.Process != "" {
42
+
<span class="inline-flex items-center gap-0.5">🌱 { props.Bean.Process }</span>
43
+
}
44
+
if props.CoffeeAmount > 0 {
45
+
<span class="inline-flex items-center gap-0.5">⚖️ { fmt.Sprintf("%dg", props.CoffeeAmount) }</span>
46
+
}
47
+
</div>
48
+
}
49
+
}
50
51
// EmptyStateProps defines properties for empty state messaging
52
type EmptyStateProps struct {
+7
-57
internal/web/pages/feed.templ
···
319
<!-- Bean info with rating -->
320
<div class="flex items-start justify-between gap-3 mb-3">
321
<div class="flex-1 min-w-0">
322
-
if item.Brew.Bean != nil {
323
-
<div class="font-bold text-brown-900 text-base">
324
-
if item.Brew.Bean.Name != "" {
325
-
{ item.Brew.Bean.Name }
326
-
} else {
327
-
{ item.Brew.Bean.Origin }
328
-
}
329
-
</div>
330
-
if item.Brew.Bean.Roaster != nil && item.Brew.Bean.Roaster.Name != "" {
331
-
<div class="text-sm text-brown-700 mt-0.5">
332
-
<span class="font-medium">🏭 { item.Brew.Bean.Roaster.Name }</span>
333
-
</div>
334
-
}
335
-
// TODO: can we share code with the bean card here? (and the roaster?)
336
-
<div class="text-xs text-brown-600 mt-1 flex flex-wrap gap-x-2 gap-y-0.5">
337
-
if item.Brew.Bean.Origin != "" {
338
-
<span class="inline-flex items-center gap-0.5">📍 { item.Brew.Bean.Origin }</span>
339
-
}
340
-
if item.Brew.Bean.RoastLevel != "" {
341
-
<span class="inline-flex items-center gap-0.5">🔥 { item.Brew.Bean.RoastLevel }</span>
342
-
}
343
-
if item.Brew.Bean.Process != "" {
344
-
<span class="inline-flex items-center gap-0.5">🌱 { item.Brew.Bean.Process }</span>
345
-
}
346
-
if item.Brew.CoffeeAmount > 0 {
347
-
<span class="inline-flex items-center gap-0.5">⚖️ { fmt.Sprintf("%dg", item.Brew.CoffeeAmount) }</span>
348
-
}
349
-
</div>
350
-
}
351
</div>
352
if item.Brew.Rating > 0 {
353
<span class="badge-rating">
···
419
templ FeedBeanContent(item *feed.FeedItem) {
420
if item.Bean != nil {
421
<div class="feed-content-box-sm">
422
-
<div class="mb-2">
423
-
<div class="font-bold text-brown-900 text-base">
424
-
if item.Bean.Name != "" {
425
-
{ item.Bean.Name }
426
-
} else {
427
-
{ item.Bean.Origin }
428
-
}
429
-
</div>
430
-
if item.Bean.Roaster != nil && item.Bean.Roaster.Name != "" {
431
-
<div class="text-sm text-brown-700 mt-0.5">
432
-
<span class="font-medium">🏭 { item.Bean.Roaster.Name }</span>
433
-
</div>
434
-
}
435
-
</div>
436
-
<div class="text-xs text-brown-600 mt-1 flex flex-wrap gap-x-2 gap-y-0.5">
437
-
if item.Bean.Origin != "" {
438
-
<span class="inline-flex items-center gap-0.5">📍 { item.Bean.Origin }</span>
439
-
}
440
-
if item.Bean.Variety != "" {
441
-
<span class="inline-flex items-center gap-0.5">🌿 { item.Bean.Variety }</span>
442
-
}
443
-
if item.Bean.RoastLevel != "" {
444
-
<span class="inline-flex items-center gap-0.5">🔥 { item.Bean.RoastLevel }</span>
445
-
}
446
-
if item.Bean.Process != "" {
447
-
<span class="inline-flex items-center gap-0.5">🌱 { item.Bean.Process }</span>
448
-
}
449
-
</div>
450
if item.Bean.Description != "" {
451
<div class="mt-2 text-sm text-brown-800 italic">"{ item.Bean.Description }"</div>
452
}
···
319
<!-- Bean info with rating -->
320
<div class="flex items-start justify-between gap-3 mb-3">
321
<div class="flex-1 min-w-0">
322
+
@components.BeanSummary(components.BeanSummaryProps{
323
+
Bean: item.Brew.Bean,
324
+
CoffeeAmount: item.Brew.CoffeeAmount,
325
+
})
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
326
</div>
327
if item.Brew.Rating > 0 {
328
<span class="badge-rating">
···
394
templ FeedBeanContent(item *feed.FeedItem) {
395
if item.Bean != nil {
396
<div class="feed-content-box-sm">
397
+
@components.BeanSummary(components.BeanSummaryProps{
398
+
Bean: item.Bean,
399
+
})
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
400
if item.Bean.Description != "" {
401
<div class="mt-2 text-sm text-brown-800 italic">"{ item.Bean.Description }"</div>
402
}