feat: Apple Watch app + Paywall + Privacy Policy + rebranding

## Major Features
- Apple Watch companion app (6 phases complete)
  - WatchConnectivity iPhone ↔ Watch
  - HealthKit integration (HR, calories)
  - SwiftUI premium UI
  - 9 complication types
  - Always-On Display support

- Paywall screen with RevenueCat integration
- Privacy Policy screen
- App rebranding: tabatago → TabataFit
- Bundle ID: com.millianlmx.tabatafit

## Changes
- New: ios/TabataFit Watch App/ (complete Watch app)
- New: app/paywall.tsx (subscription UI)
- New: app/privacy.tsx (privacy policy)
- New: src/features/watch/ (Watch sync hooks)
- New: admin-web/ (admin dashboard)
- Updated: app.json, package.json (branding)
- Updated: profile.tsx (paywall + privacy links)
- Updated: i18n translations (EN/FR/DE/ES)
- New: app icon 1024x1024

## Watch App Files
- TabataFitWatchApp.swift (entry point)
- ContentView.swift (premium UI)
- HealthKitManager.swift (HR + calories)
- WatchSessionManager.swift (communication)
- Complications/ (WidgetKit)
- UserDefaults+Shared.swift (data sharing)
This commit is contained in:
Millian Lamiaux
2026-03-11 09:43:53 +01:00
parent f80798069b
commit 2ad7ae3a34
86 changed files with 19648 additions and 365 deletions

67
assets/images/icon.svg Normal file
View File

@@ -0,0 +1,67 @@
<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
<!-- Background gradient -->
<defs>
<linearGradient id="bgGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#1a1a2e"/>
<stop offset="100%" style="stop-color:#16213e"/>
</linearGradient>
<linearGradient id="timerGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#FF6B35"/>
<stop offset="100%" style="stop-color:#FF8A5B"/>
</linearGradient>
<linearGradient id="flameGradient" x1="0%" y1="100%" x2="0%" y2="0%">
<stop offset="0%" style="stop-color:#FF6B35"/>
<stop offset="50%" style="stop-color:#FF8A5B"/>
<stop offset="100%" style="stop-color:#FFB347"/>
</linearGradient>
<filter id="glow" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur stdDeviation="8" result="coloredBlur"/>
<feMerge>
<feMergeNode in="coloredBlur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<!-- Background -->
<rect width="1024" height="1024" rx="220" fill="url(#bgGradient)"/>
<!-- Timer ring background -->
<circle cx="512" cy="512" r="320" stroke="#2a2a4a" stroke-width="40" fill="none"/>
<!-- Timer ring (animated feel - 75% complete) -->
<circle cx="512" cy="512" r="320" stroke="url(#timerGradient)" stroke-width="40" fill="none"
stroke-linecap="round" stroke-dasharray="1508" stroke-dashoffset="377"
transform="rotate(-90 512 512)" filter="url(#glow)"/>
<!-- Timer ticks -->
<g stroke="#3a3a5a" stroke-width="8" opacity="0.6">
<line x1="512" y1="152" x2="512" y2="192"/>
<line x1="512" y1="832" x2="512" y2="872"/>
<line x1="152" y1="512" x2="192" y2="512"/>
<line x1="832" y1="512" x2="872" y2="512"/>
</g>
<!-- Flame -->
<g transform="translate(512, 480)" filter="url(#glow)">
<!-- Outer flame -->
<path d="M0,-200 C60,-160 100,-80 80,0 C70,50 40,80 0,100 C-40,80 -70,50 -80,0 C-100,-80 -60,-160 0,-200 Z"
fill="url(#flameGradient)" opacity="0.9"/>
<!-- Middle flame -->
<path d="M0,-160 C40,-130 60,-60 50,0 C40,30 20,50 0,60 C-20,50 -40,30 -50,0 C-60,-60 -40,-130 0,-160 Z"
fill="#FFB347" opacity="0.8"/>
<!-- Inner flame (hot core) -->
<path d="M0,-100 C20,-80 30,-40 25,0 C20,15 10,25 0,30 C-10,25 -20,15 -25,0 C-30,-40 -20,-80 0,-100 Z"
fill="#FFF5E6" opacity="0.9"/>
</g>
<!-- Timer indicator dot -->
<circle cx="512" cy="192" r="24" fill="url(#timerGradient)" filter="url(#glow)"/>
<!-- Play button hint at bottom of flame -->
<g transform="translate(512, 620)">
<polygon points="0,-30 26,15 -26,15" fill="#FF6B35" opacity="0.8"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.7 KiB