From 5c05bd6552a6388fa63217a4f790fcb9d53913e3 Mon Sep 17 00:00:00 2001 From: Disco DeDisco Date: Tue, 21 Apr 2026 21:54:34 -0400 Subject: [PATCH] sky: store birth_tz, prefill form from User model, drop localStorage Co-Authored-By: Claude Sonnet 4.6 --- src/apps/dashboard/views.py | 8 ++- .../lyric/migrations/0019_sky_birth_tz.py | 18 ++++++ src/apps/lyric/models.py | 1 + src/templates/apps/dashboard/sky.html | 59 +++++-------------- 4 files changed, 41 insertions(+), 45 deletions(-) create mode 100644 src/apps/lyric/migrations/0019_sky_birth_tz.py diff --git a/src/apps/dashboard/views.py b/src/apps/dashboard/views.py index e13d3dd..06c829a 100644 --- a/src/apps/dashboard/views.py +++ b/src/apps/dashboard/views.py @@ -303,9 +303,12 @@ def sky_view(request): return render(request, "apps/dashboard/sky.html", { "preview_url": request.build_absolute_uri("/dashboard/sky/preview"), "save_url": request.build_absolute_uri("/dashboard/sky/save"), - "saved_sky": request.user.sky_chart_data, + "saved_sky": request.user.sky_chart_data, "saved_birth_dt": request.user.sky_birth_dt, "saved_birth_place": request.user.sky_birth_place, + "saved_birth_lat": request.user.sky_birth_lat, + "saved_birth_lon": request.user.sky_birth_lon, + "saved_birth_tz": request.user.sky_birth_tz, "page_class": "page-sky", }) @@ -338,12 +341,13 @@ def sky_save(request): user.sky_birth_lat = body.get('birth_lat') user.sky_birth_lon = body.get('birth_lon') user.sky_birth_place = body.get('birth_place', '') + user.sky_birth_tz = body.get('birth_tz', '') user.sky_house_system = body.get('house_system', 'O') user.sky_chart_data = body.get('chart_data') user.save(update_fields=[ 'sky_birth_dt', 'sky_birth_lat', 'sky_birth_lon', - 'sky_birth_place', 'sky_house_system', 'sky_chart_data', + 'sky_birth_place', 'sky_birth_tz', 'sky_house_system', 'sky_chart_data', ]) return JsonResponse({"saved": True}) diff --git a/src/apps/lyric/migrations/0019_sky_birth_tz.py b/src/apps/lyric/migrations/0019_sky_birth_tz.py new file mode 100644 index 0000000..229e1e2 --- /dev/null +++ b/src/apps/lyric/migrations/0019_sky_birth_tz.py @@ -0,0 +1,18 @@ +# Generated by Django 6.0 on 2026-04-22 01:39 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('lyric', '0018_user_sky_fields'), + ] + + operations = [ + migrations.AddField( + model_name='user', + name='sky_birth_tz', + field=models.CharField(blank=True, max_length=64), + ), + ] diff --git a/src/apps/lyric/models.py b/src/apps/lyric/models.py index 5e2b752..886a6f2 100644 --- a/src/apps/lyric/models.py +++ b/src/apps/lyric/models.py @@ -52,6 +52,7 @@ class User(AbstractBaseUser): sky_birth_lat = models.DecimalField(max_digits=9, decimal_places=4, null=True, blank=True) sky_birth_lon = models.DecimalField(max_digits=9, decimal_places=4, null=True, blank=True) sky_birth_place = models.CharField(max_length=255, blank=True) + sky_birth_tz = models.CharField(max_length=64, blank=True) sky_house_system = models.CharField(max_length=1, blank=True, default="O") sky_chart_data = models.JSONField(null=True, blank=True) diff --git a/src/templates/apps/dashboard/sky.html b/src/templates/apps/dashboard/sky.html index 554aa4e..85d0d6a 100644 --- a/src/templates/apps/dashboard/sky.html +++ b/src/templates/apps/dashboard/sky.html @@ -19,12 +19,14 @@
- +
- + Local time at birth place. Use 12:00 if unknown.
@@ -33,7 +35,8 @@
+ autocomplete="off" + {% if saved_birth_place %}value="{{ saved_birth_place }}"{% endif %}>
+ placeholder="auto-detected from location" + {% if saved_birth_tz %}value="{{ saved_birth_tz }}"{% endif %}>
@@ -109,9 +115,6 @@ const NOMINATIM = 'https://nominatim.openstreetmap.org/search'; const USER_AGENT = 'EarthmanRPG/1.0 (https://earthmanrpg.me)'; - // localStorage key — fixed for the user's personal sky (not room-scoped) - const LS_KEY = 'natus-form:dashboard:sky'; - let _lastChartData = null; let _placeDebounce = null; let _chartDebounce = null; @@ -120,34 +123,6 @@ NatusWheel.preload(); - // ── localStorage persistence ──────────────────────────────────────────── - - function _saveForm() { - const data = { - date: document.getElementById('id_nf_date').value, - time: document.getElementById('id_nf_time').value, - place: placeInput.value, - lat: latInput.value, - lon: lonInput.value, - tz: tzInput.value, - }; - try { localStorage.setItem(LS_KEY, JSON.stringify(data)); } catch (_) {} - } - - function _restoreForm() { - let data; - try { data = JSON.parse(localStorage.getItem(LS_KEY) || 'null'); } catch (_) {} - if (!data) return; - if (data.date) document.getElementById('id_nf_date').value = data.date; - if (data.time) document.getElementById('id_nf_time').value = data.time; - if (data.place) placeInput.value = data.place; - if (data.lat) latInput.value = data.lat; - if (data.lon) lonInput.value = data.lon; - if (data.tz) { tzInput.value = data.tz; tzHint.textContent = 'Auto-detected from coordinates.'; } - // If we have enough data from localStorage, kick off a wheel draw - if (_formReady()) schedulePreview(); - } - // ── Status helper ─────────────────────────────────────────────────────── function setStatus(msg, type) { @@ -209,7 +184,6 @@ latInput.value = parseFloat(place.lat).toFixed(4); lonInput.value = parseFloat(place.lon).toFixed(4); hideSuggestions(); - _saveForm(); schedulePreview(); } @@ -230,8 +204,7 @@ }) .then(r => r.json()) .then(data => { placeInput.value = _cityName(data.address) || data.display_name || ''; }) - .catch(() => {}) - .finally(() => _saveForm()); + .catch(() => {}); setStatus(''); schedulePreview(); }, @@ -251,7 +224,6 @@ form.addEventListener('input', (e) => { if (e.target === placeInput) return; - _saveForm(); clearTimeout(_chartDebounce); _chartDebounce = setTimeout(schedulePreview, CHART_DELAY); }); @@ -312,6 +284,7 @@ birth_lat: parseFloat(latInput.value), birth_lon: parseFloat(lonInput.value), birth_place: placeInput.value, + birth_tz: tzInput.value.trim(), house_system: _lastChartData.house_system || 'O', chart_data: _lastChartData, }; @@ -340,9 +313,9 @@ return m ? m[1] : ''; } - // ── Restore persisted form on load ─────────────────────────────────────── + // ── Auto-preview on load if form is pre-filled from saved sky ─────────── - _restoreForm(); + if (_formReady()) schedulePreview(); })(); {% endblock %}