feat: Schiffs-Stammdaten erweitern und Ablenkungstabelle ausblenden
Neue Felder für Yachttyp, Länge, Tiefgang und Höhe; Compass Deviation Table ist für Freizeit-Skipper vorerst aus der Navigation entfernt. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+8
-3
@@ -5,7 +5,8 @@ import AuthOnboarding from './components/AuthOnboarding.tsx'
|
|||||||
import LogbookDashboard from './components/LogbookDashboard.tsx'
|
import LogbookDashboard from './components/LogbookDashboard.tsx'
|
||||||
import VesselForm from './components/VesselForm.tsx'
|
import VesselForm from './components/VesselForm.tsx'
|
||||||
import CrewForm from './components/CrewForm.tsx'
|
import CrewForm from './components/CrewForm.tsx'
|
||||||
import DeviationForm from './components/DeviationForm.tsx'
|
// Compass Deviation Table — für Freizeit-Skipper vorerst deaktiviert (Komponente bleibt erhalten)
|
||||||
|
// import DeviationForm from './components/DeviationForm.tsx'
|
||||||
import LogEntriesList from './components/LogEntriesList.tsx'
|
import LogEntriesList from './components/LogEntriesList.tsx'
|
||||||
import SettingsForm from './components/SettingsForm.tsx'
|
import SettingsForm from './components/SettingsForm.tsx'
|
||||||
import InvitationAcceptance from './components/InvitationAcceptance.tsx'
|
import InvitationAcceptance from './components/InvitationAcceptance.tsx'
|
||||||
@@ -16,7 +17,7 @@ import PwaInstallPrompt from './components/PwaInstallPrompt.tsx'
|
|||||||
import AppFooter from './components/AppFooter.tsx'
|
import AppFooter from './components/AppFooter.tsx'
|
||||||
import { db } from './services/db.js'
|
import { db } from './services/db.js'
|
||||||
import { useLiveQuery } from 'dexie-react-hooks'
|
import { useLiveQuery } from 'dexie-react-hooks'
|
||||||
import { Ship, LogOut, ChevronLeft, Users, Compass, FileText, Settings, Wifi, WifiOff } from 'lucide-react'
|
import { Ship, LogOut, ChevronLeft, Users, FileText, Settings, Wifi, WifiOff } from 'lucide-react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
@@ -24,7 +25,7 @@ function App() {
|
|||||||
const [isAuthenticated, setIsAuthenticated] = useState(false)
|
const [isAuthenticated, setIsAuthenticated] = useState(false)
|
||||||
const [activeLogbookId, setActiveLogbookId] = useState<string | null>(null)
|
const [activeLogbookId, setActiveLogbookId] = useState<string | null>(null)
|
||||||
const [activeLogbookTitle, setActiveLogbookTitle] = useState<string | null>(null)
|
const [activeLogbookTitle, setActiveLogbookTitle] = useState<string | null>(null)
|
||||||
const [activeTab, setActiveTab] = useState<'vessel' | 'crew' | 'deviation' | 'logs' | 'settings'>('logs')
|
const [activeTab, setActiveTab] = useState<'vessel' | 'crew' | 'logs' | 'settings'>('logs')
|
||||||
const [online, setOnline] = useState(navigator.onLine)
|
const [online, setOnline] = useState(navigator.onLine)
|
||||||
const [isSyncing, setIsSyncing] = useState(false)
|
const [isSyncing, setIsSyncing] = useState(false)
|
||||||
const [appliedTheme, setAppliedTheme] = useState<'ocean' | 'material' | 'cupertino'>('ocean')
|
const [appliedTheme, setAppliedTheme] = useState<'ocean' | 'material' | 'cupertino'>('ocean')
|
||||||
@@ -271,6 +272,7 @@ function App() {
|
|||||||
{t('nav.crew')}
|
{t('nav.crew')}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
{/* Compass Deviation Table — für Freizeit-Skipper vorerst ausgeblendet
|
||||||
<button
|
<button
|
||||||
className={`sidebar-btn ${activeTab === 'deviation' ? 'active' : ''}`}
|
className={`sidebar-btn ${activeTab === 'deviation' ? 'active' : ''}`}
|
||||||
onClick={() => setActiveTab('deviation')}
|
onClick={() => setActiveTab('deviation')}
|
||||||
@@ -278,6 +280,7 @@ function App() {
|
|||||||
<Compass size={18} />
|
<Compass size={18} />
|
||||||
{t('nav.deviation')}
|
{t('nav.deviation')}
|
||||||
</button>
|
</button>
|
||||||
|
*/}
|
||||||
|
|
||||||
<button
|
<button
|
||||||
className={`sidebar-btn ${activeTab === 'settings' ? 'active' : ''}`}
|
className={`sidebar-btn ${activeTab === 'settings' ? 'active' : ''}`}
|
||||||
@@ -302,9 +305,11 @@ function App() {
|
|||||||
<CrewForm logbookId={activeLogbookId} />
|
<CrewForm logbookId={activeLogbookId} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Compass Deviation Table — für Freizeit-Skipper vorerst deaktiviert
|
||||||
{activeTab === 'deviation' && (
|
{activeTab === 'deviation' && (
|
||||||
<DeviationForm logbookId={activeLogbookId} />
|
<DeviationForm logbookId={activeLogbookId} />
|
||||||
)}
|
)}
|
||||||
|
*/}
|
||||||
|
|
||||||
{activeTab === 'settings' && (
|
{activeTab === 'settings' && (
|
||||||
<SettingsForm logbookId={activeLogbookId} />
|
<SettingsForm logbookId={activeLogbookId} />
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ interface VesselFormProps {
|
|||||||
export default function VesselForm({ logbookId, readOnly = false, preloadedData }: VesselFormProps) {
|
export default function VesselForm({ logbookId, readOnly = false, preloadedData }: VesselFormProps) {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const [name, setName] = useState('')
|
const [name, setName] = useState('')
|
||||||
|
const [vesselType, setVesselType] = useState<'sailing' | 'motor' | ''>('')
|
||||||
|
const [lengthM, setLengthM] = useState('')
|
||||||
|
const [draftM, setDraftM] = useState('')
|
||||||
|
const [airDraftM, setAirDraftM] = useState('')
|
||||||
const [homePort, setHomePort] = useState('')
|
const [homePort, setHomePort] = useState('')
|
||||||
const [charterCompany, setCharterCompany] = useState('')
|
const [charterCompany, setCharterCompany] = useState('')
|
||||||
const [owner, setOwner] = useState('')
|
const [owner, setOwner] = useState('')
|
||||||
@@ -43,6 +47,10 @@ export default function VesselForm({ logbookId, readOnly = false, preloadedData
|
|||||||
try {
|
try {
|
||||||
if (readOnly && preloadedData) {
|
if (readOnly && preloadedData) {
|
||||||
setName(preloadedData.name || '')
|
setName(preloadedData.name || '')
|
||||||
|
setVesselType(preloadedData.vesselType || '')
|
||||||
|
setLengthM(preloadedData.lengthM != null ? String(preloadedData.lengthM) : '')
|
||||||
|
setDraftM(preloadedData.draftM != null ? String(preloadedData.draftM) : '')
|
||||||
|
setAirDraftM(preloadedData.airDraftM != null ? String(preloadedData.airDraftM) : '')
|
||||||
setHomePort(preloadedData.homePort || '')
|
setHomePort(preloadedData.homePort || '')
|
||||||
setCharterCompany(preloadedData.charterCompany || '')
|
setCharterCompany(preloadedData.charterCompany || '')
|
||||||
setOwner(preloadedData.owner || '')
|
setOwner(preloadedData.owner || '')
|
||||||
@@ -64,6 +72,10 @@ export default function VesselForm({ logbookId, readOnly = false, preloadedData
|
|||||||
const decrypted = await decryptJson(local.encryptedData, local.iv, local.tag, masterKey)
|
const decrypted = await decryptJson(local.encryptedData, local.iv, local.tag, masterKey)
|
||||||
if (decrypted) {
|
if (decrypted) {
|
||||||
setName(decrypted.name || '')
|
setName(decrypted.name || '')
|
||||||
|
setVesselType(decrypted.vesselType || '')
|
||||||
|
setLengthM(decrypted.lengthM != null ? String(decrypted.lengthM) : '')
|
||||||
|
setDraftM(decrypted.draftM != null ? String(decrypted.draftM) : '')
|
||||||
|
setAirDraftM(decrypted.airDraftM != null ? String(decrypted.airDraftM) : '')
|
||||||
setHomePort(decrypted.homePort || '')
|
setHomePort(decrypted.homePort || '')
|
||||||
setCharterCompany(decrypted.charterCompany || '')
|
setCharterCompany(decrypted.charterCompany || '')
|
||||||
setOwner(decrypted.owner || '')
|
setOwner(decrypted.owner || '')
|
||||||
@@ -170,6 +182,10 @@ export default function VesselForm({ logbookId, readOnly = false, preloadedData
|
|||||||
|
|
||||||
const yachtData = {
|
const yachtData = {
|
||||||
name: name.trim(),
|
name: name.trim(),
|
||||||
|
vesselType: vesselType || undefined,
|
||||||
|
lengthM: lengthM.trim() || undefined,
|
||||||
|
draftM: draftM.trim() || undefined,
|
||||||
|
airDraftM: airDraftM.trim() || undefined,
|
||||||
homePort: homePort.trim(),
|
homePort: homePort.trim(),
|
||||||
charterCompany: charterCompany.trim(),
|
charterCompany: charterCompany.trim(),
|
||||||
owner: owner.trim(),
|
owner: owner.trim(),
|
||||||
@@ -302,6 +318,59 @@ export default function VesselForm({ logbookId, readOnly = false, preloadedData
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className="input-group">
|
||||||
|
<label>{t('vessel.type')}</label>
|
||||||
|
<select
|
||||||
|
className="input-text"
|
||||||
|
value={vesselType}
|
||||||
|
onChange={(e) => setVesselType(e.target.value as 'sailing' | 'motor' | '')}
|
||||||
|
disabled={saving || readOnly}
|
||||||
|
>
|
||||||
|
<option value="">{t('vessel.type_unset')}</option>
|
||||||
|
<option value="sailing">{t('vessel.type_sailing')}</option>
|
||||||
|
<option value="motor">{t('vessel.type_motor')}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="input-group">
|
||||||
|
<label>{t('vessel.length_m')}</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
inputMode="decimal"
|
||||||
|
className="input-text"
|
||||||
|
value={lengthM}
|
||||||
|
onChange={(e) => setLengthM(e.target.value)}
|
||||||
|
disabled={saving || readOnly}
|
||||||
|
placeholder="0.00"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="input-group">
|
||||||
|
<label>{t('vessel.draft_m')}</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
inputMode="decimal"
|
||||||
|
className="input-text"
|
||||||
|
value={draftM}
|
||||||
|
onChange={(e) => setDraftM(e.target.value)}
|
||||||
|
disabled={saving || readOnly}
|
||||||
|
placeholder="0.00"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="input-group">
|
||||||
|
<label>{t('vessel.air_draft_m')}</label>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
inputMode="decimal"
|
||||||
|
className="input-text"
|
||||||
|
value={airDraftM}
|
||||||
|
onChange={(e) => setAirDraftM(e.target.value)}
|
||||||
|
disabled={saving || readOnly}
|
||||||
|
placeholder="0.00"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="input-group">
|
<div className="input-group">
|
||||||
<label>{t('vessel.port')}</label>
|
<label>{t('vessel.port')}</label>
|
||||||
<input
|
<input
|
||||||
|
|||||||
@@ -76,6 +76,13 @@
|
|||||||
"vessel": {
|
"vessel": {
|
||||||
"title": "Schiffs-Stammdaten",
|
"title": "Schiffs-Stammdaten",
|
||||||
"name": "Yachtname",
|
"name": "Yachtname",
|
||||||
|
"type": "Yachttyp",
|
||||||
|
"type_unset": "— nicht angegeben —",
|
||||||
|
"type_sailing": "Segelyacht",
|
||||||
|
"type_motor": "Motoryacht",
|
||||||
|
"length_m": "Länge (m)",
|
||||||
|
"draft_m": "Tiefgang (m)",
|
||||||
|
"air_draft_m": "Höhe (m)",
|
||||||
"port": "Heimathafen",
|
"port": "Heimathafen",
|
||||||
"owner": "Eigner",
|
"owner": "Eigner",
|
||||||
"charter": "Charterfirma",
|
"charter": "Charterfirma",
|
||||||
|
|||||||
@@ -76,6 +76,13 @@
|
|||||||
"vessel": {
|
"vessel": {
|
||||||
"title": "Vessel Master Data",
|
"title": "Vessel Master Data",
|
||||||
"name": "Yacht Name",
|
"name": "Yacht Name",
|
||||||
|
"type": "Vessel Type",
|
||||||
|
"type_unset": "— not specified —",
|
||||||
|
"type_sailing": "Sailing yacht",
|
||||||
|
"type_motor": "Motor yacht",
|
||||||
|
"length_m": "Length (m)",
|
||||||
|
"draft_m": "Draft (m)",
|
||||||
|
"air_draft_m": "Air draft (m)",
|
||||||
"port": "Home Port",
|
"port": "Home Port",
|
||||||
"owner": "Owner",
|
"owner": "Owner",
|
||||||
"charter": "Charter Company",
|
"charter": "Charter Company",
|
||||||
|
|||||||
Reference in New Issue
Block a user