Heavily customized version of smokesignal - https://whtwnd.com/kayrozen.com/3lpwe4ymowg2t
at main 14 kB view raw
1<!-- =============================================== --> 2<!-- CSS STYLES REGION --> 3<!-- =============================================== --> 4<style> 5 .event-grid { 6 display: grid; 7 grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); 8 gap: 1.5rem; 9 margin: 1rem 0; 10 } 11 12 .event-card { 13 background: rgba(255, 255, 255, 0.05); 14 border-radius: 12px; 15 padding: 1.25rem; 16 border: 1px solid #3a3a3a; 17 height: 100%; 18 transition: transform 0.2s ease, box-shadow 0.2s ease; 19 position: relative; 20 overflow: hidden; 21 cursor: pointer; 22 } 23 24 .event-card:hover { 25 transform: translateY(-5px); 26 box-shadow: 0 10px 20px rgba(0,0,0,0.2); 27 } 28 29 .event-card-link { 30 position: absolute; 31 top: 0; 32 left: 0; 33 right: 0; 34 bottom: 0; 35 z-index: 1; 36 } 37 38 .event-card-content { 39 position: relative; 40 z-index: 2; 41 } 42 43 /* Ensure buttons remain clickable */ 44 .event-card .button, 45 .event-card a:not(.event-card-link) { 46 position: relative; 47 z-index: 3; 48 } 49 50 .event-time { 51 color: #888; 52 font-size: 0.75rem; 53 margin-bottom: 0.5rem; 54 font-weight: 500; 55 text-transform: uppercase; 56 letter-spacing: 0.5px; 57 } 58 59 .event-title { 60 color: white; 61 font-size: 1.125rem; 62 font-weight: 600; 63 margin-bottom: 0.75rem; 64 line-height: 1.4; 65 height: 2.8em; 66 overflow: hidden; 67 display: -webkit-box; 68 -webkit-line-clamp: 2; 69 line-clamp: 2; 70 -webkit-box-orient: vertical; 71 } 72 73 .event-title a { 74 color: white; 75 text-decoration: none; 76 transition: color 0.2s ease; 77 } 78 79 .event-title a:hover { 80 color: #7dd87f; 81 } 82 83 .event-organizer { 84 display: flex; 85 align-items: center; 86 margin-bottom: 0.75rem; 87 } 88 89 .organizer-avatar { 90 width: 24px; 91 height: 24px; 92 border-radius: 50%; 93 background: linear-gradient(45deg, #7dd87f, #5a9f63); 94 margin-right: 0.5rem; 95 display: flex; 96 align-items: center; 97 justify-content: center; 98 font-weight: bold; 99 font-size: 0.75rem; 100 color: white; 101 flex-shrink: 0; 102 } 103 104 .organizer-name { 105 color: #ccc; 106 font-size: 0.875rem; 107 white-space: nowrap; 108 overflow: hidden; 109 text-overflow: ellipsis; 110 } 111 112 .event-tags { 113 display: flex; 114 gap: 0.5rem; 115 margin-bottom: 1rem; 116 flex-wrap: wrap; 117 } 118 119 .event-tag { 120 font-size: 0.75rem; 121 padding: 0.25rem 0.5rem; 122 border-radius: 4px; 123 font-weight: 500; 124 text-transform: uppercase; 125 letter-spacing: 0.3px; 126 } 127 128 .tag-inperson { background-color: #2d5a3d; color: #7dd87f; } 129 .tag-virtual { background-color: #2d3d5a; color: #7f9ff8; } 130 .tag-hybrid { background-color: #5a2d5a; color: #d87fd8; } 131 .tag-planned { background-color: #3a3a3a; color: #aaa; } 132 .tag-scheduled { background-color: #2d5a3d; color: #7dd87f; } 133 .tag-cancelled { background-color: #5a2d2d; color: #f87f7f; } 134 .tag-postponed { background-color: #5a4a2d; color: #f8d67f; } 135 .tag-rescheduled { background-color: #2d3d5a; color: #7f9ff8; } 136 .tag-going { background-color: #2d5a3d; color: #7dd87f; } 137 .tag-interested { background-color: #2d3d5a; color: #7f9ff8; } 138 .tag-notgoing { background-color: #5a2d2d; color: #f87f7f; } 139 .tag-organizer { background-color: #5a2d5a; color: #d87fd8; } 140 .tag-legacy { background-color: #5a4a2d; color: #f8d67f; } 141 142 .event-participants { 143 display: flex; 144 align-items: center; 145 color: #aaa; 146 font-size: 0.875rem; 147 margin-bottom: 1rem; 148 } 149 150 .participants-icon { 151 margin-right: 0.5rem; 152 color: #7dd87f; 153 width: 12px; 154 } 155 156 .event-description { 157 color: #aaa; 158 font-size: 0.875rem; 159 margin-bottom: 1rem; 160 line-height: 1.4; 161 height: 2.8em; 162 overflow: hidden; 163 display: -webkit-box; 164 -webkit-line-clamp: 2; 165 line-clamp: 2; 166 -webkit-box-orient: vertical; 167 } 168 169 .event-actions { 170 display: flex; 171 gap: 0.5rem; 172 margin-top: 1rem; 173 padding-top: 1rem; 174 border-top: 1px solid #3a3a3a; 175 } 176 177 .action-btn { 178 flex: 1; 179 background: rgba(125, 216, 127, 0.1); 180 border: 1px solid #7dd87f; 181 color: #7dd87f; 182 border-radius: 6px; 183 padding: 0.5rem; 184 font-size: 0.875rem; 185 transition: all 0.2s ease; 186 text-decoration: none; 187 display: flex; 188 align-items: center; 189 justify-content: center; 190 gap: 0.25rem; 191 } 192 193 .action-btn:hover { 194 background: #7dd87f; 195 color: #1a1a1a; 196 } 197 198 .action-btn.secondary { 199 background: rgba(255, 255, 255, 0.05); 200 border: 1px solid #666; 201 color: #ccc; 202 } 203 204 .action-btn.secondary:hover { 205 background: rgba(255, 255, 255, 0.1); 206 color: white; 207 } 208 209 .event-stats { 210 display: flex; 211 gap: 1rem; 212 margin-bottom: 1rem; 213 font-size: 0.875rem; 214 color: #aaa; 215 } 216 217 .event-stats .stat { 218 display: flex; 219 align-items: center; 220 gap: 0.25rem; 221 } 222 223 .event-stats .stat i { 224 color: #7dd87f; 225 } 226 227 .empty-state { 228 text-align: center; 229 padding: 3rem 1rem; 230 color: #888; 231 } 232 233 .empty-state .icon { 234 font-size: 3rem; 235 margin-bottom: 1rem; 236 color: #555; 237 } 238 239 .empty-state h3 { 240 color: #ccc; 241 margin-bottom: 0.5rem; 242 } 243 244 @media (max-width: 768px) { 245 .event-grid { 246 grid-template-columns: 1fr; 247 gap: 1rem; 248 } 249 250 .event-card { 251 padding: 1rem; 252 } 253 254 .event-actions { 255 flex-direction: column; 256 } 257 } 258</style> 259 260<!-- =============================================== --> 261<!-- EVENT LISTING CONTENT --> 262<!-- =============================================== --> 263 264{% if events %} 265<div class="event-grid"> 266 {% for event in events %} 267 <div class="event-card"> 268 <a href="{{ base }}{{ event.site_url }}" class="event-card-link" hx-boost="true"></a> 269 270 <div class="event-card-content"> 271 <!-- Time and Date --> 272 {% if event.starts_at_human %} 273 <div class="event-time"> 274 <i class="fas fa-clock"></i> 275 <time class="dt-start" {% if event.starts_at_machine %}datetime="{{ event.starts_at_machine }}"{% endif %}> 276 {{ event.starts_at_human }} 277 </time> 278 </div> 279 {% endif %} 280 281 <!-- Event Title --> 282 <h3 class="event-title"> 283 <a href="{{ base }}{{ event.site_url }}" hx-boost="true"> 284 {% autoescape false %}{{ event.name }}{% endautoescape %} 285 </a> 286 </h3> 287 288 <!-- Event Tags --> 289 <div class="event-tags"> 290 <!-- Role Tag --> 291 {% if event.role %} 292 <span class="event-tag tag-{{ event.role }}"> 293 <i class=" 294 {%- if event.role == 'going' -%}fas fa-star 295 {%- elif event.role == 'interested' -%}fas fa-eye 296 {%- elif event.role == 'notgoing' -%}fas fa-ban 297 {%- elif event.role == 'organizer' -%}fas fa-calendar 298 {%- else -%}fas fa-question 299 {%- endif -%}"></i> 300 {%- if event.role == 'going' -%}{{ t("status-going") }} 301 {%- elif event.role == 'interested' -%}{{ t("status-interested") }} 302 {%- elif event.role == 'notgoing' -%}{{ t("status-not-going") }} 303 {%- elif event.role == 'organizer' -%}{{ t("status-organizer") }} 304 {%- else -%}{{ t("status-unknown") }} 305 {%- endif -%} 306 </span> 307 {% endif %} 308 309 <!-- Legacy Tag --> 310 {% if event.collection != "community.lexicon.calendar.event" %} 311 <span class="event-tag tag-legacy">{{ t("status-legacy") }}</span> 312 {% endif %} 313 314 <!-- Status Tag --> 315 {% if event.status == "planned" %} 316 <span class="event-tag tag-planned" title="{{ t('status-planned') }}"> 317 <i class="fas fa-calendar-days"></i> {{ t("status-planned") }} 318 </span> 319 {% elif event.status == "scheduled" %} 320 <span class="event-tag tag-scheduled" title="{{ t('status-scheduled') }}"> 321 <i class="fas fa-calendar-check"></i> {{ t("status-scheduled") }} 322 </span> 323 {% elif event.status == "rescheduled" %} 324 <span class="event-tag tag-rescheduled" title="{{ t('status-rescheduled') }}"> 325 <i class="fas fa-calendar-plus"></i> {{ t("status-rescheduled") }} 326 </span> 327 {% elif event.status == "cancelled" %} 328 <span class="event-tag tag-cancelled" title="{{ t('status-cancelled') }}"> 329 <i class="fas fa-calendar-xmark"></i> {{ t("status-cancelled") }} 330 </span> 331 {% elif event.status == "postponed" %} 332 <span class="event-tag tag-postponed" title="{{ t('status-postponed') }}"> 333 <i class="fas fa-calendar-minus"></i> {{ t("status-postponed") }} 334 </span> 335 {% endif %} 336 337 <!-- Mode Tag --> 338 {% if event.mode == "inperson" %} 339 <span class="event-tag tag-inperson"> 340 <i class="fas fa-users"></i> {{ t("mode-in-person") }} 341 </span> 342 {% elif event.mode == "virtual" %} 343 <span class="event-tag tag-virtual"> 344 <i class="fas fa-video"></i> {{ t("mode-virtual") }} 345 </span> 346 {% elif event.mode == "hybrid" %} 347 <span class="event-tag tag-hybrid"> 348 <i class="fas fa-globe"></i> {{ t("mode-hybrid") }} 349 </span> 350 {% endif %} 351 </div> 352 353 <!-- Organizer Info --> 354 {% if event.organizer_display_name %} 355 <div class="event-organizer"> 356 <div class="organizer-avatar"> 357 {{ event.organizer_display_name|first|upper }} 358 </div> 359 <span class="organizer-name"> 360 <a href="{{ base }}/{{ event.organizer_did }}" hx-boost="true" style="color: inherit; text-decoration: none;"> 361 {{ event.organizer_display_name }} 362 </a> 363 </span> 364 </div> 365 {% endif %} 366 367 <!-- Event Description Preview --> 368 {% if event.description_short %} 369 <div class="event-description"> 370 {% autoescape false %}{{ event.description_short }}{% endautoescape %} 371 </div> 372 {% endif %} 373 374 <!-- Location --> 375 {% if event.location %} 376 <div class="event-location" style="color: #aaa; font-size: 0.875rem; margin-bottom: 1rem;"> 377 <i class="fas fa-map-marker-alt" style="color: #7dd87f; margin-right: 0.5rem;"></i> 378 {{ event.location }} 379 </div> 380 {% endif %} 381 382 <!-- End Time --> 383 {% if event.ends_at_human %} 384 <div class="event-end-time" style="color: #888; font-size: 0.75rem; margin-bottom: 1rem;"> 385 <i class="fas fa-clock" style="margin-right: 0.25rem;"></i> 386 {{ t("ends-at", time=event.ends_at_human) }} 387 </div> 388 {% endif %} 389 390 <!-- Event Statistics --> 391 <div class="event-stats"> 392 <div class="stat" title="{{ t('event-count-going', count=event.count_going | default(0)) }}"> 393 <i class="fas fa-star"></i> 394 <span>{{ event.count_going | default(0) }}</span> 395 </div> 396 <div class="stat" title="{{ t('event-count-interested', count=event.count_interested | default(0)) }}"> 397 <i class="fas fa-eye"></i> 398 <span>{{ event.count_interested | default(0) }}</span> 399 </div> 400 <div class="stat" title="{{ t('event-count-not-going', count=event.count_not_going | default(0)) }}"> 401 <i class="fas fa-ban"></i> 402 <span>{{ event.count_not_going | default(0) }}</span> 403 </div> 404 </div> 405 406 <!-- Action Buttons --> 407 <div class="event-actions"> 408 <a href="{{ base }}{{ event.site_url }}" class="action-btn" hx-boost="true"> 409 <i class="fas fa-eye"></i> 410 {{ t("view-event") }} 411 </a> 412 </div> 413 </div> 414 </div> 415 {% endfor %} 416</div> 417{% else %} 418<div class="empty-state"> 419 <div class="icon"> 420 <i class="fas fa-calendar-times"></i> 421 </div> 422 <h3>{{ t("no-events-found") }}</h3> 423 <p>{{ t("no-events-description") }}</p> 424</div> 425{% endif %}