import { StyleSheet, View } from 'react-native' import { Icon, ProgressBar, Text } from 'react-native-paper' import { useWellColors, WELL_SHADOW } from './wellSurface' // A neutral gray for a locked badge's own background - exported so a caller computing its own // badge color (unlocked ? tierColor : LOCKED_BADGE_COLOR, matching LightCycles' own achievements.tsx) // doesn't need to invent or duplicate this exact tone. export const LOCKED_BADGE_COLOR = 'rgba(128,128,128,0.3)' interface Props { icon: string title: string description: string // The badge's own background - pass the achievement's tier color when unlocked, or // LOCKED_BADGE_COLOR (this package's own export, above) when it isn't; this component doesn't // infer that from unlockedLabel itself, since a locked-vs-unlocked badge color scheme is a // caller-level design choice (see checkColor below for the identical reasoning on the status // icon's own color). badgeColor: string // undefined = locked. A precomputed display string (e.g. "Unlocked 2 days ago"), not a raw // timestamp - this component has no opinion on date formatting or streak conventions, which vary // per app (see LightCycles' own calendar-day-difference convention in its achievements.tsx). unlockedLabel?: string // Color for the unlocked check-circle icon and the locked progress bar - defaults to badgeColor. // Its own prop so a caller can tune it apart from the badge: AchievementCatalogSection passes the // tier color darkened in light mode, where raw gold and silver barely show on white, while the badge // keeps the true tier color behind its black glyph. checkColor?: string // Only rendered while locked (unlockedLabel is undefined) - 0..1. progress?: number // The "Same for every profile" note LightCycles shows for a device-scoped achievement viewed // from a specific profile's own tab - optional since only an app with per-profile stat views has // this concept at all. deviceMarker?: boolean // Independently optional overrides for this row's own text/background colors - each defaults to the well's // (wellSurface.ts: the theme's surface and its onSurface/onSurfaceVariant text), like StatSection/StatRow. A // caller with its own app-wide chrome palette passes whichever of the three it needs. fg?: string fgMuted?: string sectionBg?: string } // One row per achievement - a tier-colored (or locked-gray) badge, title/description, an optional // progress bar while locked, and either an unlocked check-mark+label or a lock icon. Extracted // verbatim from LightCycles' own achievements.tsx, where this exact row shape backed its entire // "ALL ACHIEVEMENTS" list. Each row is its own well (wellSurface.ts: the theme's surface on MD3's level-1 shadow); // fg/fgMuted/its own background default to the well's colors, each independently overridable via the matching // prop for a caller with its own chrome palette. Has no opinion on what an achievement actually IS (id, unlock predicate, catalog) // - that stays entirely app-local; this is purely the presentational row. export function AchievementRow({ icon, title, description, badgeColor, unlockedLabel, checkColor, progress, deviceMarker, fg: fgOverride, fgMuted: fgMutedOverride, sectionBg: sectionBgOverride }: Props) { const well = useWellColors() const fg = fgOverride ?? well.fg const fgMuted = fgMutedOverride ?? well.fgMuted const sectionBg = sectionBgOverride ?? well.bg const unlocked = unlockedLabel !== undefined return ( {title} {description} {deviceMarker && ( Same for every profile )} {!unlocked && progress !== undefined && } {unlocked ? ( {unlockedLabel} ) : ( )} ) } const styles = StyleSheet.create({ badge: { alignItems: 'center', borderRadius: 10, height: 36, justifyContent: 'center', width: 36 }, boldText: { fontWeight: 'bold' }, deviceMarker: { alignItems: 'center', flexDirection: 'row', gap: 4 }, progressBar: { borderRadius: 4, height: 6, marginTop: 6 }, row: { alignItems: 'center', borderRadius: 12, boxShadow: WELL_SHADOW, flexDirection: 'row', gap: 12, padding: 12 }, status: { alignItems: 'center', gap: 2, width: 64 }, text: { flex: 1, gap: 2 } })