Files
scha/schasite/templates/schasite/calendar2.html
T
westfarn f37ff3e87b
Unit Tests / test (push) Successful in 3s
Add start/end time fields to CalendarEvent (#28) (#29)
## Summary
Closes #28.

- Add optional `start_time` / `end_time` (`TimeField`) on `CalendarEvent`
- Expose times in Django admin list + form
- Replace hardcoded calendar template times with `time_range_display`
- Add migration `0013` and unit coverage for time formatting

## Test plan
- [ ] `python manage.py migrate`
- [ ] `python manage.py test schasite.tests.CalendarEventTests`
- [ ] In admin, edit an event with start/end times and confirm calendar page shows them
- [ ] Confirm events without times hide the Time rowReviewed-on: #29
2026-08-04 11:00:24 -07:00

216 lines
10 KiB
HTML

{% extends 'schasite/base2.html' %}
{% load static %}
{% block pagetitle %}
<title>Calendar | Stonehedge Community Homeowners Association</title>
<style type="text/css">
/* Calendar Page Specific Styles */
.event-card {
transition: transform 0.3s ease;
margin-bottom: 1.5rem;
}
.event-card:hover {
transform: translateY(-5px);
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);
}
.event-card .card-header {
padding: 0.75rem 1.25rem;
}
.event-card img {
height: 180px;
width: 100%;
object-fit: cover;
aspect-ratio: 16 / 9;
}
.nav-tabs .nav-link {
color: var(--bs-success);
font-weight: 500;
}
.nav-tabs .nav-link.active {
color: var(--bs-success);
border-color: var(--bs-success);
font-weight: 600;
}
/* Responsive adjustments */
@media (max-width: 767.98px) {
.event-card img {
height: 120px;
}
.event-card .col-md-4 {
margin-bottom: 1rem;
}
}
/* Icon alignment */
.bi-calendar-event,
.bi-calendar-range,
.bi-clock,
.bi-geo-alt,
.bi-house,
.bi-person,
.bi-envelope {
width: 1.25rem;
text-align: center;
}
</style>
{% endblock %}
{% block meta_tags %}
<meta name="description" content="Stonehedge community calendar — upcoming HOA events, gatherings, and past activities for Wheaton residents.">
{% endblock %}
{% block og_title %}Calendar | Stonehedge Community Homeowners Association{% endblock %}
{% block og_description %}Stonehedge community calendar — upcoming HOA events, gatherings, and past activities for Wheaton residents.{% endblock %}
{% block twitter_title %}Calendar | Stonehedge Community Homeowners Association{% endblock %}
{% block twitter_description %}Stonehedge community calendar — upcoming HOA events, gatherings, and past activities for Wheaton residents.{% endblock %}
{% block content %}
<div class="py-5">
<div class="container">
<!-- Calendar Navigation -->
<div class="row mb-4">
<div class="col-12">
<h1 class="text-success mb-3">Community Calendar</h1>
<ul class="nav nav-tabs" id="calendarTabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="upcoming-tab" data-bs-toggle="tab" data-bs-target="#upcoming" type="button" role="tab" aria-controls="upcoming" aria-selected="true">
Upcoming Events
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="past-tab" data-bs-toggle="tab" data-bs-target="#past" type="button" role="tab" aria-controls="past" aria-selected="false">
Past Events
</button>
</li>
</ul>
</div>
</div>
<!-- Calendar Content -->
<div class="tab-content" id="calendarTabContent">
<!-- Upcoming Events Tab -->
<div class="tab-pane fade show active" id="upcoming" role="tabpanel">
<div class="row g-4">
{% for event in future_events %}
<div class="col-lg-6">
<div class="card h-100 shadow-sm">
<div class="card-header bg-success text-white">
<div class="d-flex justify-content-between align-items-center">
<h3 class="h5 mb-0">{{ event.event_name }}</h3>
<span class="badge bg-light text-success">Upcoming</span>
</div>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-4">
<img src="../images/events/picnic.jpg" alt="Community Picnic" class="img-fluid rounded mb-3 mb-md-0">
</div>
<div class="col-md-8">
<div class="mb-3">
<p class="mb-1"><i class="bi bi-calendar-event text-success me-2"></i><strong>Date:</strong> {{ event.start_date }}</p>
{% if event.time_range_display %}
<p class="mb-1"><i class="bi bi-clock text-success me-2"></i><strong>Time:</strong> {{ event.time_range_display }}</p>
{% endif %}
<p class="mb-1"><i class="bi bi-geo-alt text-success me-2"></i><strong>Location:</strong> {{ event.location_name }}</p>
<p class="mb-1"><i class="bi bi-house text-success me-2"></i><strong>Address:</strong> </p>
<p class="mb-1"><i class="bi bi-person text-success me-2"></i><strong>Coordinator:</strong> {{ event.coordinator_name }}</p>
<p class="mb-1"><i class="bi bi-envelope text-success me-2"></i><strong>Email:</strong> <a href="mailto:{{ event.coordinator_email }}">{{ event.coordinator_email }}</a></p>
</div>
<p>{{ event.description }}</p>
<div class="d-flex justify-content-between align-items-center">
<a href="{{ event.event_url }}" class="btn btn-sm btn-success">{{ event.event_link_name }}</a>
{% if event.rsvp_date %}
<small class="text-muted">RSVP by {{ event.rsvp_date }}</small>
{% endif %}
</div>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
<!-- Past Events Tab -->
<div class="tab-pane fade" id="past" role="tabpanel">
<div class="row g-4">
<!-- Past Event 1 -->
{% for event in future_events %}
<div class="col-lg-6">
<div class="card h-100 shadow-sm">
<div class="card-header bg-secondary text-white">
<div class="d-flex justify-content-between align-items-center">
<h3 class="h5 mb-0">{{ event.event_name }}</h3>
<span class="badge bg-light text-secondary">Completed</span>
</div>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-4">
<img src="../images/events/spring-cleanup.jpg" alt="Spring Cleanup" class="img-fluid rounded mb-3 mb-md-0">
</div>
<div class="col-md-8">
<div class="mb-3">
<p class="mb-1"><i class="bi bi-calendar-event text-secondary me-2"></i><strong>Date:</strong> {{ event.start_date }}</p>
{% if event.time_range_display %}
<p class="mb-1"><i class="bi bi-clock text-secondary me-2"></i><strong>Time:</strong> {{ event.time_range_display }}</p>
{% endif %}
<p class="mb-1"><i class="bi bi-geo-alt text-secondary me-2"></i><strong>Location:</strong> {{ event.location_name }}</p>
<p class="mb-1"><i class="bi bi-house text-secondary me-2"></i><strong>Address:</strong> </p>
<p class="mb-1"><i class="bi bi-person text-secondary me-2"></i><strong>Coordinator:</strong> {{ event.coordinator_name }}</p>
<p class="mb-1"><i class="bi bi-envelope text-secondary me-2"></i><strong>Email:</strong> <a href="mailto:{{ event.coordinator_email }}">{{ event.coordinator_email }}</a></p>
</div>
<p>{{ event.description }}</p>
<div class="d-flex justify-content-between align-items-center">
<a href="https://greenwoodestates.org/events/spring-cleanup-2024" class="btn btn-sm btn-secondary">Event Recap</a>
<small class="text-muted">52 volunteers participated</small>
</div>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_js %}
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
// This would be replaced with actual event loading from a database
console.log('Calendar page loaded');
// Example: Highlight current tab in URL
const urlParams = new URLSearchParams(window.location.search);
const tab = urlParams.get('tab');
if (tab === 'past') {
const pastTab = new bootstrap.Tab(document.getElementById('past-tab'));
pastTab.show();
}
// Example: Add event to Google Calendar
document.querySelectorAll('.add-to-calendar').forEach(button => {
button.addEventListener('click', function() {
// In a real implementation, this would generate a calendar event
alert('This would add the event to your calendar');
});
});
});
</script>
{% endblock %}