Compare commits
3 Commits
v0.1.0.110
...
v0.1.0.111
| Author | SHA1 | Date | |
|---|---|---|---|
| 91cf2674f7 | |||
| b7a9df6ae0 | |||
| 7bc3c25ba4 |
@@ -5472,6 +5472,27 @@ html.theme-cupertino .events-scroll-container {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.kofi-footer-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 2px 8px;
|
||||
border-radius: 999px;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
color: #94a3b8;
|
||||
text-decoration: none;
|
||||
background: rgba(255, 94, 91, 0.08);
|
||||
border: 1px solid rgba(255, 94, 91, 0.18);
|
||||
transition: color 0.15s ease, background 0.15s ease, border-color 0.15s ease;
|
||||
}
|
||||
|
||||
.kofi-footer-badge:hover {
|
||||
color: #fecaca;
|
||||
background: rgba(255, 94, 91, 0.14);
|
||||
border-color: rgba(255, 94, 91, 0.32);
|
||||
}
|
||||
|
||||
.demo-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
import { Coffee } from 'lucide-react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { PlausibleEvents, trackPlausibleEvent } from '../services/analytics.js'
|
||||
|
||||
const APP_VERSION = typeof __APP_VERSION__ !== 'undefined' ? __APP_VERSION__ : 'dev'
|
||||
const KOFI_URL = 'https://ko-fi.com/kapteinsdaagbok'
|
||||
|
||||
export default function AppFooter() {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<footer className="app-version-footer">
|
||||
<span className="app-version-footer__version">v{APP_VERSION}</span>
|
||||
@@ -18,6 +23,21 @@ export default function AppFooter() {
|
||||
Markus F.J. Busche
|
||||
</a>
|
||||
</span>
|
||||
<span className="app-version-footer__sep" aria-hidden="true">
|
||||
·
|
||||
</span>
|
||||
<a
|
||||
className="kofi-footer-badge"
|
||||
href={KOFI_URL}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
title={t('footer.kofi_title')}
|
||||
aria-label={t('footer.kofi_title')}
|
||||
onClick={() => trackPlausibleEvent(PlausibleEvents.KOFI_LINK_CLICKED)}
|
||||
>
|
||||
<Coffee size={12} aria-hidden="true" />
|
||||
<span>{t('footer.kofi_label')}</span>
|
||||
</a>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
"beta": "Beta",
|
||||
"beta_hint": "Betaversion - funktioner kan stadig ændres"
|
||||
},
|
||||
"footer": {
|
||||
"kofi_label": "Ko-fi",
|
||||
"kofi_title": "Støt projektet, videreudvikling og driftsomkostninger på Ko-fi"
|
||||
},
|
||||
"languages": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
"beta": "Beta",
|
||||
"beta_hint": "Beta-Version — Funktionen können sich noch ändern"
|
||||
},
|
||||
"footer": {
|
||||
"kofi_label": "Ko-fi",
|
||||
"kofi_title": "Projekt, Weiterentwicklung und Betriebskosten auf Ko-fi unterstützen"
|
||||
},
|
||||
"languages": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
"beta": "Beta",
|
||||
"beta_hint": "Beta release — features may still change"
|
||||
},
|
||||
"footer": {
|
||||
"kofi_label": "Ko-fi",
|
||||
"kofi_title": "Support the project, development, and running costs on Ko-fi"
|
||||
},
|
||||
"languages": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
"beta": "Beta",
|
||||
"beta_hint": "Betaversjon - funksjoner kan fortsatt endres"
|
||||
},
|
||||
"footer": {
|
||||
"kofi_label": "Ko-fi",
|
||||
"kofi_title": "Støtt prosjektet, videreutvikling og driftskostnader på Ko-fi"
|
||||
},
|
||||
"languages": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
"beta": "Beta",
|
||||
"beta_hint": "Betaversion - funktioner kan fortfarande ändras"
|
||||
},
|
||||
"footer": {
|
||||
"kofi_label": "Ko-fi",
|
||||
"kofi_title": "Stöd projektet, vidareutveckling och driftskostnader på Ko-fi"
|
||||
},
|
||||
"languages": {
|
||||
"de": "Deutsch",
|
||||
"en": "English",
|
||||
|
||||
@@ -26,6 +26,7 @@ export const PlausibleEvents = {
|
||||
PUSH_ENABLED: 'Push Enabled',
|
||||
PUSH_DISABLED: 'Push Disabled',
|
||||
FOOTER_LINK_CLICKED: 'Footer Link Clicked',
|
||||
KOFI_LINK_CLICKED: 'Ko-fi Link Clicked',
|
||||
PROFILE_OPENED: 'Profile Opened',
|
||||
PASSKEY_ADDED: 'Passkey Added',
|
||||
PASSKEY_REMOVED: 'Passkey Removed',
|
||||
@@ -40,9 +41,7 @@ export const PlausibleEvents = {
|
||||
NMEA_UPLOADED: 'NMEA Uploaded',
|
||||
LIVE_LOG_OPENED: 'Live Log Opened',
|
||||
LIVE_LOG_EVENT_LOGGED: 'Live Log Event Logged',
|
||||
LIVE_LOG_PHOTO_UPLOADED: 'Live Log Photo Uploaded',
|
||||
VOICE_MEMO_UPLOADED: 'Voice Memo Uploaded',
|
||||
LIVE_LOG_VOICE_UPLOADED: 'Live Log Voice Uploaded',
|
||||
OWM_WEATHER_FETCHED: 'OWM Weather Fetched',
|
||||
AI_SUMMARY_GENERATED: 'AI Summary Generated',
|
||||
PWA_BOOT_WATCHDOG_SOFT: 'PWA Boot Watchdog Soft',
|
||||
|
||||
@@ -55,9 +55,6 @@ export async function saveEntryPhoto(options: {
|
||||
})
|
||||
|
||||
trackPlausibleEvent(PlausibleEvents.PHOTO_UPLOADED, { context: analyticsContext })
|
||||
if (analyticsContext === 'live_log') {
|
||||
trackPlausibleEvent(PlausibleEvents.LIVE_LOG_PHOTO_UPLOADED)
|
||||
}
|
||||
syncLogbook(logbookId).catch((err) => console.warn('Background sync failed:', err))
|
||||
return photoId
|
||||
}
|
||||
|
||||
@@ -66,9 +66,6 @@ export async function saveEntryVoiceMemo(options: {
|
||||
})
|
||||
|
||||
trackPlausibleEvent(PlausibleEvents.VOICE_MEMO_UPLOADED, { context: analyticsContext })
|
||||
if (analyticsContext === 'live_log') {
|
||||
trackPlausibleEvent(PlausibleEvents.LIVE_LOG_VOICE_UPLOADED)
|
||||
}
|
||||
syncLogbook(logbookId).catch((err) => console.warn('Background sync failed:', err))
|
||||
return voiceId
|
||||
}
|
||||
|
||||
@@ -37,9 +37,7 @@ Kapteins Daagbok nutzt [Plausible Analytics](https://plausible.io/) mit dem Scri
|
||||
| CSV Exported | CSV-Download aus der Eintragsliste (`LogEntriesList.tsx`) | — |
|
||||
| CSV Shared | CSV über Web Share API geteilt (`LogEntriesList.tsx`) | — |
|
||||
| Photo Uploaded | Foto hochgeladen (`photoAttachments.ts`, `PhotoCapture.tsx`, `CrewForm.tsx`) | `context`: `logbook` \| `live_log` \| `crew`, bei Crew zusätzlich `role`: `skipper` \| `crew` |
|
||||
| Live Log Photo Uploaded | Foto im Live-Journal per Kamera gespeichert (`photoAttachments.ts`, `analyticsContext`: `live_log`) | — |
|
||||
| Voice Memo Uploaded | Sprachnotiz gespeichert (`voiceAttachments.ts`) | `context`: `logbook` \| `live_log` |
|
||||
| Live Log Voice Uploaded | Sprachnotiz im Live-Journal gespeichert (`voiceAttachments.ts`, `analyticsContext`: `live_log`) | — |
|
||||
| OWM Weather Fetched | Erfolgreicher OpenWeatherMap-API-Abruf (`weather.ts`, zentral nach HTTP 200) | `source`: siehe [OWM-Quellen](#owm-quellen) |
|
||||
| AI Summary Generated | Erfolgreiche KI-Zusammenfassung eines Reisetags (`aiSummary.ts`) | — |
|
||||
| Backup Exported | Backup-Datei heruntergeladen (`LogbookBackupPanel.tsx`, v2 ZIP) | `entries`, `photos`, `voiceMemos`, `bytes` (Anzahlen/Größe, keine Inhalte) |
|
||||
@@ -47,6 +45,7 @@ Kapteins Daagbok nutzt [Plausible Analytics](https://plausible.io/) mit dem Scri
|
||||
| Push Enabled | Crew-Änderungs-Push aktiviert (`PushNotificationSettings.tsx`) | — |
|
||||
| Push Disabled | Crew-Änderungs-Push deaktiviert (`PushNotificationSettings.tsx`) | — |
|
||||
| Footer Link Clicked | Klick auf Autoren-Link im App-Footer (`AppFooter.tsx`) | — |
|
||||
| Ko-fi Link Clicked | Klick auf Ko-fi-Unterstützen-Badge im App-Footer (`AppFooter.tsx`) | — |
|
||||
| Profile Opened | Profilseite geöffnet (`UserProfilePage.tsx`, einmal pro Mount) | — |
|
||||
| Passkey Added | Passkey erfolgreich registriert (`UserProfilePage.tsx`) | `labeled`: `true` \| `false` (optionaler Name gesetzt) |
|
||||
| Passkey Removed | Passkey entfernt, mindestens ein Key verbleibt (`UserProfilePage.tsx`) | — |
|
||||
@@ -138,7 +137,7 @@ Empfohlene Goal-Ketten für Auswertung (nur Business!):
|
||||
7. **Kontosicherheit:** Profile Opened → Passkey Added / Local PIN Set / Recovery Rotated; Last Passkey Remove Hinted → Account Deleted (selten, aber aussagekräftig)
|
||||
8. **Internationalisierung:** Language Changed (Verteilung `to`, Pfade mit Übersetzungs-Feedback)
|
||||
9. **NMEA-Import:** NMEA Uploaded → NMEA Imported (Modus, `events`, optional Track; Upload-Funnel vs. Abbruch)
|
||||
10. **Live-Journal:** Live Log Opened → Live Log Event Logged (Verteilung `action`; z. B. `fix`, `course`, `motor_start`) → Live Log Photo Uploaded
|
||||
10. **Live-Journal:** Live Log Opened → Live Log Event Logged (Verteilung `action`; z. B. `fix`, `course`, `motor_start`) → Photo Uploaded / Voice Memo Uploaded (Filter `context`: `live_log`)
|
||||
11. **OpenWeatherMap:** OWM Weather Fetched (Verteilung `source`; Live-Journal vs. Reisetag-Editor)
|
||||
12. **PWA-Stabilitaet:** PWA Boot Watchdog Soft → PWA Boot Watchdog Hard → PWA Boot Watchdog Fallback → PWA Boot Watchdog Manual Repair
|
||||
|
||||
@@ -151,7 +150,8 @@ trackPlausibleEvent(PlausibleEvents.TRAVEL_DAY_SAVED)
|
||||
trackPlausibleEvent(PlausibleEvents.ENTRY_SIGNED, { role: 'skipper' })
|
||||
trackPlausibleEvent(PlausibleEvents.LANGUAGE_CHANGED, { from: 'de', to: 'da' })
|
||||
trackPlausibleEvent(PlausibleEvents.LIVE_LOG_EVENT_LOGGED, { action: 'course' })
|
||||
trackPlausibleEvent(PlausibleEvents.LIVE_LOG_PHOTO_UPLOADED)
|
||||
trackPlausibleEvent(PlausibleEvents.PHOTO_UPLOADED, { context: 'live_log' })
|
||||
trackPlausibleEvent(PlausibleEvents.VOICE_MEMO_UPLOADED, { context: 'live_log' })
|
||||
trackPlausibleEvent(PlausibleEvents.OWM_WEATHER_FETCHED, { source: 'live_log' })
|
||||
trackPlausibleEvent(PlausibleEvents.NMEA_UPLOADED, { lines: 1200, candidates: 8, duplicate: false, has_position: true })
|
||||
trackPlausibleEvent(PlausibleEvents.NMEA_IMPORTED, { mode: 'both', events: 6, track: true })
|
||||
|
||||
Reference in New Issue
Block a user