Skip to content

Commit a18b834

Browse files
fix(06-02): improve mobile muscle list layout and grouping
- Issue 1: Two-line layout per muscle (name+ratio on line 1, progress bar on line 2) - Issue 2: Remove set totals from group headers (show group name + chevron only) - Issue 3: Merge Forearms into Arms group (reduce from 7 to 6 UI groups) Changes: - src/core/taxonomy.ts: Move Forearm muscles into Arms group, remove Forearms from UIMuscleGroup type - src/ui/components/mobile/MobileMuscleList.tsx: Two-line muscle layout with h-1 progress bar, remove group summary display
1 parent 3f0dc3f commit a18b834

2 files changed

Lines changed: 18 additions & 59 deletions

File tree

src/core/taxonomy.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ export type ExerciseMapping = Partial<Record<ScientificMuscle, number>>;
171171
* UI muscle group categories for displaying muscles in forms/editors.
172172
* This is the single source of truth for UI components like MuscleValueEditor.
173173
*/
174-
export type UIMuscleGroup = 'Back' | 'Chest' | 'Shoulders' | 'Arms' | 'Legs' | 'Core' | 'Forearms';
174+
export type UIMuscleGroup = 'Back' | 'Chest' | 'Shoulders' | 'Arms' | 'Legs' | 'Core';
175175

176176
/**
177177
* UI muscle groups with their constituent ScientificMuscles.
@@ -209,6 +209,8 @@ export const UI_MUSCLE_GROUPS: readonly { name: UIMuscleGroup; muscles: readonly
209209
'Biceps Brachii',
210210
'Triceps (Long Head)',
211211
'Triceps (Lateral/Medial)',
212+
'Forearm Flexors',
213+
'Forearm Extensors',
212214
],
213215
},
214216
{
@@ -232,11 +234,4 @@ export const UI_MUSCLE_GROUPS: readonly { name: UIMuscleGroup; muscles: readonly
232234
'Hip Flexors',
233235
],
234236
},
235-
{
236-
name: 'Forearms',
237-
muscles: [
238-
'Forearm Flexors',
239-
'Forearm Extensors',
240-
],
241-
},
242237
] as const;

src/ui/components/mobile/MobileMuscleList.tsx

Lines changed: 15 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -42,29 +42,6 @@ export function MobileMuscleList({
4242
return new Map<string, VolumeStatItem>(stats.map((s) => [s.name, s]));
4343
}, [stats]);
4444

45-
// Calculate group summaries for header display
46-
const groupSummaries = useMemo(() => {
47-
const summaries = new Map<
48-
string,
49-
{ totalVolume: number; totalGoal: number; percentage: number }
50-
>();
51-
52-
for (const group of UI_MUSCLE_GROUPS) {
53-
let totalVolume = 0;
54-
let totalGoal = 0;
55-
56-
for (const muscle of group.muscles) {
57-
const muscleStats = statsMap.get(muscle);
58-
totalVolume += muscleStats?.volume ?? 0;
59-
totalGoal += muscleStats?.goal ?? 0;
60-
}
61-
62-
const percentage = totalGoal > 0 ? (totalVolume / totalGoal) * 100 : 0;
63-
summaries.set(group.name, { totalVolume, totalGoal, percentage });
64-
}
65-
66-
return summaries;
67-
}, [statsMap]);
6845

6946
// Start with first group expanded (mobile-optimized: less initial scrolling)
7047
const [expandedGroups, setExpandedGroups] = useState<Set<string>>(() => {
@@ -105,9 +82,6 @@ export function MobileMuscleList({
10582
<div className="space-y-2">
10683
{UI_MUSCLE_GROUPS.map((group) => {
10784
const isExpanded = expandedGroups.has(group.name);
108-
const summary = groupSummaries.get(group.name);
109-
const groupPercentage = summary?.percentage ?? 0;
110-
const groupVolume = summary?.totalVolume ?? 0;
11185

11286
return (
11387
<div
@@ -138,36 +112,31 @@ export function MobileMuscleList({
138112

139113
{/* Group name */}
140114
<span className="font-medium text-white">{group.name}</span>
141-
142-
{/* Group summary - total sets with color indicating progress */}
143-
<div className="ml-auto flex items-center gap-2">
144-
<span
145-
className="font-mono text-sm"
146-
style={{ color: getVolumeColor(groupPercentage) }}
147-
>
148-
{formatVolume(groupVolume)}
149-
</span>
150-
<span className="text-primary-400 text-xs">sets</span>
151-
</div>
152115
</button>
153116

154117
{/* Group content - conditionally rendered */}
155118
{isExpanded && (
156-
<div className="bg-primary-900 p-3 space-y-1">
119+
<div className="bg-primary-900 p-3 space-y-3">
157120
{group.muscles.map((muscle) => {
158121
const muscleStats = statsMap.get(muscle);
159122
const volume = muscleStats?.volume ?? 0;
123+
const goal = muscleStats?.goal ?? 0;
160124
const percentage = muscleStats?.percentage ?? 0;
161125

162126
return (
163-
<div key={muscle} className="flex items-center gap-3 py-2">
164-
{/* Muscle name - flex-1 for overflow handling */}
165-
<span className="flex-1 text-sm text-primary-200 truncate">
166-
{muscle}
167-
</span>
168-
169-
{/* Progress bar container - fixed width for consistency */}
170-
<div className="w-24 h-2 overflow-hidden rounded-full bg-primary-800">
127+
<div key={muscle} className="space-y-1">
128+
{/* Line 1: Muscle name (left) + volume/goal ratio (right) */}
129+
<div className="flex items-center justify-between">
130+
<span className="text-sm text-primary-200">
131+
{muscle}
132+
</span>
133+
<span className="text-xs text-primary-400 font-mono">
134+
{formatVolume(volume)}/{formatVolume(goal)}
135+
</span>
136+
</div>
137+
138+
{/* Line 2: Progress bar - 4px tall (h-1), full width */}
139+
<div className="w-full h-1 overflow-hidden rounded-full bg-primary-800">
171140
<div
172141
className="h-full rounded-full transition-all duration-300"
173142
style={{
@@ -176,11 +145,6 @@ export function MobileMuscleList({
176145
}}
177146
/>
178147
</div>
179-
180-
{/* Numeric value - secondary emphasis (LIST-04) */}
181-
<span className="w-12 text-right text-xs text-primary-400 font-mono">
182-
{formatVolume(volume)}
183-
</span>
184148
</div>
185149
);
186150
})}

0 commit comments

Comments
 (0)