# BusinessCard

A SwiftUI iOS + watchOS app that creates and shares digital business cards with QR codes, quick share actions, customization, and contact tracking. Data syncs across devices via iCloud.

## Platforms

- iOS 26+
- watchOS 12+
- Swift 6.2

## Features

### My Cards

- **Full-screen card display**: Swipe between your business cards in a full-screen view
- Tap the **edit icon** (pencil) in the top right to edit the current card
- Tap the **plus icon** to create a new card
- Set a default card for sharing
- **Modern card design**: Banner with optional cover photo, company logo, overlapping profile photo, clean contact rows
- **Header layout picker**: Choose how profile, cover, and logo images are arranged in the card header
  - **Profile Banner**: Profile photo fills the entire banner (great for personal branding)
  - **Cover + Avatar**: Cover image as banner with profile photo overlapping at bottom
  - **Centered Logo**: Cover image with company logo centered and profile avatar smaller
  - **Logo Badge**: Cover with small logo badge in corner, profile avatar overlapping
  - **Side by Side**: Avatar and logo displayed together in the content area
- **Smart layout suggestions**: The app suggests the best layout based on which images you've added
- **Live layout preview**: See exactly how each layout looks before selecting in both the picker and editor
- **Profile photos**: Add a headshot from library or camera with crop/zoom editor
- **Cover photos**: Add a custom banner background from library or camera
- **Company logos**: Upload a logo from library or camera
- **3-step photo workflow**: Choose source (library/camera) → crop/position → save
- **Rich profiles**: First/middle/last name, prefix, maiden name, preferred name, pronouns, headline, bio, accreditations
- **Clickable contact fields**: Tap any field to call, email, open link, or launch app

### Share

- **Floating share button**: Centered above the tab bar for quick access
- **Dark-themed share sheet**: Sleek QR code display with prominent sharing options
- Share options: copy link, SMS, email, WhatsApp, LinkedIn, and more
- **Offline sharing toggle**: Share your card without internet connection
- **Track shares**: Record who received your card and when
- Button is hidden when no cards exist
- Placeholder actions for Apple Wallet and NFC (alerts included)

### Card Editor

Access via the edit (pencil) icon in the My Cards tab:

- **Horizontal color picker**: Scrollable theme swatches for quick selection
- Theme picker with multiple color palettes (Coral, Midnight, Ocean, Lime, Violet)
- **Expandable name section**: Prefix, first, middle, last, maiden name, suffix, preferred name, pronouns
- **Edit all card details**: Name, role, department, company, headline, bio
- **Accreditations**: Tag-based input with inline editing

#### Dynamic Contact Fields

Add unlimited contact fields of any type, reorder by drag-and-drop:

- **Contact**: Email, phone, website, address
- **Social Media**: LinkedIn, X/Twitter, Instagram, Facebook, TikTok, Threads, Bluesky, Mastodon, Reddit, Twitch, YouTube, Snapchat, Pinterest
- **Developer**: GitHub, GitLab, Stack Overflow, CodePen
- **Messaging**: Telegram, WhatsApp, Discord, Slack, Matrix, Signal
- **Support & Funding**: Patreon, Ko-fi, Buy Me a Coffee, GitHub Sponsors
- **Payment**: Venmo, Cash App, PayPal, Zelle
- **Scheduling**: Calendly
- **Other**: Custom links with any URL

Each field has:
- **Custom icons**: Brand-colored icons from asset catalog (not generic SF Symbols)
- **Title/Label**: Add context like "Work", "Personal", or custom call-to-action
- **Deep linking**: Opens native apps when available (X, Instagram, etc.)
- **Drag-to-reorder**: Long press and drag to change order

- **Suggestion chips**: Quick-fill suggestions for field titles
- **Live preview**: "Preview card" button to see changes before saving
- **Delete cards** you no longer need

### Contacts

- **Add contacts manually**: Tap + to create contacts with name, role, company, email, phone
- **Profile photos**: Add or edit a photo for each contact
- Track who you've shared your card with
- **Scan QR codes** to save someone else's business card
- **Notes & annotations**: Add notes about each contact
- **Tags**: Organize contacts with comma-separated tags
- **Follow-up reminders**: Set reminder dates with overdue indicators
- **Where you met**: Record event or location where you connected
- Search contacts using localized matching (searches name, company, role, tags, notes)
- Shows last shared time and the card label used
- Swipe to delete contacts

### Widgets (Preview Only)

- Phone widget preview mock
- Watch widget preview mock

### watchOS App

- Shows the **default card QR code** full-screen (no card picker)
- Default card is determined by the iPhone app
- **Syncs with iPhone** via WatchConnectivity framework
- QR codes are pre-generated on iPhone (CoreImage not available on watchOS)

## Data Sync

### iCloud Sync (iOS)

Cards and contacts are stored using SwiftData with CloudKit sync enabled. Your data automatically syncs across all your iPhones and iPads signed into the same iCloud account.

### iPhone to Watch Sync

The iPhone app syncs card data to the paired Apple Watch via WatchConnectivity framework using `updateApplicationContext`. When you create, edit, or delete cards on your iPhone, the changes are pushed to your watch automatically.

**Note**: The watch receives data from the iPhone. To update cards on the watch, make changes on the iPhone first. QR codes are pre-generated on iPhone since CoreImage is not available on watchOS.

**IMPORTANT**: Do NOT use App Groups for iPhone-Watch communication. App Groups only work between an app and its extensions on the SAME device. iPhone and Apple Watch are separate devices with separate file systems.

## Architecture

- **Clean Architecture**: Clear separation between Views, State, Services, and Models
- **Views are dumb**: Presentation only, no business logic
- **State is smart**: `@Observable` classes with all business logic
- **Protocol-oriented**: Interfaces for services and stores
- **SwiftData + CloudKit**: Persistent storage with iCloud sync
- **WatchConnectivity**: iPhone to Apple Watch sync (NOT App Groups)
- **One type per file**: Lean, maintainable files under 300 lines
- **Reusable components**: Shared UI in `Views/Components/`
- **Bedrock package**: Shared design system and utilities
- **String Catalogs**: Localization for en, es-MX, fr-CA
- **Single source of truth for names**: `BusinessCard.fullName` is computed from individual name fields (no stored displayName)

## Dependencies

### Bedrock (Local Package)

The app uses the [Bedrock](ssh://git@192.168.1.128:220/mbrucedogs/Bedrock.git) package for:

- **Design constants**: `Design.Spacing`, `Design.CornerRadius`, `Design.Opacity`, etc.
- **QR code generation**: `QRCodeGenerator`, `QRCodeImageView`
- **Reusable UI components**: Settings views, badges, effects

App-specific extensions are in `Design/DesignConstants.swift`.

### Settings Layout Contract

`SettingsCard` is the single owner of horizontal row inset in `SettingsView`.

- Use `SettingsCardRow` for custom in-card rows (`HStack`, status/info rows, custom content).
- Use `SettingsDivider` between in-card rows (instead of `Divider`/manual lines).
- Use `SettingsNavigationRow(..., backgroundColor: .clear)` for standard in-card navigation rows.
- Avoid child `.padding(.horizontal, ...)` inside `SettingsCard` unless intentional indentation is required.

## Project Structure

```
BusinessCard/
├── Assets.xcassets/
│   └── SocialSymbols/   # Custom brand icons (LinkedIn, X, Instagram, etc.)
├── Configuration/       # App identifiers and configuration
│   ├── Base.xcconfig         # Source of truth for all identifiers
│   ├── Debug.xcconfig        # Debug configuration (imports Base)
│   ├── Release.xcconfig      # Release configuration (imports Base)
│   └── AppIdentifiers.swift  # Swift interface to configuration
├── Design/              # Design constants (extends Bedrock)
├── Localization/        # String helpers
├── Models/
│   ├── BusinessCard.swift    # Main card model
│   ├── CardHeaderLayout.swift # Header layout options (profile banner, cover+avatar, etc.)
│   ├── Contact.swift         # Received contacts
│   ├── ContactField.swift    # Dynamic contact fields (SwiftData)
│   └── ContactFieldType.swift # Field type definitions with icons & URLs
├── Protocols/           # Protocol definitions
├── Resources/           # String Catalogs (.xcstrings)
├── Services/            # ShareLinkService, VCardFileService, WatchConnectivityService
├── State/               # Observable stores (CardStore, ContactsStore)
└── Views/
    ├── Components/      # Reusable UI (ContactFieldPickerView, HeaderLayoutPickerView, etc.)
    ├── Sheets/          # Modal sheets (ContactFieldEditorSheet, RecordContactSheet, etc.)
    └── [Feature].swift  # Feature screens

BusinessCardWatch Watch App/  # watchOS app target (WatchConnectivity sync)
BusinessCardTests/       # Unit tests
```

## Configuration

### Required Capabilities

**iOS Target:**

- iCloud (CloudKit enabled)
- App Groups (`group.com.mbrucedogs.BusinessCard`) - for future widget access
- Background Modes (Remote notifications)
- Camera (for QR code scanning)

**watchOS Target:**

- WatchConnectivity (for receiving cards from iPhone)
- Bundle ID must be prefixed with iOS bundle ID (e.g., `com.mbrucedogs.BusinessCard.watchkitapp`)

### Watch App Embedding (CRITICAL)

The watch app must be embedded in the iOS app for deployment. In the iOS target's **Build Phases**:

1. **"Embed Watch Content"** phase must exist
2. **"Code Sign On Copy"** must be CHECKED ✓

Without this, the iOS app installs but the watch app does NOT install on the paired Apple Watch. See `Agents.md` for full troubleshooting guide.

### CloudKit Container

`iCloud.com.mbrucedogs.BusinessCard`

### App Identifiers (xcconfig)

All company-specific identifiers are centralized in `Configuration/Base.xcconfig`:

```
COMPANY_IDENTIFIER = com.mbrucedogs
DEVELOPMENT_TEAM = 6R7KLBPBLZ
```

This flows through:
- **Build settings**: Bundle IDs, Team ID (via xcconfig → project)
- **Entitlements**: CloudKit container, App Group (via variable substitution)
- **Swift code**: `AppIdentifiers.*` (via Info.plist → Bundle.main)

**To migrate to a new developer account**: Update `Base.xcconfig` only. See `DevAccount-Migration.md`.

## Notes

- Share URLs are sample placeholders
- Wallet/NFC flows are stubs with alerts only
- Widget UI is a visual preview (not a WidgetKit extension)

## Running

1. Open `BusinessCard.xcodeproj` in Xcode
2. Ensure Bedrock package is resolved (File → Packages → Resolve Package Versions)
3. Build and run on iOS Simulator or device

## Tests

Unit tests cover:

- vCard payload formatting
- Default card selection
- Contact search filtering
- Create, update, delete cards
- Contact tracking (new and existing contacts)
- Theme and layout assignment
- Social links detection
- Contact notes and tags
- Follow-up status and overdue detection
- vCard parsing for received cards
- Adding received cards via QR scan

Run tests with `Cmd+U` in Xcode.

## Roadmap

See [ROADMAP.md](ROADMAP.md) for planned features and implementation status.

---

*Built with SwiftUI, SwiftData, and ❤️*
