Coffee journaling on ATProto (alpha) alpha.arabica.social
coffee
17
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: links to record view pages from profile

+50 -14
+41 -10
internal/web/components/entity_tables.templ
··· 1 1 package components 2 2 3 - import "arabica/internal/models" 3 + import ( 4 + "arabica/internal/models" 5 + "fmt" 6 + ) 4 7 5 8 // BeansTableProps defines props for the shared beans table 6 9 type BeansTableProps struct { 7 10 Beans []*models.Bean 8 - ShowActions bool // Whether to show Edit/Delete actions 9 - ShowStatus bool // Whether to show Status column (open/closed badge) 11 + ShowActions bool // Whether to show Edit/Delete actions 12 + ShowStatus bool // Whether to show Status column (open/closed badge) 13 + OwnerHandle string // If set, name links to view page with this owner 10 14 } 11 15 12 16 // BeansTable renders a table of beans with configurable columns and actions ··· 44 48 } 45 49 </td> 46 50 } 47 - <td class="px-6 py-4 text-sm font-medium text-brown-900">{ bean.Name }</td> 51 + <td class="px-6 py-4 text-sm font-medium text-brown-900"> 52 + if props.OwnerHandle != "" { 53 + <a href={ templ.SafeURL(fmt.Sprintf("/beans/%s?owner=%s", bean.RKey, props.OwnerHandle)) } class="hover:underline">{ bean.Name }</a> 54 + } else { 55 + { bean.Name } 56 + } 57 + </td> 48 58 <td class="px-6 py-4 text-sm text-brown-900">{ bean.Origin }</td> 49 59 <td class="px-6 py-4 text-sm text-brown-900"> 50 60 if bean.Roaster != nil && bean.Roaster.Name != "" { ··· 102 112 // RoastersTableProps defines props for the shared roasters table 103 113 type RoastersTableProps struct { 104 114 Roasters []*models.Roaster 105 - ShowActions bool // Whether to show Edit/Delete actions 115 + ShowActions bool // Whether to show Edit/Delete actions 116 + OwnerHandle string // If set, name links to view page with this owner 106 117 } 107 118 108 119 // RoastersTable renders a table of roasters with configurable actions ··· 125 136 <tbody class="table-body"> 126 137 for _, roaster := range props.Roasters { 127 138 <tr class="table-row"> 128 - <td class="px-6 py-4 text-sm font-medium text-brown-900">{ roaster.Name }</td> 139 + <td class="px-6 py-4 text-sm font-medium text-brown-900"> 140 + if props.OwnerHandle != "" { 141 + <a href={ templ.SafeURL(fmt.Sprintf("/roasters/%s?owner=%s", roaster.RKey, props.OwnerHandle)) } class="hover:underline">{ roaster.Name }</a> 142 + } else { 143 + { roaster.Name } 144 + } 145 + </td> 129 146 <td class="px-6 py-4 text-sm text-brown-900"> 130 147 if roaster.Location != "" { 131 148 { roaster.Location } ··· 174 191 // GrindersTableProps defines props for the shared grinders table 175 192 type GrindersTableProps struct { 176 193 Grinders []*models.Grinder 177 - ShowActions bool // Whether to show Edit/Delete actions 194 + ShowActions bool // Whether to show Edit/Delete actions 195 + OwnerHandle string // If set, name links to view page with this owner 178 196 } 179 197 180 198 // GrindersTable renders a table of grinders with configurable actions ··· 198 216 <tbody class="table-body"> 199 217 for _, grinder := range props.Grinders { 200 218 <tr class="table-row"> 201 - <td class="px-6 py-4 text-sm font-medium text-brown-900">{ grinder.Name }</td> 219 + <td class="px-6 py-4 text-sm font-medium text-brown-900"> 220 + if props.OwnerHandle != "" { 221 + <a href={ templ.SafeURL(fmt.Sprintf("/grinders/%s?owner=%s", grinder.RKey, props.OwnerHandle)) } class="hover:underline">{ grinder.Name }</a> 222 + } else { 223 + { grinder.Name } 224 + } 225 + </td> 202 226 <td class="px-6 py-4 text-sm text-brown-900"> 203 227 if grinder.GrinderType != "" { 204 228 { grinder.GrinderType } ··· 248 272 // BrewersTableProps defines props for the shared brewers table 249 273 type BrewersTableProps struct { 250 274 Brewers []*models.Brewer 251 - ShowActions bool // Whether to show Edit/Delete actions 275 + ShowActions bool // Whether to show Edit/Delete actions 276 + OwnerHandle string // If set, name links to view page with this owner 252 277 } 253 278 254 279 // BrewersTable renders a table of brewers with configurable actions ··· 271 296 <tbody class="table-body"> 272 297 for _, brewer := range props.Brewers { 273 298 <tr class="table-row"> 274 - <td class="px-6 py-4 text-sm font-medium text-brown-900">{ brewer.Name }</td> 299 + <td class="px-6 py-4 text-sm font-medium text-brown-900"> 300 + if props.OwnerHandle != "" { 301 + <a href={ templ.SafeURL(fmt.Sprintf("/brewers/%s?owner=%s", brewer.RKey, props.OwnerHandle)) } class="hover:underline">{ brewer.Name }</a> 302 + } else { 303 + { brewer.Name } 304 + } 305 + </td> 275 306 <td class="px-6 py-4 text-sm text-brown-900"> 276 307 if brewer.BrewerType != "" { 277 308 { brewer.BrewerType }
+9 -4
internal/web/components/profile_partial.templ
··· 42 42 </div> 43 43 <!-- Beans Tab --> 44 44 <div x-show="activeTab === 'beans'"> 45 - @ProfileBeansTab(props.Beans, props.Roasters, props.IsOwnProfile) 45 + @ProfileBeansTab(props.Beans, props.Roasters, props.IsOwnProfile, props.ProfileHandle) 46 46 </div> 47 47 <!-- Equipment Tab --> 48 48 <div x-show="activeTab === 'equipment'"> 49 - @ProfileEquipmentTab(props.Grinders, props.Brewers, props.IsOwnProfile) 49 + @ProfileEquipmentTab(props.Grinders, props.Brewers, props.IsOwnProfile, props.ProfileHandle) 50 50 </div> 51 51 } 52 52 53 53 // ProfileBeansTab renders the beans and roasters tab for profile 54 - templ ProfileBeansTab(beans []*models.Bean, roasters []*models.Roaster, isOwnProfile bool) { 54 + templ ProfileBeansTab(beans []*models.Bean, roasters []*models.Roaster, isOwnProfile bool, profileHandle string) { 55 55 <div class="space-y-6"> 56 56 <!-- Open Bags Section --> 57 57 <div> ··· 73 73 Beans: filterOpenBeans(beans), 74 74 ShowActions: false, 75 75 ShowStatus: false, 76 + OwnerHandle: profileHandle, 76 77 }) 77 78 } 78 79 </div> ··· 89 90 @RoastersTable(RoastersTableProps{ 90 91 Roasters: roasters, 91 92 ShowActions: false, 93 + OwnerHandle: profileHandle, 92 94 }) 93 95 } 94 96 </div> ··· 104 106 Beans: filterClosedBeans(beans), 105 107 ShowActions: false, 106 108 ShowStatus: false, 109 + OwnerHandle: profileHandle, 107 110 }) 108 111 } 109 112 </div> ··· 198 201 } 199 202 200 203 // ProfileEquipmentTab renders the equipment tab for profile (grinders and brewers only) 201 - templ ProfileEquipmentTab(grinders []*models.Grinder, brewers []*models.Brewer, isOwnProfile bool) { 204 + templ ProfileEquipmentTab(grinders []*models.Grinder, brewers []*models.Brewer, isOwnProfile bool, profileHandle string) { 202 205 <div class="space-y-6"> 203 206 <!-- Grinders Section --> 204 207 <div> ··· 213 216 @GrindersTable(GrindersTableProps{ 214 217 Grinders: grinders, 215 218 ShowActions: false, 219 + OwnerHandle: profileHandle, 216 220 }) 217 221 } 218 222 </div> ··· 229 233 @BrewersTable(BrewersTableProps{ 230 234 Brewers: brewers, 231 235 ShowActions: false, 236 + OwnerHandle: profileHandle, 232 237 }) 233 238 } 234 239 </div>