/**
* Tabata Program Detail Screen
* Displays program overview, weeks, sessions, and progression for kiné programs
*/
import React from 'react'
import { View, Text, StyleSheet, ScrollView, Pressable } from 'react-native'
import { Stack, useRouter, useLocalSearchParams } from 'expo-router'
import { useSafeAreaInsets } from 'react-native-safe-area-context'
import { Icon } from '@/src/shared/components/Icon'
import { useTabataProgramStore } from '@/src/shared/stores/tabataProgramStore'
import { getTabataProgramById, getTabataSessionsByWeek } from '@/src/shared/data/tabata'
import { canAccessProgram } from '@/src/shared/services/access'
import { useUserStore } from '@/src/shared/stores/userStore'
import type { TabataProgramId } from '@/src/shared/types/program'
import { TYPOGRAPHY } from '@/src/shared/constants/typography'
import { SPACING } from '@/src/shared/constants/spacing'
import { RADIUS } from '@/src/shared/constants/borderRadius'
import { TEXT, NAVY, GREEN, BORDER_COLORS, AMBER, DARK } from '@/src/shared/constants/colors'
import { withOpacity } from '@/src/shared/utils/color'
export default function TabataProgramDetailScreen() {
const { id } = useLocalSearchParams<{ id: string }>()
const router = useRouter()
const insets = useSafeAreaInsets()
const programId = id as TabataProgramId
const program = getTabataProgramById(programId)
const selectProgram = useTabataProgramStore(s => s.selectProgram)
const progress = useTabataProgramStore(s => s.programsProgress[programId])
const isWeekUnlocked = useTabataProgramStore(s => s.isWeekUnlocked)
const getCurrentSession = useTabataProgramStore(s => s.getCurrentSession)
const completion = useTabataProgramStore(s => s.getProgramCompletion(programId))
const getProgramStatus = useTabataProgramStore(s => s.getProgramStatus)
const isPremium = useUserStore(s => s.profile.subscription) !== 'free'
const canAccess = canAccessProgram(programId, isPremium)
const status = getProgramStatus(programId)
if (!program) {
return (
Programme non trouvé
)
}
const handleStartProgram = () => {
selectProgram(programId)
const session = getCurrentSession(programId)
if (session) {
router.push(`/workout/${session.id}`)
}
}
const handleSessionPress = (sessionId: string) => {
router.push(`/workout/${sessionId}`)
}
return (
{/* Program header */}
{program.title}
{program.description}
{/* Tier badge */}
{program.tier === 'free' ? 'GRATUIT' : 'PREMIUM'}
{/* Stats row */}
{program.durationWeeks}
Semaines
{program.sessionsPerWeek}
Séances/sem
{program.totalSessions}
Séances
{/* Progress */}
{status === 'in-progress' && (
{completion}% complété
)}
{/* Principles */}
{program.principles.length > 0 && (
Principes
{program.principles.map((p, i) => (
•
{p}
))}
)}
{/* Weeks */}
{program.weeks.map(week => {
const unlocked = isWeekUnlocked(programId, week.weekNumber)
return (
Semaine {week.weekNumber}: {week.title}
{week.isDeload && (
Décharge
)}
{!unlocked && (
)}
{week.focus}
{/* Sessions */}
{week.sessions.map(session => {
const isCompleted = progress?.completedSessionIds.includes(session.id) ?? false
const sessionLocked = !unlocked
return (
!sessionLocked && canAccess && handleSessionPress(session.id)}
disabled={sessionLocked || !canAccess}
>
Séance {session.order}: {session.title}
{session.blocks.length} bloc{session.blocks.length > 1 ? 's' : ''} · {session.totalDuration} min · {session.calories} cal
{isCompleted && }
{!canAccess && !sessionLocked && }
)
})}
)
})}
{/* Completion criteria */}
{program.completionCriteria.length > 0 && (
Critères de passage
{program.completionCriteria.map((c, i) => (
✓
{c}
))}
)}
{/* CTA */}
{canAccess ? (
{status === 'in-progress' ? 'Continuer le programme' : status === 'completed' ? 'Recommencer' : 'Commencer le programme'}
) : (
router.push('/paywall')}>
Débloquer avec Premium
)}
)
}
const styles = StyleSheet.create({
container: { flex: 1, backgroundColor: NAVY[900] },
scrollView: { flex: 1 },
heroSection: { padding: SPACING[6], alignItems: 'center' },
iconCircle: { width: 64, height: 64, borderRadius: 32, alignItems: 'center', justifyContent: 'center', marginBottom: SPACING[3] },
programTitle: { ...TYPOGRAPHY.LARGE_TITLE, color: TEXT.PRIMARY, textAlign: 'center' },
programDescription: { ...TYPOGRAPHY.BODY, color: TEXT.SECONDARY, textAlign: 'center', marginTop: SPACING[2], lineHeight: 22 },
tierBadge: { marginTop: SPACING[3], paddingHorizontal: SPACING[2], paddingVertical: 3, borderRadius: RADIUS.SM, borderWidth: 1 },
tierBadgeText: { ...TYPOGRAPHY.LABEL },
statsRow: { flexDirection: 'row', marginTop: SPACING[6], gap: SPACING[8] },
statItem: { alignItems: 'center' },
statValue: { ...TYPOGRAPHY.TITLE_2, color: TEXT.PRIMARY },
statLabel: { ...TYPOGRAPHY.CAPTION_1, color: TEXT.TERTIARY, marginTop: 2 },
progressSection: { marginTop: SPACING[4], width: '100%' },
progressBar: { height: 4, borderRadius: RADIUS.PILL, backgroundColor: BORDER_COLORS.DIM, overflow: 'hidden' },
progressFill: { height: '100%', borderRadius: RADIUS.PILL },
progressText: { ...TYPOGRAPHY.CAPTION_1, color: TEXT.TERTIARY, marginTop: SPACING[1], textAlign: 'center' },
section: { paddingHorizontal: SPACING[5], marginTop: SPACING[6] },
sectionTitle: { ...TYPOGRAPHY.HEADLINE, color: TEXT.PRIMARY, marginBottom: SPACING[3] },
principleItem: { flexDirection: 'row', gap: SPACING[2], marginBottom: SPACING[2] },
principleBullet: { color: TEXT.TERTIARY, fontSize: 14 },
principleText: { ...TYPOGRAPHY.SUBHEADLINE, color: TEXT.SECONDARY, flex: 1, lineHeight: 20 },
weekSection: { paddingHorizontal: SPACING[5], marginTop: SPACING[6] },
weekHeader: { flexDirection: 'row', alignItems: 'center', gap: SPACING[2] },
weekTitle: { ...TYPOGRAPHY.TITLE_3, color: TEXT.PRIMARY, flex: 1 },
weekFocus: { ...TYPOGRAPHY.CAPTION_1, color: TEXT.TERTIARY, marginTop: SPACING[1], marginBottom: SPACING[3] },
deloadBadge: { backgroundColor: withOpacity(AMBER[500], 0.2), paddingHorizontal: SPACING[2], paddingVertical: 2, borderRadius: RADIUS.SM },
deloadText: { ...TYPOGRAPHY.LABEL, color: AMBER[500] },
sessionCard: { backgroundColor: NAVY[800], borderRadius: RADIUS.MD, padding: SPACING[3], marginBottom: SPACING[2], borderWidth: 1, borderColor: BORDER_COLORS.DIM },
sessionCardLocked: { opacity: 0.5 },
sessionInfo: { flexDirection: 'row', alignItems: 'center', gap: SPACING[3] },
sessionDot: { width: 8, height: 8, borderRadius: 4 },
sessionTitle: { ...TYPOGRAPHY.SUBHEADLINE, color: TEXT.PRIMARY },
sessionMeta: { ...TYPOGRAPHY.CAPTION_2, color: TEXT.TERTIARY, marginTop: 2 },
ctaContainer: { position: 'absolute', bottom: 0, left: 0, right: 0, paddingHorizontal: SPACING[5], paddingTop: SPACING[3], backgroundColor: DARK.SCRIM, borderTopWidth: 1, borderTopColor: BORDER_COLORS.DIM },
ctaButton: { height: 52, borderRadius: RADIUS.MD, alignItems: 'center', justifyContent: 'center' },
ctaText: { ...TYPOGRAPHY.BUTTON_MEDIUM, color: NAVY[900], letterSpacing: 0.5 },
errorText: { color: TEXT.SECONDARY, textAlign: 'center', marginTop: 100 },
})