Skip to content

Commit b7b1ba5

Browse files
explodedclaude
andcommitted
Add full-month calendar view with prev/next navigation
Replace the fixed 10-day window with a full calendar for the current month. Prev/next arrow links navigate between months (with year rollover). Today's row is highlighted in yellow. The home-page calendar link now includes the current year and month so it always lands on the right month. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 2970b20 commit b7b1ba5

4 files changed

Lines changed: 104 additions & 22 deletions

File tree

calendar.html

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ <h1 class="header-title">📅 Moon Rise and Set Calendar</h1>
2828
<main>
2929
<div class="page-content">
3030
<div class="card">
31+
<div class="month-nav">
32+
<a href="calendar?lat={{.Lat}}&lon={{.Lon}}&zon={{.Zon}}&year={{.PrevYear}}&month={{.PrevMonth}}">&#8592;</a>
33+
<span>{{.MonthName}} {{.Year}}</span>
34+
<a href="calendar?lat={{.Lat}}&lon={{.Lon}}&zon={{.Zon}}&year={{.NextYear}}&month={{.NextMonth}}">&#8594;</a>
35+
</div>
3136
<table>
3237
<thead>
3338
<tr>
@@ -40,7 +45,7 @@ <h1 class="header-title">📅 Moon Rise and Set Calendar</h1>
4045
</thead>
4146
<tbody>
4247
{{ range .Rows }}
43-
<tr>
48+
<tr{{if .IsToday}} class="today"{{end}}>
4449
<td>{{.Date}}</td>
4550
<td>{{if .Moon.AlwaysAbove}}Always above{{else if .Moon.AlwaysBelow}}Always below{{else}}{{.Moon.Rise}}{{end}}</td>
4651
<td>{{if .Moon.AlwaysAbove}}Always above{{else if .Moon.AlwaysBelow}}Always below{{else}}{{.Moon.Set}}{{end}}</td>

moon.go

Lines changed: 64 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -193,36 +193,80 @@ func calendar(w http.ResponseWriter, r *http.Request) {
193193
Zon = 10 // Default
194194
}
195195

196-
type gridrow struct {
197-
Date string
198-
Moon riseset.RiseSet
199-
Sun riseset.RiseSet
196+
// Determine which month to show, defaulting to the current month in the
197+
// user's timezone.
198+
zondur := time.Hour * time.Duration(Zon)
199+
now := time.Now().Add(zondur)
200+
201+
year, err := strconv.Atoi(r.URL.Query().Get("year"))
202+
if err != nil || year < 1 || year > 9999 {
203+
year = now.Year()
204+
}
205+
month, err := strconv.Atoi(r.URL.Query().Get("month"))
206+
if err != nil || month < 1 || month > 12 {
207+
month = int(now.Month())
208+
}
209+
210+
// Previous / next month navigation (handles year rollovers).
211+
prevMonth, prevYear := month-1, year
212+
if prevMonth < 1 {
213+
prevMonth = 12
214+
prevYear--
215+
}
216+
nextMonth, nextYear := month+1, year
217+
if nextMonth > 12 {
218+
nextMonth = 1
219+
nextYear++
200220
}
201221

202-
var arow gridrow
203-
var newdate time.Time
222+
// Today's date string in local time, used to highlight the current row.
223+
today := now.Format("02-01-2006")
224+
225+
// Last day of the requested month: day 0 of the following month.
226+
lastDay := time.Date(year, time.Month(month+1), 0, 0, 0, 0, 0, time.UTC).Day()
227+
228+
type gridrow struct {
229+
Date string
230+
Moon riseset.RiseSet
231+
Sun riseset.RiseSet
232+
IsToday bool
233+
}
204234

205235
type mypar struct {
206-
Rows []gridrow
207-
Lon float64
208-
Lat float64
209-
Zon float64
236+
Rows []gridrow
237+
Lon float64
238+
Lat float64
239+
Zon float64
240+
Year int
241+
Month int
242+
MonthName string
243+
PrevYear int
244+
PrevMonth int
245+
NextYear int
246+
NextMonth int
210247
}
211248

212249
var Passme mypar
213250
Passme.Lat = Lat
214251
Passme.Lon = Lon
215252
Passme.Zon = Zon
216-
217-
var zondur time.Duration = time.Hour * time.Duration(Zon)
218-
newdate = time.Now().Add(zondur)
219-
220-
for i := 0; i < 10; i++ {
221-
newdate = newdate.AddDate(0, 0, 1)
222-
arow.Date = newdate.Format("02-01-2006")
223-
arow.Moon = riseset.Riseset(riseset.Moon, newdate, Lon, Lat, Zon)
224-
arow.Sun = riseset.Riseset(riseset.Sun, newdate, Lon, Lat, Zon)
225-
Passme.Rows = append(Passme.Rows, arow)
253+
Passme.Year = year
254+
Passme.Month = month
255+
Passme.MonthName = time.Month(month).String()
256+
Passme.PrevYear = prevYear
257+
Passme.PrevMonth = prevMonth
258+
Passme.NextYear = nextYear
259+
Passme.NextMonth = nextMonth
260+
261+
for day := 1; day <= lastDay; day++ {
262+
d := time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC)
263+
dateStr := d.Format("02-01-2006")
264+
Passme.Rows = append(Passme.Rows, gridrow{
265+
Date: dateStr,
266+
Moon: riseset.Riseset(riseset.Moon, d, Lon, Lat, Zon),
267+
Sun: riseset.Riseset(riseset.Sun, d, Lon, Lat, Zon),
268+
IsToday: dateStr == today,
269+
})
226270
}
227271

228272
if templates != nil {

static/script.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,10 @@ function SpinnersChanged() {
274274
function updateCalLink() {
275275
const calendarLink = document.getElementById("callink");
276276
if (calendarLink) {
277-
calendarLink.href = `calendar?lat=${mylat}&lon=${mylon}&zon=${myzon}`;
277+
const now = new Date();
278+
const year = now.getFullYear();
279+
const month = now.getMonth() + 1;
280+
calendarLink.href = `calendar?lat=${mylat}&lon=${mylon}&zon=${myzon}&year=${year}&month=${month}`;
278281
}
279282
}
280283

static/styles.css

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,36 @@ table tfoot th {
325325
font-size: 14px;
326326
}
327327

328+
/* Month navigation header */
329+
.month-nav {
330+
display: flex;
331+
align-items: center;
332+
justify-content: space-between;
333+
padding: 12px 16px;
334+
border-bottom: 1px solid #e0e0e0;
335+
font-weight: 600;
336+
font-size: 16px;
337+
color: #333;
338+
}
339+
340+
.month-nav a {
341+
color: #1976d2;
342+
text-decoration: none;
343+
font-size: 20px;
344+
padding: 4px 10px;
345+
border-radius: 4px;
346+
transition: background 0.2s ease;
347+
}
348+
349+
.month-nav a:hover {
350+
background-color: #f0f0f0;
351+
}
352+
353+
/* Today row highlight */
354+
tr.today td {
355+
background-color: #fffde7;
356+
}
357+
328358
/* Responsive Styles */
329359
@media (max-width: 768px) {
330360
.page-content {

0 commit comments

Comments
 (0)