Skip to content

Commit fdc960b

Browse files
committed
src
food stuff changes
1 parent ec828e7 commit fdc960b

File tree

10 files changed

+368
-50
lines changed

10 files changed

+368
-50
lines changed

src/components/ActivityList.jsx

Lines changed: 56 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import { useState } from 'react'
12
import { format } from 'date-fns'
3+
import { useStore } from '../lib/store'
24
import styles from './ActivityList.module.css'
35

46
const sportIcons = {
@@ -9,7 +11,11 @@ const sportIcons = {
911
other: '🧘',
1012
}
1113

12-
export default function ActivityList({ workouts }) {
14+
export default function ActivityList({ workouts, showToast }) {
15+
const { deleteWorkout } = useStore()
16+
const [expandedItem, setExpandedItem] = useState(null)
17+
const [deleting, setDeleting] = useState(null)
18+
1319
if (workouts.length === 0) {
1420
return (
1521
<div className={styles.empty}>
@@ -28,29 +34,65 @@ export default function ActivityList({ workouts }) {
2834
return `${mins}:00`
2935
}
3036

37+
const handleDelete = async (id) => {
38+
setDeleting(id)
39+
try {
40+
await deleteWorkout(id)
41+
showToast?.('Workout deleted')
42+
} catch (error) {
43+
showToast?.('Failed to delete', 'error')
44+
}
45+
setDeleting(null)
46+
setExpandedItem(null)
47+
}
48+
49+
const toggleExpand = (id) => {
50+
setExpandedItem(expandedItem === id ? null : id)
51+
}
52+
3153
return (
3254
<div className={styles.list}>
3355
{workouts.map((workout, index) => (
3456
<div
3557
key={workout.id}
36-
className={styles.item}
58+
className={styles.itemWrapper}
3759
style={{ animationDelay: `${index * 0.1}s` }}
3860
>
39-
<div className={`${styles.icon} ${styles[workout.sport]}`}>
40-
{sportIcons[workout.sport] || '🏃'}
41-
</div>
42-
<div className={styles.info}>
43-
<div className={styles.name}>{workout.name || workout.sport}</div>
44-
<div className={styles.meta}>
45-
{format(new Date(workout.date), 'MMM d')} · {workout.environment || 'Workout'}
61+
<div
62+
className={styles.item}
63+
onClick={() => toggleExpand(workout.id)}
64+
>
65+
<div className={`${styles.icon} ${styles[workout.sport]}`}>
66+
{sportIcons[workout.sport] || '🏃'}
4667
</div>
47-
</div>
48-
<div className={styles.stats}>
49-
<div className={styles.duration}>{formatDuration(workout.duration_minutes)}</div>
50-
<div className={styles.distance}>
51-
{workout.distance ? `${workout.distance} ${workout.sport === 'swim' ? 'm' : 'km'}` : workout.sport}
68+
<div className={styles.info}>
69+
<div className={styles.name}>{workout.name || workout.sport}</div>
70+
<div className={styles.meta}>
71+
{format(new Date(workout.date), 'MMM d')} · {workout.environment || 'Workout'}
72+
</div>
73+
</div>
74+
<div className={styles.stats}>
75+
<div className={styles.duration}>{formatDuration(workout.duration_minutes)}</div>
76+
<div className={styles.distance}>
77+
{workout.distance ? `${workout.distance} ${workout.sport === 'swim' ? 'm' : 'km'}` : workout.sport}
78+
</div>
5279
</div>
5380
</div>
81+
82+
{expandedItem === workout.id && (
83+
<div className={styles.actions}>
84+
{workout.notes && (
85+
<div className={styles.notes}>📝 {workout.notes}</div>
86+
)}
87+
<button
88+
className={styles.deleteBtn}
89+
onClick={() => handleDelete(workout.id)}
90+
disabled={deleting === workout.id}
91+
>
92+
{deleting === workout.id ? 'Deleting...' : '🗑️ Delete'}
93+
</button>
94+
</div>
95+
)}
5496
</div>
5597
))}
5698
</div>

src/components/ActivityList.module.css

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,11 @@
44
gap: 12px;
55
}
66

7-
.item {
7+
.itemWrapper {
88
background: var(--bg-card);
99
border-radius: var(--radius-sm);
10-
padding: 16px 20px;
1110
border: 1px solid var(--border);
12-
display: flex;
13-
align-items: center;
14-
gap: 16px;
15-
transition: all 0.2s ease;
16-
cursor: pointer;
11+
overflow: hidden;
1712
animation: slideIn 0.4s ease-out backwards;
1813
}
1914

@@ -24,10 +19,19 @@
2419
}
2520
}
2621

27-
.item:hover {
22+
.itemWrapper:hover {
2823
border-color: var(--text-muted);
2924
}
3025

26+
.item {
27+
padding: 16px 20px;
28+
display: flex;
29+
align-items: center;
30+
gap: 16px;
31+
cursor: pointer;
32+
transition: all 0.2s ease;
33+
}
34+
3135
.icon {
3236
width: 48px;
3337
height: 48px;
@@ -76,6 +80,45 @@
7680
text-transform: capitalize;
7781
}
7882

83+
.actions {
84+
padding: 12px 20px 16px;
85+
border-top: 1px solid var(--border);
86+
display: flex;
87+
justify-content: space-between;
88+
align-items: center;
89+
animation: fadeIn 0.2s ease-out;
90+
}
91+
92+
@keyframes fadeIn {
93+
from { opacity: 0; }
94+
}
95+
96+
.notes {
97+
font-size: 13px;
98+
color: var(--text-secondary);
99+
flex: 1;
100+
}
101+
102+
.deleteBtn {
103+
padding: 8px 16px;
104+
background: rgba(239, 68, 68, 0.1);
105+
border: 1px solid var(--accent-red);
106+
border-radius: var(--radius-xs);
107+
color: var(--accent-red);
108+
font-size: 13px;
109+
cursor: pointer;
110+
transition: all 0.2s ease;
111+
}
112+
113+
.deleteBtn:hover:not(:disabled) {
114+
background: rgba(239, 68, 68, 0.2);
115+
}
116+
117+
.deleteBtn:disabled {
118+
opacity: 0.5;
119+
cursor: not-allowed;
120+
}
121+
79122
.empty {
80123
text-align: center;
81124
padding: 40px 20px;

src/components/FoodLog.jsx

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { useState } from 'react'
2+
import { useStore } from '../lib/store'
13
import styles from './FoodLog.module.css'
24

35
const mealInfo = {
@@ -7,9 +9,29 @@ const mealInfo = {
79
snack: { emoji: '🍎', label: 'Snacks' },
810
}
911

10-
export default function FoodLog({ meals, onAddFood }) {
12+
export default function FoodLog({ meals, onAddFood, showToast }) {
13+
const { deleteFoodEntry } = useStore()
14+
const [expandedItem, setExpandedItem] = useState(null)
15+
const [deleting, setDeleting] = useState(null)
16+
1117
const hasMeals = Object.values(meals).some(m => m.length > 0)
1218

19+
const handleDelete = async (id) => {
20+
setDeleting(id)
21+
try {
22+
await deleteFoodEntry(id)
23+
showToast?.('Food deleted')
24+
} catch (error) {
25+
showToast?.('Failed to delete', 'error')
26+
}
27+
setDeleting(null)
28+
setExpandedItem(null)
29+
}
30+
31+
const toggleExpand = (id) => {
32+
setExpandedItem(expandedItem === id ? null : id)
33+
}
34+
1335
if (!hasMeals) {
1436
return (
1537
<div className={styles.empty}>
@@ -41,14 +63,36 @@ export default function FoodLog({ meals, onAddFood }) {
4163
</div>
4264

4365
{foods.map(food => (
44-
<div key={food.id} className={styles.foodItem}>
45-
<div className={styles.foodInfo}>
46-
<span className={styles.foodName}>{food.food_name}</span>
47-
{food.quantity > 1 && (
48-
<span className={styles.foodQty}>× {food.quantity}</span>
49-
)}
66+
<div key={food.id} className={styles.foodItemWrapper}>
67+
<div
68+
className={styles.foodItem}
69+
onClick={() => toggleExpand(food.id)}
70+
>
71+
<div className={styles.foodInfo}>
72+
<span className={styles.foodName}>{food.food_name}</span>
73+
{food.quantity > 1 && (
74+
<span className={styles.foodQty}>× {food.quantity}</span>
75+
)}
76+
</div>
77+
<span className={styles.foodCals}>{(food.calories || 0) * (food.quantity || 1)} kcal</span>
5078
</div>
51-
<span className={styles.foodCals}>{(food.calories || 0) * (food.quantity || 1)} kcal</span>
79+
80+
{expandedItem === food.id && (
81+
<div className={styles.foodActions}>
82+
<div className={styles.foodMacros}>
83+
{food.protein && <span>P: {food.protein}g</span>}
84+
{food.carbs && <span>C: {food.carbs}g</span>}
85+
{food.fat && <span>F: {food.fat}g</span>}
86+
</div>
87+
<button
88+
className={styles.deleteBtn}
89+
onClick={() => handleDelete(food.id)}
90+
disabled={deleting === food.id}
91+
>
92+
{deleting === food.id ? 'Deleting...' : '🗑️ Delete'}
93+
</button>
94+
</div>
95+
)}
5296
</div>
5397
))}
5498
</div>

src/components/FoodLog.module.css

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,27 @@
3838
font-weight: 500;
3939
}
4040

41+
.foodItemWrapper {
42+
border-bottom: 1px solid var(--border);
43+
}
44+
45+
.foodItemWrapper:last-child {
46+
border-bottom: none;
47+
}
48+
4149
.foodItem {
4250
display: flex;
4351
justify-content: space-between;
4452
align-items: center;
45-
padding: 8px 0;
53+
padding: 12px 0;
54+
cursor: pointer;
55+
transition: background 0.2s ease;
4656
}
4757

48-
.foodItem:not(:last-child) {
49-
border-bottom: 1px solid var(--border);
58+
.foodItem:hover {
59+
background: var(--bg-elevated);
60+
margin: 0 -16px;
61+
padding: 12px 16px;
5062
}
5163

5264
.foodInfo {
@@ -69,6 +81,48 @@
6981
color: var(--text-secondary);
7082
}
7183

84+
.foodActions {
85+
display: flex;
86+
justify-content: space-between;
87+
align-items: center;
88+
padding: 8px 0 12px;
89+
animation: slideDown 0.2s ease-out;
90+
}
91+
92+
@keyframes slideDown {
93+
from {
94+
opacity: 0;
95+
transform: translateY(-8px);
96+
}
97+
}
98+
99+
.foodMacros {
100+
display: flex;
101+
gap: 12px;
102+
font-size: 12px;
103+
color: var(--text-muted);
104+
}
105+
106+
.deleteBtn {
107+
padding: 8px 16px;
108+
background: rgba(239, 68, 68, 0.1);
109+
border: 1px solid var(--accent-red);
110+
border-radius: var(--radius-xs);
111+
color: var(--accent-red);
112+
font-size: 13px;
113+
cursor: pointer;
114+
transition: all 0.2s ease;
115+
}
116+
117+
.deleteBtn:hover:not(:disabled) {
118+
background: rgba(239, 68, 68, 0.2);
119+
}
120+
121+
.deleteBtn:disabled {
122+
opacity: 0.5;
123+
cursor: not-allowed;
124+
}
125+
72126
.empty {
73127
text-align: center;
74128
padding: 40px 20px;

0 commit comments

Comments
 (0)