Files
Cable/CLAUDE.md
Stefan Lange-Hegermann 03878b9507 Add analytics tracking, overview PDF export, and charger updates
Add first launch event, share tracking for overview PDF and diagram
exports. Add SystemOverviewPDFExporter for A4 PDF generation. Update
charger model with new configuration fields and localization for all
5 languages. Refresh app icon assets and CLAUDE.md build instructions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 17:45:54 +01:00

67 lines
3.4 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Build & Test Commands
Use the **Xcode MCP server** tools instead of `xcodebuild` CLI:
- **List windows first**: Always run `mcp__xcode__XcodeListWindows` to find the correct `tabIdentifier` — it changes depending on which Xcode windows are open.
- **Build**: `mcp__xcode__BuildProject`
- **Run all tests**: `mcp__xcode__RunAllTests`
- **Check errors**: `mcp__xcode__GetBuildLog` (severity: `error`) or `mcp__xcode__XcodeListNavigatorIssues`
No external dependencies beyond the Xcode toolchain.
## Architecture
**SwiftUI + SwiftData app** for sizing low-voltage electrical conductors (boats, RVs, off-grid).
### Data Model Hierarchy
`ElectricalSystem` (top-level container) owns collections of:
- `SavedLoad` — individual electrical loads with wire sizing parameters
- `SavedBattery` — battery banks with chemistry-specific capacity rules
- `SavedCharger` — charging equipment specs
All are `@Model` classes persisted via SwiftData. The container is configured in `CableApp.swift` and injected into the SwiftUI environment.
### Key Layers
- **Calculation engine** (`Loads/ElectricalCalculations.swift`): Pure static functions for wire cross-section sizing, voltage drop, power loss, and fuse recommendations. Uses copper resistivity (0.017 Ω·mm²/m) with a 5% max voltage drop constraint. Supports both metric (mm²) and imperial (AWG) wire standards.
- **CableCalculator** (`Loads/CableCalculator.swift`): ObservableObject wrapper that bridges the calculation engine to SwiftUI views.
- **App-wide state**: `UnitSystemSettings` (metric/imperial, persisted to UserDefaults) and `StoreKitManager` (subscription status) are injected as `@EnvironmentObject`.
### Navigation Flow
`SystemsView` (root list) → `LoadsView` (per-system TabView with 4 tabs: Overview, Components, Batteries, Chargers) → individual editor modals for each entity type.
### Feature Organization
Each feature has its own directory under `Cable/`: `Loads/`, `Systems/`, `Batteries/`, `Chargers/`, `Overview/`, `Paywall/`. Models and views for each feature live together.
## Code Style
- 4-space indentation, trailing commas on multiline collections, 120-char soft line limit
- `UpperCamelCase` for types, `lowerCamelCase` for methods/properties
- Test naming: `testScenario_expectedResult`
- Commit messages: short imperative subjects under 50 characters
## Localization
5 languages: English (base), German, Spanish, French, Dutch. Translation files are in `*.lproj/Localizable.strings` and `Localizable.stringsdict`.
- Use `String(localized:defaultValue:)`**not** `NSLocalizedString`. The `defaultValue` serves as English fallback and avoids showing raw keys when a Localizable.strings entry is missing.
- When adding new user-facing strings, add translations to **all 5** Localizable.strings files immediately.
## PDF Export Pattern
PDF exports use `UIGraphicsPDFRenderer` with A4 portrait format. The pattern is:
- **Exporter struct** (e.g. `SystemOverviewPDFExporter`, `SystemBillOfMaterialsPDFExporter`) with snapshot data types — keeps Core Graphics rendering isolated from SwiftUI/SwiftData.
- **ShareSheet** triggered via `@State` item binding in the parent view.
- **Toolbar button** (not inline content) for the export action.
## StoreKit
Subscription product IDs: `app.voltplan.cable.weekly`, `app.voltplan.cable.yearly`. Pro features are gated via `StoreKitManager.isPro`.