Files
kegel/src/app/settings.tsx
marcuspaico 22c761cedc
Some checks failed
Build & Release APK / build (push) Has been cancelled
feat(ui): design polish pass — guide disc, button states, done screen
- GuideDisc breathes with work/rest inside the sweep ring; flicks
  pulse at flick rhythm since each 1s step re-triggers inflate
- Button variants (primary/secondary/danger) with pressed feedback
- Done screen: spring-in check ring + session stats card
- Settings: round -/+ stepper, disabled at 5-30s bounds
- Home hero glow, shared Card, drawn SVG gear replaces emoji

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-17 12:12:09 -07:00

81 lines
3.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Alert, Pressable, StyleSheet, Text, View } from "react-native";
import { Button, Card, StatRow } from "../components/ui";
import { adjustHold, currentHold, resetProgress } from "../lib/store";
import { C } from "../lib/theme";
import { useStore } from "../lib/useStore";
import { MAX_HOLD, MIN_HOLD } from "../lib/workout";
function StepperButton({ label, disabled, onPress }: { label: string; disabled: boolean; onPress: () => void }) {
return (
<Pressable
style={({ pressed }) => [s.step, disabled && s.stepDisabled, pressed && !disabled && s.stepPressed]}
onPress={onPress}
disabled={disabled}
>
<Text style={[s.stepText, disabled && s.stepTextDisabled]}>{label}</Text>
</Pressable>
);
}
export default function Settings() {
const { sessionsCompleted, holdAdjust } = useStore();
const hold = currentHold();
return (
<View style={s.screen}>
<Text style={s.section}>Difficulty</Text>
<Card style={{ marginBottom: 12 }}>
<View style={s.stepperRow}>
<StepperButton label="−" disabled={hold <= MIN_HOLD} onPress={() => adjustHold(-1)} />
<View style={s.stepperValue}>
<Text style={s.holdValue}>{hold}s</Text>
<Text style={s.holdLabel}>hold length</Text>
</View>
<StepperButton label="+" disabled={hold >= MAX_HOLD} onPress={() => adjustHold(1)} />
</View>
<StatRow label="Manual adjustment" value={`${holdAdjust >= 0 ? "+" : ""}${holdAdjust}s`} />
</Card>
<Text style={s.hint}>
Holds grow automatically by 1s every 3 completed sessions ({MIN_HOLD}–{MAX_HOLD}s). Adjust here if a session
feels too easy or too hard — the adjustment stacks with the automatic progression.
</Text>
<Text style={s.section}>Progress</Text>
<Button
title="Reset progress"
variant="danger"
onPress={() =>
Alert.alert("Reset progress?", `This clears ${sessionsCompleted} completed sessions and starts over at ${MIN_HOLD}s holds.`, [
{ text: "Cancel", style: "cancel" },
{ text: "Reset", style: "destructive", onPress: resetProgress },
])
}
/>
</View>
);
}
const s = StyleSheet.create({
screen: { flex: 1, backgroundColor: C.bg, padding: 20 },
section: { color: C.muted, fontSize: 13, textTransform: "uppercase", letterSpacing: 1.2, marginBottom: 8, marginTop: 12 },
stepperRow: { flexDirection: "row", alignItems: "center", justifyContent: "space-between", paddingVertical: 14 },
stepperValue: { alignItems: "center" },
holdValue: { color: C.accent, fontSize: 34, fontWeight: "700", fontVariant: ["tabular-nums"] },
holdLabel: { color: C.muted, fontSize: 12, textTransform: "uppercase", letterSpacing: 1.2, marginTop: 2 },
step: {
width: 52,
height: 52,
borderRadius: 26,
backgroundColor: C.surface2,
borderWidth: 1,
borderColor: C.border,
alignItems: "center",
justifyContent: "center",
},
stepPressed: { opacity: 0.7, transform: [{ scale: 0.95 }] },
stepDisabled: { opacity: 0.35 },
stepText: { color: C.text, fontSize: 26, fontWeight: "600", lineHeight: 30 },
stepTextDisabled: { color: C.muted },
hint: { color: C.muted, fontSize: 13, lineHeight: 19, marginBottom: 12 },
});