diff --git a/backend/static/js/pages/dog-profile.js b/backend/static/js/pages/dog-profile.js
index fdf69ca..6d72005 100644
--- a/backend/static/js/pages/dog-profile.js
+++ b/backend/static/js/pages/dog-profile.js
@@ -133,14 +133,19 @@ window.Page_dog_profile = (() => {
${dog.gewicht_kg} kg
` : ''}
- ${dog.chip_nr ? `
-
-
Chip-Nr.
-
${_esc(dog.chip_nr)}
+
+
+ Transponder
- ` : ''}
+ ${dog.chip_nr
+ ? `
${_esc(dog.chip_nr)}
`
+ : `
nicht eingetragen
+
+
`
+ }
+
${dog.bio ? `
@@ -230,9 +235,46 @@ window.Page_dog_profile = (() => {
}
});
+ // Transponder "Eintragen"-Button
+ document.getElementById('dp-chip-edit-btn')?.addEventListener('click', () => {
+ _showChipEdit(dog);
+ });
+
// Edit- und Add-Klicks laufen über Event-Delegation in init() — keine direkten Listener nötig.
}
+ function _showChipEdit(dog) {
+ UI.modal.open({
+ title: 'Transpondernummer',
+ body: `
+
+
+
+
`,
+ footer: `
+
+ `,
+ });
+ document.getElementById('chip-edit-save-btn').addEventListener('click', async () => {
+ const nr = document.getElementById('chip-edit-input').value.trim() || null;
+ const btn = document.getElementById('chip-edit-save-btn');
+ UI.setLoading(btn, true);
+ try {
+ await API.dogs.update(dog.id, { chip_nr: nr });
+ dog.chip_nr = nr;
+ _appState.activeDog = { ..._appState.activeDog, chip_nr: nr };
+ _appState.dogs = _appState.dogs.map(d => d.id === dog.id ? _appState.activeDog : d);
+ UI.modal.close();
+ UI.toast.success('Transpondernummer gespeichert.');
+ _renderProfile(_appState.activeDog);
+ } catch (e) {
+ UI.setLoading(btn, false);
+ UI.toast.error('Fehler beim Speichern.');
+ }
+ });
+ }
+
// ----------------------------------------------------------
// NEU ANLEGEN (direkt auf der Seite, kein Modal)
// ----------------------------------------------------------
diff --git a/backend/static/js/ui.js b/backend/static/js/ui.js
index 1b6cf14..22f66d0 100644
--- a/backend/static/js/ui.js
+++ b/backend/static/js/ui.js
@@ -259,6 +259,15 @@ const UI = (() => {
`;
}
+ function escape(str) {
+ if (!str) return '';
+ return String(str)
+ .replace(/&/g, '&')
+ .replace(//g, '>')
+ .replace(/"/g, '"');
+ }
+
// Öffentliche API
return {
toast, modal,
@@ -267,6 +276,7 @@ const UI = (() => {
emptyState, time,
setupPhotoPreview, scrollTop, skeleton,
icon: _svgIcon,
+ escape,
};
})();
diff --git a/backend/static/sw.js b/backend/static/sw.js
index 223defb..aec02ba 100644
--- a/backend/static/sw.js
+++ b/backend/static/sw.js
@@ -3,7 +3,7 @@
Offline-Cache + Push Notifications + Tile-Cache
============================================================ */
-const CACHE_VERSION = 'by-v142';
+const CACHE_VERSION = 'by-v143';
const CACHE_STATIC = `${CACHE_VERSION}-static`;
const CACHE_TILES = 'ban-yaro-tiles-v1'; // bleibt über SW-Updates erhalten