diff --git a/index.html b/index.html
index 197923d..f3d4dd3 100644
--- a/index.html
+++ b/index.html
@@ -149,6 +149,10 @@
diff --git a/src/appwrite.ts b/src/appwrite.ts
index d3a53b2..3dee252 100644
--- a/src/appwrite.ts
+++ b/src/appwrite.ts
@@ -98,6 +98,26 @@ export class AppwriteDB {
}
}
+ // Upadte food entry
+ static async updateFoodEntry(documentId: string, entryData: Partial) {
+ try {
+ const response = await databases.updateDocument(
+ DATABASE_ID,
+ FOOD_ENTRIES_COLLECTION_ID,
+ documentId,
+ {
+ ...entryData,
+ userId: (await account.get()).$id,
+ }
+ );
+ console.debug('Food entry updated:', response);
+ return response;
+ } catch (error) {
+ console.error('Update food entry error:', error);
+ throw error;
+ }
+ }
+
// Save food entry
static async saveUserSettings(userSettings: UserSettings) {
try {
diff --git a/src/foodDatabase.ts b/src/foodDatabase.ts
index 6156a0d..999acae 100644
--- a/src/foodDatabase.ts
+++ b/src/foodDatabase.ts
@@ -88,6 +88,7 @@ export const foodDatabase: FoodItem[] = [
{ name: 'Melão', info: { calories: 29, protein: 0.7, fat: 0, carbs: 7.5, fiber: 0.3, category: 'fruits', alkaline: true } },
{ name: 'Uva', info: { calories: 53, protein: 0.7, fat: 0.2, carbs: 13.6, fiber: 0.9, category: 'fruits', alkaline: true } },
{ name: 'Goiaba, branca, com casca, crua', info: { calories: 52, protein: 0.9, fat: 0.5, carbs: 12.4, fiber: 6.3, category: 'fruits', alkaline: true } },
+ { name: 'Morango, cru', info: { calories: 30, protein: 0.9, fat: 0.3, carbs: 6.8, fiber: 1.7, category: 'fruits', alkaline: true } },
// Dairy
{ name: 'Iogurte, natural, desnatado', info: { calories: 41, protein: 3.8, fat: 0.3, carbs: 5.8, fiber: 0, category: 'dairy', alkaline: true } },
@@ -117,7 +118,6 @@ export const foodDatabase: FoodItem[] = [
{ name: 'Couve flor, cozida', info: { calories: 19, protein: 1.2, fat: 0.3, carbs: 3.9, fiber: 2.1, category: 'carbs (low)', alkaline: true } },
{ name: 'Pepino', info: { calories: 10, protein: 0.9, fat: 0, carbs: 2, fiber: 1.1, category: 'carbs (low)', alkaline: true } },
{ name: 'Chuchu, cozido', info: { calories: 19, protein: 0.4, fat: 0, carbs: 4.9, fiber: 1.0, category: 'carbs (low)', alkaline: true } },
- { name: 'Cogumelo Paris, in natura', info: { calories: 17, protein: 4.9, fat: 0, carbs: 1, fiber: 1.7, category: 'proteins', alkaline: true } },
- { name: 'Milho, verde, enlatado, drenado', info: { calories: 98, protein: 3.2, fat: 2.4, carbs: 17.1, fiber: 4.6, category: 'proteins', alkaline: true } },
- { name: 'Morango, cru', info: { calories: 30, protein: 0.9, fat: 0.3, carbs: 6.8, fiber: 1.7, category: 'proteins', alkaline: true } },
+ { name: 'Cogumelo Paris, in natura', info: { calories: 17, protein: 4.9, fat: 0, carbs: 1, fiber: 1.7, category: 'carbs (low)', alkaline: true } },
+ { name: 'Milho, verde, enlatado, drenado', info: { calories: 98, protein: 3.2, fat: 2.4, carbs: 17.1, fiber: 4.6, category: 'carbs (low)', alkaline: true } },
];
diff --git a/src/index.ts b/src/index.ts
index 5af75ac..749caf5 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -285,6 +285,14 @@ function hideLoading() {
loadingOverlay.classList.add('hidden');
}
+function clearEditing() {
+ searchInput.value = '';
+ getInputById('gramAmount').value = '100';
+ showFoodPreview(false);
+ getButtonById('add-food-btn').innerHTML = 'Add Food';
+ selectedFood = null;
+}
+
// Clear application data
function clearAppData() {
getDivById('caloriesCounter').textContent = '0';
@@ -301,6 +309,7 @@ function clearAppData() {
totalCaloriesToday = 0;
totalGramsToday = 0;
totalAlkalineToday = 0;
+ getButtonById('cancel-food-btn').style.display = 'none';
}
const getFoodData = (grams: number, foodData: FoodItem): FoodItem => {
@@ -322,7 +331,7 @@ const getFoodData = (grams: number, foodData: FoodItem): FoodItem => {
const getFoodItemByName = (foodName: string): FoodItem => {
const foodDataSearch: FoodItem[] = foodDatabase.filter(f => f.name === foodName);
if (foodDataSearch.length === 0) {
- throw new Error(`Food not found for name ${name}`);
+ throw new Error(`Food not found for name ${foodName}`);
}
return foodDataSearch[0];
}
@@ -366,7 +375,11 @@ const setupEventListeners = () => {
});
getButtonById('add-food-btn').addEventListener('click', () => {
- addFood();
+ if (getButtonById('add-food-btn').innerHTML === 'Add Food') {
+ addFood();
+ } else {
+ updateFood();
+ }
});
getButtonById('next-month-btn').addEventListener('click', () => {
@@ -388,6 +401,10 @@ const setupEventListeners = () => {
toggleAuthForms();
});
+ getButtonById('cancel-food-btn').addEventListener('click', () => {
+ clearEditing();
+ });
+
// Auth forms
document.getElementById('loginForm')?.addEventListener('submit', handleLogin);
document.getElementById('registerForm')?.addEventListener('submit', handleRegister);
@@ -545,6 +562,38 @@ function selectFood(food: FoodItem) {
previewCalories(food);
}
+async function setFoodToEdit(foodId: string) {
+ showLoading();
+
+ try {
+ // get food item
+ const entries = await AppwriteDB.getFoodEntries(selectedDate);
+ const foodToEdit = entries.filter(entry => entry.$id === foodId);
+ if (foodToEdit.length === 0) {
+ swal('Hey!', 'Unable to get food entry from server', 'error');
+ return;
+ }
+
+ // set the selected food name and quantity
+ const foodData: FoodItem = getFoodItemByName(foodToEdit[0].name);
+ selectedFood = foodData;
+ searchInput.value = foodToEdit[0].name;
+ getInputById('gramAmount').value = foodToEdit[0].grams;
+ previewCalories(foodData)
+
+ getButtonById('add-food-btn').innerHTML = 'Save Food';
+ getInputById('foodIdToUpdate').value = foodId;
+ getInputById('foodTimeToUpdate').value = foodToEdit[0].time;
+
+ hideLoading();
+ } catch (error) {
+ console.error('Set food to edit error:', error);
+ swal('Oh no!', 'Failed to load food entry: ' + error.message, 'error');
+ } finally {
+ hideLoading();
+ }
+}
+
// Hide search results
function hideSearchResults() {
searchResults.classList.remove('show');
@@ -584,9 +633,7 @@ function editCardHandler(e: Event) {
const foodId = card.getAttribute('data-food-id');
if (foodId) {
- // FIXME: Implement edit functionality
- // handleEditFood(foodId);
- window.alert('Edit functionality is not implemented yet.');
+ setFoodToEdit(foodId);
}
}
@@ -624,6 +671,56 @@ const updateCurrentDate = () => {
});
}
+const updateFood = async () => {
+ if (!currentUser) {
+ swal('Hey!', 'Please log in to add food entries.', 'info');
+ return;
+ }
+
+ const gramAmount = getInputById('gramAmount');
+
+ if (!selectedFood || !gramAmount.value) {
+ swal('Hey!', 'Please select a food item and enter the amount', 'error');
+ return;
+ }
+
+ showLoading();
+
+ try {
+ const foodId = getInputById('foodIdToUpdate').value;
+ const grams: number = parseFloat(gramAmount.value);
+ const foodData: FoodItem = getFoodItemByName(selectedFood.name);
+
+ // Current date, with timezone
+ const date = new Date(selectedDate.getTime() - (selectedDate.getTimezoneOffset() * 60000)).toISOString();
+
+ // Calculate nutrition for the amount
+ const proportion: FoodItem = getFoodData(grams, foodData);
+ const entry: FoodStorage = {
+ name: selectedFood.name,
+ grams: grams,
+ calories: proportion.info.calories,
+ protein: proportion.info.protein,
+ fat: proportion.info.fat,
+ carbs: proportion.info.carbs,
+ fiber: proportion.info.fiber,
+ date: date.split('T')[0],
+ alkaline: selectedFood.info.alkaline,
+ time: getInputById('foodTimeToUpdate').value,
+ };
+
+ // Save to Appwrite
+ await AppwriteDB.updateFoodEntry(foodId, entry);
+ clearEditing();
+ selectDate(selectedDate);
+ } catch (error) {
+ console.error('Update food error:', error);
+ swal('Oh no!', 'Failed to update food entry: ' + error.message, 'error');
+ } finally {
+ hideLoading();
+ }
+}
+
// Add food to the log
const addFood = async () => {
if (!currentUser) {
@@ -634,7 +731,7 @@ const addFood = async () => {
const gramAmount = getInputById('gramAmount');
if (!selectedFood || !gramAmount.value) {
- swal('Hey!', 'Please select a food item and enter amount', 'error');
+ swal('Hey!', 'Please select a food item and enter the amount', 'error');
return;
}
@@ -1090,6 +1187,3 @@ function editFood(id: string) {
}
(window as any).selectFood = selectFood;
-(window as any).toggleCard = toggleCard;
-(window as any).editFood = editFood;
-(window as any).deleteFood = deleteFood;
diff --git a/style.css b/style.css
index ccbe813..bb2345c 100644
--- a/style.css
+++ b/style.css
@@ -402,7 +402,7 @@ h1 {
.add-food-form {
display: grid;
- grid-template-columns: 2fr 1fr auto;
+ grid-template-columns: 2fr 1fr 1fr auto;
gap: 15px;
align-items: end;
}
@@ -467,6 +467,24 @@ label {
box-shadow: 0 5px 15px rgba(76, 175, 80, 0.3);
}
+.cancel-btn {
+ padding: 17px 25px;
+ background: linear-gradient(135deg, #757575, #616161);
+ color: white;
+ border: none;
+ border-radius: 6px;
+ cursor: pointer;
+ font-size: 1rem;
+ font-weight: 600;
+ transition: all 0.3s ease;
+ height: fit-content;
+}
+
+.cancel-btn:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 5px 15px rgba(76, 175, 80, 0.3);
+}
+
.food-table-section {
background: white;
border-radius: 6px;