fix: Login zentrieren und CSV-Unterschrift-Platzhalter übersetzen
Auth-Screens werden per auth-screen über die volle Viewport-Höhe zentriert. Bild-Unterschriften im CSV-Export nutzen i18n statt festem deutschen Text. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+18
-3
@@ -4,12 +4,27 @@ body {
|
|||||||
background: radial-gradient(circle at center, #1b264f 0%, #0b0c10 100%);
|
background: radial-gradient(circle at center, #1b264f 0%, #0b0c10 100%);
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
font-family: system-ui, -apple-system, sans-serif;
|
font-family: system-ui, -apple-system, sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#root:has(.auth-screen) {
|
||||||
|
width: 100%;
|
||||||
|
max-width: none;
|
||||||
|
border-inline: none;
|
||||||
|
text-align: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-screen {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 100svh;
|
||||||
|
padding: 24px 16px calc(48px + env(safe-area-inset-bottom, 0px));
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
/* Glassmorphism Auth Card */
|
/* Glassmorphism Auth Card */
|
||||||
.auth-card {
|
.auth-card {
|
||||||
background: rgba(11, 12, 16, 0.75);
|
background: rgba(11, 12, 16, 0.75);
|
||||||
|
|||||||
+2
-2
@@ -166,7 +166,7 @@ function App() {
|
|||||||
|
|
||||||
if (isAcceptingInvite) {
|
if (isAcceptingInvite) {
|
||||||
return (
|
return (
|
||||||
<div className={`theme-${appliedTheme}`} style={{ display: 'contents' }}>
|
<div className={`theme-${appliedTheme} auth-screen`}>
|
||||||
<InvitationAcceptance
|
<InvitationAcceptance
|
||||||
onAccepted={(logbookId, title) => {
|
onAccepted={(logbookId, title) => {
|
||||||
setIsAuthenticated(true)
|
setIsAuthenticated(true)
|
||||||
@@ -186,7 +186,7 @@ function App() {
|
|||||||
|
|
||||||
if (!isAuthenticated) {
|
if (!isAuthenticated) {
|
||||||
return (
|
return (
|
||||||
<div className={`theme-${appliedTheme}`} style={{ display: 'contents' }}>
|
<div className={`theme-${appliedTheme} auth-screen`}>
|
||||||
<AuthOnboarding onAuthenticated={handleAuthenticated} />
|
<AuthOnboarding onAuthenticated={handleAuthenticated} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -117,6 +117,7 @@
|
|||||||
"sign_crew": "Crew-Unterschrift",
|
"sign_crew": "Crew-Unterschrift",
|
||||||
"sign_hint": "Mit Finger, Stift oder Maus unterschreiben",
|
"sign_hint": "Mit Finger, Stift oder Maus unterschreiben",
|
||||||
"sign_clear": "Löschen",
|
"sign_clear": "Löschen",
|
||||||
|
"sign_export_image": "[Unterschrift]",
|
||||||
"no_entries": "Keine Logbucheinträge für diese Yacht gefunden. Erstellen Sie Ihren ersten Reisetag!",
|
"no_entries": "Keine Logbucheinträge für diese Yacht gefunden. Erstellen Sie Ihren ersten Reisetag!",
|
||||||
"back_to_list": "Zurück zur Journal-Liste",
|
"back_to_list": "Zurück zur Journal-Liste",
|
||||||
"save": "Logbuchseite speichern",
|
"save": "Logbuchseite speichern",
|
||||||
|
|||||||
@@ -117,6 +117,7 @@
|
|||||||
"sign_crew": "Crew signature",
|
"sign_crew": "Crew signature",
|
||||||
"sign_hint": "Sign with finger, stylus, or mouse",
|
"sign_hint": "Sign with finger, stylus, or mouse",
|
||||||
"sign_clear": "Clear",
|
"sign_clear": "Clear",
|
||||||
|
"sign_export_image": "[Signature]",
|
||||||
"no_entries": "No logbook entries found for this yacht. Create your first travel day to begin!",
|
"no_entries": "No logbook entries found for this yacht. Create your first travel day to begin!",
|
||||||
"back_to_list": "Back to Journal List",
|
"back_to_list": "Back to Journal List",
|
||||||
"save": "Save Logbook Page",
|
"save": "Save Logbook Page",
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { getActiveMasterKey } from './auth.js'
|
|||||||
import { getLogbookKey } from './logbookKeys.js'
|
import { getLogbookKey } from './logbookKeys.js'
|
||||||
import { decryptJson } from './crypto.js'
|
import { decryptJson } from './crypto.js'
|
||||||
import { formatSignatureForExport } from '../utils/signatures.js'
|
import { formatSignatureForExport } from '../utils/signatures.js'
|
||||||
|
import i18n from '../i18n/index.js'
|
||||||
|
|
||||||
function escapeCsvValue(val: string | number | undefined | null): string {
|
function escapeCsvValue(val: string | number | undefined | null): string {
|
||||||
if (val === null || val === undefined) return '';
|
if (val === null || val === undefined) return '';
|
||||||
@@ -89,14 +90,15 @@ export async function exportLogbookToCsv(logbookId: string, preloadedData?: { ya
|
|||||||
];
|
];
|
||||||
|
|
||||||
const rows: string[][] = [headers];
|
const rows: string[][] = [headers];
|
||||||
|
const signaturePlaceholder = i18n.t('logs.sign_export_image');
|
||||||
|
|
||||||
for (const entry of decryptedEntries) {
|
for (const entry of decryptedEntries) {
|
||||||
const dateVal = entry.date || '';
|
const dateVal = entry.date || '';
|
||||||
const travelDay = entry.dayOfTravel || '';
|
const travelDay = entry.dayOfTravel || '';
|
||||||
const dep = entry.departure || '';
|
const dep = entry.departure || '';
|
||||||
const dest = entry.destination || '';
|
const dest = entry.destination || '';
|
||||||
const signS = formatSignatureForExport(entry.signSkipper);
|
const signS = formatSignatureForExport(entry.signSkipper, signaturePlaceholder);
|
||||||
const signC = formatSignatureForExport(entry.signCrew);
|
const signC = formatSignatureForExport(entry.signCrew, signaturePlaceholder);
|
||||||
const trackDist = entry.trackDistanceNm ?? '';
|
const trackDist = entry.trackDistanceNm ?? '';
|
||||||
const trackMax = entry.trackSpeedMaxKn ?? '';
|
const trackMax = entry.trackSpeedMaxKn ?? '';
|
||||||
const trackAvg = entry.trackSpeedAvgKn ?? '';
|
const trackAvg = entry.trackSpeedAvgKn ?? '';
|
||||||
|
|||||||
@@ -2,8 +2,11 @@ export function isSignatureImage(value: string | undefined | null): boolean {
|
|||||||
return typeof value === 'string' && value.startsWith('data:image/')
|
return typeof value === 'string' && value.startsWith('data:image/')
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatSignatureForExport(value: string | undefined | null): string {
|
export function formatSignatureForExport(
|
||||||
|
value: string | undefined | null,
|
||||||
|
imagePlaceholder: string
|
||||||
|
): string {
|
||||||
if (!value) return ''
|
if (!value) return ''
|
||||||
if (isSignatureImage(value)) return '[Unterschrift]'
|
if (isSignatureImage(value)) return imagePlaceholder
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user