feat: add settings
This commit is contained in:
@@ -191,7 +191,8 @@
|
||||
}
|
||||
|
||||
/* Update main content spacing */
|
||||
#app-content {
|
||||
#app-content,
|
||||
#settings-content {
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
@@ -214,7 +215,8 @@
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.auth-form {
|
||||
.auth-form,
|
||||
.settings-form {
|
||||
min-width: 280px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
+31
@@ -6,6 +6,7 @@
|
||||
<title>Daily Calorie Tracker</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<link rel="stylesheet" href="auth.css">
|
||||
<link rel="stylesheet" href="settings.css">
|
||||
</head>
|
||||
<body>
|
||||
<!-- Authentication Header -->
|
||||
@@ -61,6 +62,7 @@
|
||||
<div id="user-info" class="user-info hidden">
|
||||
<div class="user-details">
|
||||
<span id="userName">Welcome, User!</span>
|
||||
<button id="settingsBtn" class="logout-btn">Settings</button>
|
||||
<button id="logoutBtn" class="logout-btn">Logout</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -88,18 +90,22 @@
|
||||
<div class="nutrition-summary" id="nutritionSummary">
|
||||
<div class="nutrition-item">
|
||||
<div class="nutrition-value" id="proteinValue">0</div>
|
||||
<div class="nutrition-label hidden" id="proteinGoalText">of 190</div>
|
||||
<div class="nutrition-label">Protein (g)</div>
|
||||
</div>
|
||||
<div class="nutrition-item">
|
||||
<div class="nutrition-value" id="fatValue">0</div>
|
||||
<div class="nutrition-label hidden" id="fatGoalText">of 190</div>
|
||||
<div class="nutrition-label">Fat (g)</div>
|
||||
</div>
|
||||
<div class="nutrition-item">
|
||||
<div class="nutrition-value" id="carboValue">0</div>
|
||||
<div class="nutrition-label hidden" id="carboGoalText">of 190</div>
|
||||
<div class="nutrition-label">Carbs (g)</div>
|
||||
</div>
|
||||
<div class="nutrition-item">
|
||||
<div class="nutrition-value" id="fiberValue">0</div>
|
||||
<div class="nutrition-label hidden" id="fiberGoalText">of 190</div>
|
||||
<div class="nutrition-label">Fiber (g)</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -183,6 +189,31 @@
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- Settings -->
|
||||
<section id="settings-content" class="hidden">
|
||||
<div class="container">
|
||||
<h1>⚙️ Settings</h1>
|
||||
|
||||
<div class="date-display">Define your macros goal</div>
|
||||
|
||||
<form id="settingsForm" class="settings-form">
|
||||
<div class="form-group">
|
||||
<input type="number" id="proteinGoal" placeholder="Proteins in grams" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="number" id="fatGoal" placeholder="Fat in grams" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="number" id="carboGoal" placeholder="Carbo in grams" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="number" id="fiberGoal" placeholder="Fiber in grams" required>
|
||||
</div>
|
||||
<button type="submit" class="settings-btn">Save</button>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script type="module" src="src/index.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
.settings-form {
|
||||
backdrop-filter: blur(10px);
|
||||
border-radius: 10px;
|
||||
padding: 25px;
|
||||
min-width: 300px;
|
||||
/* background: rgba(255, 255, 255, 0.1);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2); */
|
||||
}
|
||||
|
||||
.settings-form .form-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.settings-form input {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
border-radius: 6px;
|
||||
font-size: 1rem;
|
||||
backdrop-filter: blur(10px);
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.settings-form input::placeholder {
|
||||
color: rgba(0, 0, 0, 0.7);
|
||||
}
|
||||
|
||||
.settings-form input:focus {
|
||||
outline: none;
|
||||
border-color: #667eea;
|
||||
}
|
||||
|
||||
.settings-btn {
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
color: white;
|
||||
background: #667eea;
|
||||
border: 1px solid #667eea;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.settings-btn:hover {
|
||||
background: #8d9de7;
|
||||
border: 1px solid #8d9de7;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
+56
-1
@@ -1,5 +1,5 @@
|
||||
import { Client, Account, Databases, Query } from 'appwrite';
|
||||
import { FoodStorage } from './types';
|
||||
import { FoodStorage, UserSettings } from './types';
|
||||
|
||||
// Initialize Appwrite client
|
||||
const client = new Client();
|
||||
@@ -15,6 +15,7 @@ export const databases = new Databases(client);
|
||||
// Configuration constants
|
||||
export const DATABASE_ID = '684b38db000fac8c781c'; // Replace with your database ID
|
||||
export const FOOD_ENTRIES_COLLECTION_ID = '684b38e300336fc605dc'; // Replace with your collection ID
|
||||
export const USER_SETTINGS_COLLECTION_ID = '684c75140026689fe603'; // Replace with your collection ID
|
||||
|
||||
// Auth helper functions
|
||||
export class AppwriteAuth {
|
||||
@@ -98,6 +99,26 @@ export class AppwriteDB {
|
||||
}
|
||||
}
|
||||
|
||||
// Save food entry
|
||||
static async saveUserSettings(userSettings: UserSettings) {
|
||||
try {
|
||||
const response = await databases.createDocument(
|
||||
DATABASE_ID,
|
||||
USER_SETTINGS_COLLECTION_ID,
|
||||
'unique()',
|
||||
{
|
||||
...userSettings,
|
||||
userId: (await account.get()).$id,
|
||||
}
|
||||
);
|
||||
console.debug('User settings saved:', response);
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.error('Save user settings error:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Get user's food entries for a specific date
|
||||
static async getFoodEntries(date: Date) {
|
||||
try {
|
||||
@@ -119,6 +140,40 @@ export class AppwriteDB {
|
||||
}
|
||||
}
|
||||
|
||||
// get user's settings
|
||||
static async getUserSettings() {
|
||||
try {
|
||||
const user = await account.get();
|
||||
|
||||
const response = await databases.listDocuments(
|
||||
DATABASE_ID,
|
||||
USER_SETTINGS_COLLECTION_ID,
|
||||
[
|
||||
Query.equal('userId', user.$id),
|
||||
]
|
||||
);
|
||||
console.debug('User settings retrieved:', response);
|
||||
return response.documents;
|
||||
} catch (error) {
|
||||
console.error('Get user settings error:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
static async deleteUserSettings(documentId: string) {
|
||||
try {
|
||||
await databases.deleteDocument(
|
||||
DATABASE_ID,
|
||||
USER_SETTINGS_COLLECTION_ID,
|
||||
documentId
|
||||
);
|
||||
console.debug('User settings deleted:', documentId);
|
||||
} catch (error) {
|
||||
console.error('Delete user settings error:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete food entry
|
||||
static async deleteFoodEntry(documentId: string) {
|
||||
try {
|
||||
|
||||
+21
-14
@@ -12,19 +12,19 @@ export const foodDatabase: FoodItem[] = [
|
||||
{ name: 'Frutas - Melão', info: { calories: 29, protein: 0.7, fat: 0, carbs: 7.5, fiber: 0.3 } },
|
||||
{ name: 'Frutas - Uva', info: { calories: 53, protein: 0.7, fat: 0.2, carbs: 13.6, fiber: 0.9 } },
|
||||
|
||||
{ name: 'Vegetais - Agrião', info: { calories: 17, protein: 2.7, fat: 0.2, carbs: 2.3, fiber: 2.1 } },
|
||||
{ name: 'Vegetais - Brócolis (cozido)', info: { calories: 25, protein: 2.1, fat: 0.5, carbs: 4.4, fiber: 3.4 } },
|
||||
{ name: 'Vegetais - Cenoura (cozida)', info: { calories: 30, protein: 0.8, fat: 0.2, carbs: 6.7, fiber: 2.6 } },
|
||||
{ name: 'Vegetais - Couve flor (cozida)', info: { calories: 19, protein: 1.2, fat: 0.3, carbs: 3.9, fiber: 2.1 } },
|
||||
{ name: 'Vegetais - Ervilha (cozida)', info: { calories: 88, protein: 7.5, fat: 0.5, carbs: 14.2, fiber: 9.7 } },
|
||||
{ name: 'Vegetais - Espinafre', info: { calories: 16, protein: 2, fat: 0.2, carbs: 2.6, fiber: 2.1 } },
|
||||
{ name: 'Vegetais - Feijão preto (cozido)', info: { calories: 77, protein: 4.5, fat: 0.5, carbs: 14, fiber: 8.4 } },
|
||||
{ name: 'Vegetais - Lentilha (cozida)', info: { calories: 93, protein: 6.3, fat: 0.5, carbs: 16.3, fiber: 7.9 } },
|
||||
{ name: 'Vegetais - Mandioca (cozida)', info: { calories: 125, protein: 0.6, fat: 0.3, carbs: 30.1, fiber: 1.6 } },
|
||||
{ name: 'Vegetais - Pepino', info: { calories: 10, protein: 0.9, fat: 0, carbs: 2, fiber: 1.1 } },
|
||||
{ name: 'Vegetais - Rúcula', info: { calories: 13, protein: 1.8, fat: 0.1, carbs: 2.2, fiber: 1.7 } },
|
||||
{ name: 'Vegetais - Spirulina', info: { calories: 290, protein: 57.5, fat: 23.9, carbs: 7.7, fiber: 0 } },
|
||||
{ name: 'Vegetais - Tomate', info: { calories: 15, protein: 1.1, fat: 0.2, carbs: 3.1, fiber: 1.2 } },
|
||||
{ name: 'Verduras - Agrião', info: { calories: 17, protein: 2.7, fat: 0.2, carbs: 2.3, fiber: 2.1 } },
|
||||
{ name: 'Verduras - Espinafre', info: { calories: 16, protein: 2, fat: 0.2, carbs: 2.6, fiber: 2.1 } },
|
||||
{ name: 'Verduras - Rúcula', info: { calories: 13, protein: 1.8, fat: 0.1, carbs: 2.2, fiber: 1.7 } },
|
||||
|
||||
{ name: 'Legumes - Abóbora Cabotian (crua)', info: { calories: 39, protein: 1.7, fat: 0.5, carbs: 8.4, fiber: 2.2 } },
|
||||
{ name: 'Legumes - Abóbora Cabotian (cozida)', info: { calories: 48, protein: 1.4, fat: 0.7, carbs: 10.8, fiber: 2.5 } },
|
||||
{ name: 'Legumes - Brócolis (cozido)', info: { calories: 25, protein: 2.1, fat: 0.5, carbs: 4.4, fiber: 3.4 } },
|
||||
{ name: 'Legumes - Cenoura (cozida)', info: { calories: 30, protein: 0.8, fat: 0.2, carbs: 6.7, fiber: 2.6 } },
|
||||
{ name: 'Legumes - Couve flor (cozida)', info: { calories: 19, protein: 1.2, fat: 0.3, carbs: 3.9, fiber: 2.1 } },
|
||||
{ name: 'Legumes - Pepino', info: { calories: 10, protein: 0.9, fat: 0, carbs: 2, fiber: 1.1 } },
|
||||
{ name: 'Legumes - Tomate', info: { calories: 15, protein: 1.1, fat: 0.2, carbs: 3.1, fiber: 1.2 } },
|
||||
|
||||
{ name: 'Algas - Spirulina', info: { calories: 290, protein: 57.5, fat: 23.9, carbs: 7.7, fiber: 0 } },
|
||||
|
||||
{ name: 'Carboidratos - Batata doce (assada)', info: { calories: 90, protein: 2.0, fat: 0.1, carbs: 20.7, fiber: 3.3 } },
|
||||
{ name: 'Carboidratos - Batata doce (cozida)', info: { calories: 77, protein: 0.6, fat: 0.1, carbs: 18.4, fiber: 2.2 } },
|
||||
@@ -32,6 +32,7 @@ export const foodDatabase: FoodItem[] = [
|
||||
{ name: 'Carboidratos - Batata inglesa (assada)', info: { calories: 94, protein: 2.1, fat: 0.1, carbs: 21.8, fiber: 2.1 } },
|
||||
{ name: 'Carboidratos - Batata inglesa (cozida)', info: { calories: 52, protein: 1.2, fat: 0, carbs: 11.9, fiber: 1.3 } },
|
||||
{ name: 'Carboidratos - Batata inglesa (crua)', info: { calories: 64, protein: 1.8, fat: 0, carbs: 14.7, fiber: 1.2 } },
|
||||
{ name: 'Carboidratos - Mandioca (cozida)', info: { calories: 125, protein: 0.6, fat: 0.3, carbs: 30.1, fiber: 1.6 } },
|
||||
{ name: 'Carboidratos - Pão Francês', info: { calories: 300, protein: 8, fat: 3.1, carbs: 58.6, fiber: 2.3 } },
|
||||
{ name: 'Carboidrados - Polenta (cozida)', info: { calories: 192, protein: 4.8, fat: 1.2, carbs: 40, fiber: 3.8 } },
|
||||
|
||||
@@ -47,6 +48,9 @@ export const foodDatabase: FoodItem[] = [
|
||||
|
||||
{ name: 'Grãos - Arroz integral (cozido)', info: { calories: 130, protein: 2.7, fat: 0.3, carbs: 28, fiber: 0.4 } },
|
||||
{ name: 'Grãos - Aveia', info: { calories: 394, protein: 13.9, fat: 8.5, carbs: 66.6, fiber: 9.1 } },
|
||||
{ name: 'Grãos - Ervilha (cozida)', info: { calories: 88, protein: 7.5, fat: 0.5, carbs: 14.2, fiber: 9.7 } },
|
||||
{ name: 'Grãos - Feijão preto (cozido)', info: { calories: 77, protein: 4.5, fat: 0.5, carbs: 14, fiber: 8.4 } },
|
||||
{ name: 'Grãos - Lentilha (cozida)', info: { calories: 93, protein: 6.3, fat: 0.5, carbs: 16.3, fiber: 7.9 } },
|
||||
{ name: 'Grãos - Grão de Bico (cozido)', info: { calories: 180, protein: 9.5, fat: 3, carbs: 30, fiber: 8.6 } },
|
||||
{ name: 'Grãos - Pão integral de forma', info: { calories: 253, protein: 9.4, fat: 3.7, carbs: 49.9, fiber: 6.9 } },
|
||||
{ name: 'Grãos - Pipoca c/óleo', info: { calories: 448, protein: 9.9, fat: 15.9, carbs: 70.3, fiber: 14.3 } },
|
||||
@@ -57,6 +61,7 @@ export const foodDatabase: FoodItem[] = [
|
||||
{ name: 'Castanhas - Amendoin natural', info: { calories: 611, protein: 26, fat: 49, carbs: 16, fiber: 8.5 } },
|
||||
{ name: 'Castanhas - Castanha de Caju', info: { calories: 570, protein: 18.5, fat: 46.3, carbs: 29.1, fiber: 3.7 } },
|
||||
{ name: 'Castanhas - Castanha do Pará', info: { calories: 643, protein: 14.5, fat: 63.5, carbs: 15.1, fiber: 7.9 } },
|
||||
|
||||
{ name: 'Sementes - Semente de Chia', info: { calories: 490, protein: 15.6, fat: 30.7, carbs: 43.8, fiber: 37.7 } },
|
||||
{ name: 'Sementes - Semente de Linhaça', info: { calories: 495, protein: 14.1, fat: 32.3, carbs: 43.3, fiber: 33.5 } },
|
||||
{ name: 'Sementes - Semente de Gergelim', info: { calories: 584, protein: 21.2, fat: 50.4, carbs: 21.6, fiber: 11.9 } },
|
||||
@@ -67,5 +72,7 @@ export const foodDatabase: FoodItem[] = [
|
||||
{ name: 'Lanches - Melado', info: { calories: 297, protein: 0, fat: 0, carbs: 76.6, fiber: 0 } },
|
||||
{ name: 'Lanches - Pasta de Amendoim Growth', info: { calories: 544, protein: 27, fat: 33, carbs: 20, fiber: 8 } },
|
||||
{ name: 'Lanches - Goma de Tapioca', info: { calories: 226, protein: 0, fat: 0, carbs: 57, fiber: 0 } },
|
||||
{ name: 'Lanches - 70% Nibs Garoto', info: { calories: 544, protein: 8.4, fat: 40, carbs: 34, fiber: 0 } }
|
||||
{ name: 'Lanches - 70% Nibs Garoto', info: { calories: 544, protein: 8.4, fat: 40, carbs: 34, fiber: 0 } },
|
||||
|
||||
{ name: 'Óleos - Azeite de Oliva EV', info: { calories: 844, protein: 0, fat: 100, carbs: 0, fiber: 0 } }
|
||||
];
|
||||
|
||||
+169
-7
@@ -15,6 +15,7 @@ let currentUser: any | null = null;
|
||||
const authSection = document.getElementById('auth-section');
|
||||
const userInfo = document.getElementById('user-info');
|
||||
const appContent = document.getElementById('app-content');
|
||||
const settingsContent = document.getElementById('settings-content');
|
||||
const loadingOverlay = getDivById('loading-overlay');
|
||||
const loginForm = document.getElementById('login-form');
|
||||
const registerForm = document.getElementById('register-form');
|
||||
@@ -114,6 +115,77 @@ async function handleLogin(e: SubmitEvent) {
|
||||
}
|
||||
}
|
||||
|
||||
async function processResponseItems<T, R>(
|
||||
response: T[],
|
||||
processItem: (item: T) => Promise<R>
|
||||
): Promise<R[]> {
|
||||
|
||||
// Create promises for each item (but don't execute yet)
|
||||
const promises = response.map(item => processItem(item));
|
||||
|
||||
// Execute all promises concurrently and wait for completion
|
||||
const results = await Promise.all(promises);
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
// Example usage with API calls
|
||||
interface ResponseItem {
|
||||
id: string;
|
||||
data: string;
|
||||
}
|
||||
async function fetchItemDetails(item: ResponseItem): Promise<any> {
|
||||
const response = await fetch(`/api/items/${item.id}`);
|
||||
return response.json();
|
||||
}
|
||||
|
||||
// Main function that processes the response
|
||||
async function handleResponse(response: ResponseItem[]): Promise<void> {
|
||||
try {
|
||||
// This creates and executes all promises concurrently
|
||||
const results = await processResponseItems(response, fetchItemDetails);
|
||||
|
||||
console.log('All requests completed:', results);
|
||||
} catch (error) {
|
||||
console.error('One or more requests failed:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSaveSettings(e: SubmitEvent) {
|
||||
e.preventDefault();
|
||||
showLoading();
|
||||
|
||||
try {
|
||||
const proteinGoal = getInputById('proteinGoal').value;
|
||||
const fatGoal = getInputById('fatGoal').value;
|
||||
const carboGoal = getInputById('carboGoal').value;
|
||||
const fiberGoal = getInputById('fiberGoal').value;
|
||||
|
||||
// Delete existing settings - keep only the new one
|
||||
const documents = await AppwriteDB.getUserSettings();
|
||||
const promises = [];
|
||||
for (let i=0; i<documents.length; i++) {
|
||||
// keep going from here, the promises
|
||||
}
|
||||
|
||||
// Save to Appwrite
|
||||
await AppwriteDB.saveUserSettings({
|
||||
proteinGoal: parseInt(proteinGoal),
|
||||
fatGoal: parseInt(fatGoal),
|
||||
carboGoal: parseInt(carboGoal),
|
||||
fiberGoal: parseInt(fiberGoal),
|
||||
});
|
||||
|
||||
hideLoading();
|
||||
handleSettings();
|
||||
selectDate(selectedDate);
|
||||
} catch (error) {
|
||||
hideLoading();
|
||||
console.error('Saving error:', error);
|
||||
swal('Oh no!', 'Saving failed: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function handleLogout() {
|
||||
showLoading();
|
||||
|
||||
@@ -122,11 +194,52 @@ async function handleLogout() {
|
||||
currentUser = null;
|
||||
showAuthForms();
|
||||
clearAppData();
|
||||
hideLoading();
|
||||
} catch (error) {
|
||||
hideLoading();
|
||||
console.error('Logout error:', error);
|
||||
swal('Oh no!', 'Logout failed: ' + error.message, 'error');
|
||||
} finally {
|
||||
hideLoading();
|
||||
}
|
||||
}
|
||||
|
||||
async function handleSettings() {
|
||||
const showSettings = getButtonById('settingsBtn').textContent === 'Settings';
|
||||
|
||||
if (showSettings) {
|
||||
showLoading();
|
||||
|
||||
try {
|
||||
// Fetch goals from settings
|
||||
const settings = await AppwriteDB.getUserSettings();
|
||||
const hasGoals = Array.isArray(settings) && settings.length > 0;
|
||||
if (hasGoals) {
|
||||
const index = settings.length - 1;
|
||||
getInputById('proteinGoal').value = settings[index].proteinGoal;
|
||||
getInputById('fatGoal').value = settings[index].fatGoal;
|
||||
getInputById('carboGoal').value = settings[index].carboGoal;
|
||||
getInputById('fiberGoal').value = settings[index].fiberGoal;
|
||||
} else {
|
||||
getInputById('proteinGoal').value = '';
|
||||
getInputById('fatGoal').value = '';
|
||||
getInputById('carboGoal').value = '';
|
||||
getInputById('fiberGoal').value = '';
|
||||
}
|
||||
|
||||
getButtonById('settingsBtn').textContent = 'Back to App';
|
||||
|
||||
appContent?.classList.add('hidden');
|
||||
settingsContent?.classList.remove('hidden');
|
||||
hideLoading();
|
||||
} catch (error) {
|
||||
hideLoading();
|
||||
console.error('Fetching settings failed:', error);
|
||||
swal('Oh no!', 'Fetching settings failed: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
else {
|
||||
appContent?.classList.remove('hidden');
|
||||
settingsContent?.classList.add('hidden');
|
||||
getButtonById('settingsBtn').textContent = 'Settings';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,6 +365,8 @@ const setupEventListeners = () => {
|
||||
document.getElementById('loginForm')?.addEventListener('submit', handleLogin);
|
||||
document.getElementById('registerForm')?.addEventListener('submit', handleRegister);
|
||||
document.getElementById('logoutBtn')?.addEventListener('click', handleLogout);
|
||||
document.getElementById('settingsBtn')?.addEventListener('click', handleSettings);
|
||||
document.getElementById('settingsForm')?.addEventListener('submit', handleSaveSettings);
|
||||
}
|
||||
|
||||
const addDeleteEvents = () => {
|
||||
@@ -341,6 +456,22 @@ const addFood = async () => {
|
||||
// Update totals
|
||||
updateTotalCalories();
|
||||
|
||||
// Update total macros
|
||||
const proteinDiv: HTMLElement = getDivById('proteinValue');
|
||||
const fatDiv: HTMLElement = getDivById('fatValue');
|
||||
const carboDiv: HTMLElement = getDivById('carboValue');
|
||||
const fiberDiv: HTMLElement = getDivById('fiberValue');
|
||||
|
||||
const totalProtein: number = parseInt(proteinDiv.textContent ?? '0') + proportion.info.protein;
|
||||
const totalFat: number = parseInt(fatDiv.textContent ?? '0') + proportion.info.fat;
|
||||
const totalCarbs: number = parseInt(carboDiv.textContent ?? '0') + proportion.info.carbs;
|
||||
const totalFiber: number = parseInt(fiberDiv.textContent ?? '0') + proportion.info.fiber;
|
||||
|
||||
proteinDiv.textContent = (Math.round(totalProtein * 10) / 10).toString();
|
||||
fatDiv.textContent = (Math.round(totalFat * 10) / 10).toString();
|
||||
carboDiv.textContent = (Math.round(totalCarbs * 10) / 10).toString();
|
||||
fiberDiv.textContent = (Math.round(totalFiber * 10) / 10).toString();
|
||||
|
||||
// Reset form
|
||||
foodSelect.value = '';
|
||||
gramAmount.value = '100';
|
||||
@@ -408,6 +539,41 @@ async function loadFoodEntries(date: Date) {
|
||||
getDivById('fatValue').textContent = (Math.round(totalFat * 10) / 10).toString();
|
||||
getDivById('carboValue').textContent = (Math.round(totalCarbs * 10) / 10).toString();
|
||||
getDivById('fiberValue').textContent = (Math.round(totalFiber * 10) / 10).toString();
|
||||
|
||||
// Update goals
|
||||
const settings = await AppwriteDB.getUserSettings();
|
||||
const hasGoals = Array.isArray(settings) && settings.length > 0;
|
||||
if (hasGoals) {
|
||||
const index = settings.length - 1;
|
||||
getDivById('proteinGoalText').classList.add('hidden');
|
||||
if (parseInt(settings[index].proteinGoal) > 0) {
|
||||
getDivById('proteinGoalText').textContent = `of ${settings[index].proteinGoal}`;
|
||||
getDivById('proteinGoalText').classList.remove('hidden');
|
||||
}
|
||||
|
||||
getDivById('fatGoalText').classList.add('hidden');
|
||||
if (parseInt(settings[index].fatGoal) > 0) {
|
||||
getDivById('fatGoalText').textContent = `of ${settings[index].fatGoal}`;
|
||||
getDivById('fatGoalText').classList.remove('hidden');
|
||||
}
|
||||
|
||||
getDivById('carboGoalText').classList.add('hidden');
|
||||
if (parseInt(settings[index].carboGoal) > 0) {
|
||||
getDivById('carboGoalText').textContent = `of ${settings[index].carboGoal}`;
|
||||
getDivById('carboGoalText').classList.remove('hidden');
|
||||
}
|
||||
|
||||
getDivById('fiberGoalText').classList.add('hidden');
|
||||
if (parseInt(settings[index].fiberGoal) > 0) {
|
||||
getDivById('fiberGoalText').textContent = `of ${settings[index].fiberGoal}`;
|
||||
getDivById('fiberGoalText').classList.remove('hidden');
|
||||
}
|
||||
} else {
|
||||
getDivById('proteinGoalText').classList.add('hidden');
|
||||
getDivById('fatGoalText').classList.add('hidden');
|
||||
getDivById('carboGoalText').classList.add('hidden');
|
||||
getDivById('fiberGoalText').classList.add('hidden');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Load food entries error:', error);
|
||||
swal('Oh no!', 'Failed to load food entries: ' + error.message, 'error');
|
||||
@@ -437,11 +603,7 @@ async function handleDeleteFood(documentId: string, row: HTMLTableRowElement) {
|
||||
// Delete from Appwrite
|
||||
await AppwriteDB.deleteFoodEntry(documentId);
|
||||
|
||||
// Remove from table
|
||||
row.remove();
|
||||
|
||||
// Update totals
|
||||
updateTotalCalories();
|
||||
selectDate(selectedDate);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Delete food error:', error);
|
||||
|
||||
@@ -15,3 +15,11 @@ export type FoodStorage = {
|
||||
time: string;
|
||||
date: string;
|
||||
};
|
||||
|
||||
export type UserSettings = {
|
||||
id?: string;
|
||||
proteinGoal: number;
|
||||
fatGoal: number;
|
||||
carboGoal: number;
|
||||
fiberGoal: number;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user