receita / index.html
wallaceblaia's picture
Add 2 files
f007f40 verified
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MenuMaster - Gerenciador de Cardápios</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
.dark-mode {
background-color: #1a202c;
color: #f7fafc;
}
.light-mode {
background-color: #f7fafc;
color: #1a202c;
}
.card-dark {
background-color: #2d3748;
border-color: #4a5568;
}
.card-light {
background-color: #ffffff;
border-color: #e2e8f0;
}
.transition-all {
transition: all 0.3s ease;
}
.max-h-0 {
max-height: 0;
overflow: hidden;
}
.max-h-screen {
max-height: 1000px;
}
#imagePreview {
max-width: 200px;
max-height: 200px;
}
</style>
</head>
<body class="light-mode min-h-screen">
<div class="container mx-auto px-4 py-8">
<!-- Header -->
<header class="flex justify-between items-center mb-8">
<h1 class="text-3xl font-bold text-indigo-600 dark:text-indigo-400">
<i class="fas fa-utensils mr-2"></i>MenuMaster
</h1>
<div class="flex items-center space-x-4">
<div class="relative">
<select id="userSelect" class="bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-indigo-500">
<option value="">Selecione um usuário</option>
</select>
</div>
<button id="themeToggle" class="p-2 rounded-full bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-200">
<i class="fas fa-moon dark:hidden"></i>
<i class="fas fa-sun hidden dark:inline"></i>
</button>
<button id="newUserBtn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-md">
<i class="fas fa-user-plus mr-1"></i> Novo Usuário
</button>
</div>
</header>
<!-- New User Modal -->
<div id="newUserModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
<div class="bg-white dark:bg-gray-800 rounded-lg p-6 w-full max-w-md">
<div class="flex justify-between items-center mb-4">
<h3 class="text-xl font-semibold dark:text-white">Novo Usuário</h3>
<button id="closeUserModal" class="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200">
<i class="fas fa-times"></i>
</button>
</div>
<div class="mb-4">
<label for="userName" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Nome do Usuário</label>
<input type="text" id="userName" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-white">
</div>
<div class="flex justify-end space-x-3">
<button id="cancelUserBtn" class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">Cancelar</button>
<button id="saveUserBtn" class="px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700">Salvar</button>
</div>
</div>
</div>
<!-- Tabs Navigation -->
<div class="mb-8">
<div class="flex border-b border-gray-200 dark:border-gray-700">
<button data-tab="items" class="tab-btn py-4 px-6 font-medium text-sm border-b-2 border-transparent hover:text-indigo-600 dark:hover:text-indigo-400 hover:border-gray-300 dark:hover:border-gray-600 transition-all flex items-center">
<i class="fas fa-cube mr-2"></i> Itens do Cardápio
</button>
<button data-tab="dishes" class="tab-btn py-4 px-6 font-medium text-sm border-b-2 border-transparent hover:text-indigo-600 dark:hover:text-indigo-400 hover:border-gray-300 dark:hover:border-gray-600 transition-all flex items-center">
<i class="fas fa-utensils mr-2"></i> Pratos
</button>
<button data-tab="menu" class="tab-btn py-4 px-6 font-medium text-sm border-b-2 border-transparent hover:text-indigo-600 dark:hover:text-indigo-400 hover:border-gray-300 dark:hover:border-gray-600 transition-all flex items-center">
<i class="fas fa-calendar-alt mr-2"></i> Cardápio Semanal
</button>
<button data-tab="report" class="tab-btn py-4 px-6 font-medium text-sm border-b-2 border-transparent hover:text-indigo-600 dark:hover:text-indigo-400 hover:border-gray-300 dark:hover:border-gray-600 transition-all flex items-center">
<i class="fas fa-file-alt mr-2"></i> Relatório
</button>
</div>
</div>
<!-- Items Tab Content -->
<div id="items-tab" class="tab-content">
<div class="flex justify-between items-center mb-6">
<h2 class="text-2xl font-semibold dark:text-white">
<i class="fas fa-cube mr-2"></i> Itens do Cardápio
</h2>
<button id="newItemBtn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-md flex items-center">
<i class="fas fa-plus mr-1"></i> Novo Item
</button>
</div>
<!-- Item Type Filter -->
<div class="mb-6 flex space-x-4">
<button data-filter="all" class="filter-btn px-4 py-2 bg-indigo-600 text-white rounded-md">Todos</button>
<button data-filter="protein" class="filter-btn px-4 py-2 bg-indigo-100 dark:bg-indigo-900 text-indigo-800 dark:text-indigo-200 rounded-md">Proteínas</button>
<button data-filter="side" class="filter-btn px-4 py-2 bg-indigo-100 dark:bg-indigo-900 text-indigo-800 dark:text-indigo-200 rounded-md">Acompanhamentos</button>
<button data-filter="dessert" class="filter-btn px-4 py-2 bg-indigo-100 dark:bg-indigo-900 text-indigo-800 dark:text-indigo-200 rounded-md">Sobremesas</button>
</div>
<!-- Items Grid -->
<div id="itemsGrid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<!-- Items will be loaded here -->
</div>
</div>
<!-- New Item Modal -->
<div id="itemModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
<div class="bg-white dark:bg-gray-800 rounded-lg p-6 w-full max-w-md max-h-screen overflow-y-auto">
<div class="flex justify-between items-center mb-4">
<h3 class="text-xl font-semibold dark:text-white">Novo Item</h3>
<button id="closeItemModal" class="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200">
<i class="fas fa-times"></i>
</button>
</div>
<form id="itemForm">
<div class="mb-4">
<label for="itemName" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Nome do Item</label>
<input type="text" id="itemName" required class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-white">
</div>
<div class="mb-4">
<label for="itemType" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Tipo</label>
<select id="itemType" required class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-white">
<option value="">Selecione...</option>
<option value="protein">Proteína</option>
<option value="side">Acompanhamento</option>
<option value="dessert">Sobremesa</option>
</select>
</div>
<div class="mb-4">
<label for="itemCalories" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Calorias (kcal)</label>
<input type="number" id="itemCalories" required class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-white">
</div>
<div class="mb-4">
<label for="itemQuantity" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Quantidade Disponível</label>
<input type="number" id="itemQuantity" required class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-white">
</div>
<div class="mb-4">
<label for="itemDescription" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Descrição</label>
<textarea id="itemDescription" rows="3" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-white"></textarea>
</div>
<div class="mb-4">
<label for="itemImage" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Imagem</label>
<input type="file" id="itemImage" accept="image/*" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-white">
<div class="mt-2">
<img id="imagePreview" src="#" alt="Preview" class="hidden rounded-md">
</div>
</div>
<input type="hidden" id="itemId">
<div class="flex justify-end space-x-3">
<button type="button" id="cancelItemBtn" class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">Cancelar</button>
<button type="submit" id="saveItemBtn" class="px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700">Salvar</button>
</div>
</form>
</div>
</div>
<!-- Dishes Tab Content -->
<div id="dishes-tab" class="tab-content hidden">
<div class="flex justify-between items-center mb-6">
<h2 class="text-2xl font-semibold dark:text-white">
<i class="fas fa-utensils mr-2"></i> Pratos
</h2>
<button id="newDishBtn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-md flex items-center">
<i class="fas fa-plus mr-1"></i> Novo Prato
</button>
</div>
<!-- Dishes Grid -->
<div id="dishesGrid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<!-- Dishes will be loaded here -->
</div>
</div>
<!-- New Dish Modal -->
<div id="dishModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
<div class="bg-white dark:bg-gray-800 rounded-lg p-6 w-full max-w-2xl max-h-screen overflow-y-auto">
<div class="flex justify-between items-center mb-4">
<h3 class="text-xl font-semibold dark:text-white">Novo Prato</h3>
<button id="closeDishModal" class="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200">
<i class="fas fa-times"></i>
</button>
</div>
<form id="dishForm">
<div class="mb-4">
<label for="dishName" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Nome do Prato</label>
<input type="text" id="dishName" required class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-white">
</div>
<div class="mb-4">
<label for="dishDescription" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Descrição</label>
<textarea id="dishDescription" rows="3" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-white"></textarea>
</div>
<div class="mb-6">
<h4 class="text-lg font-medium dark:text-white mb-3">Selecione os Itens</h4>
<div class="mb-4">
<h5 class="font-medium dark:text-white mb-2">Proteínas</h5>
<div id="proteinItems" class="space-y-2">
<!-- Protein items will be loaded here -->
</div>
</div>
<div class="mb-4">
<h5 class="font-medium dark:text-white mb-2">Acompanhamentos</h5>
<div id="sideItems" class="space-y-2">
<!-- Side items will be loaded here -->
</div>
</div>
<div class="mb-4">
<h5 class="font-medium dark:text-white mb-2">Sobremesas</h5>
<div id="dessertItems" class="space-y-2">
<!-- Dessert items will be loaded here -->
</div>
</div>
</div>
<div class="mb-4 p-4 rounded-lg bg-indigo-50 dark:bg-indigo-900">
<h4 class="font-medium dark:text-white mb-2">Resumo Nutricional</h4>
<div class="flex justify-between">
<span class="text-gray-700 dark:text-gray-300">Calorias totais:</span>
<span id="totalCalories" class="font-semibold">0 kcal</span>
</div>
</div>
<input type="hidden" id="dishId">
<div class="flex justify-end space-x-3">
<button type="button" id="cancelDishBtn" class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">Cancelar</button>
<button type="submit" id="saveDishBtn" class="px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700">Salvar</button>
</div>
</form>
</div>
</div>
<!-- Menu Tab Content -->
<div id="menu-tab" class="tab-content hidden">
<div class="flex justify-between items-center mb-6">
<h2 class="text-2xl font-semibold dark:text-white">
<i class="fas fa-calendar-alt mr-2"></i> Cardápio Semanal
</h2>
<button id="generateMenuBtn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-md flex items-center">
<i class="fas fa-magic mr-1"></i> Gerar Cardápio
</button>
</div>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
<thead class="bg-gray-50 dark:bg-gray-800">
<tr>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Dia</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Almoço</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Jantar</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Ações</th>
</tr>
</thead>
<tbody id="menuTableBody" class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
<!-- Menu will be loaded here -->
</tbody>
</table>
</div>
</div>
<!-- Report Tab Content -->
<div id="report-tab" class="tab-content hidden">
<div class="flex justify-between items-center mb-6">
<h2 class="text-2xl font-semibold dark:text-white">
<i class="fas fa-file-alt mr-2"></i> Relatório Semanal
</h2>
<button id="printReportBtn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-md flex items-center">
<i class="fas fa-print mr-1"></i> Imprimir Relatório
</button>
</div>
<div id="reportContent" class="bg-white dark:bg-gray-800 p-6 rounded-lg shadow">
<div class="flex justify-between items-center mb-6">
<div>
<h3 class="text-xl font-bold dark:text-white">Relatório Semanal</h3>
<p class="text-gray-600 dark:text-gray-400" id="reportDateRange">Semana de 01/01/2023 a 07/01/2023</p>
</div>
<div class="text-right">
<h4 class="text-lg font-semibold dark:text-white">Total de Calorias</h4>
<p class="text-2xl font-bold text-indigo-600 dark:text-indigo-400" id="reportTotalCalories">0 kcal</p>
</div>
</div>
<div class="mb-8">
<h4 class="text-lg font-semibold border-b pb-2 mb-4 dark:text-white dark:border-gray-700">Cardápio Semanal</h4>
<div id="weeklyMenuReport" class="space-y-6">
<!-- Weekly menu report will be loaded here -->
</div>
</div>
<div>
<h4 class="text-lg font-semibold border-b pb-2 mb-4 dark:text-white dark:border-gray-700">Estoque de Ingredientes</h4>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Item</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Tipo</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Quantidade</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Status</th>
</tr>
</thead>
<tbody id="inventoryReport" class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
<!-- Inventory report will be loaded here -->
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<script>
// Data storage
let users = JSON.parse(localStorage.getItem('menuMasterUsers')) || [];
let currentUser = null;
let items = [];
let dishes = [];
let weeklyMenu = [];
// DOM Elements
const themeToggle = document.getElementById('themeToggle');
const userSelect = document.getElementById('userSelect');
const newUserBtn = document.getElementById('newUserBtn');
const newUserModal = document.getElementById('newUserModal');
const closeUserModal = document.getElementById('closeUserModal');
const cancelUserBtn = document.getElementById('cancelUserBtn');
const saveUserBtn = document.getElementById('saveUserBtn');
const userName = document.getElementById('userName');
// Tab elements
const tabContents = document.querySelectorAll('.tab-content');
const tabButtons = document.querySelectorAll('.tab-btn');
// Item elements
const newItemBtn = document.getElementById('newItemBtn');
const itemModal = document.getElementById('itemModal');
const closeItemModal = document.getElementById('closeItemModal');
const cancelItemBtn = document.getElementById('cancelItemBtn');
const saveItemBtn = document.getElementById('saveItemBtn');
const itemForm = document.getElementById('itemForm');
const itemsGrid = document.getElementById('itemsGrid');
const filterButtons = document.querySelectorAll('.filter-btn');
const itemImage = document.getElementById('itemImage');
const imagePreview = document.getElementById('imagePreview');
// Dish elements
const newDishBtn = document.getElementById('newDishBtn');
const dishModal = document.getElementById('dishModal');
const closeDishModal = document.getElementById('closeDishModal');
const cancelDishBtn = document.getElementById('cancelDishBtn');
const saveDishBtn = document.getElementById('saveDishBtn');
const dishForm = document.getElementById('dishForm');
const dishesGrid = document.getElementById('dishesGrid');
const proteinItems = document.getElementById('proteinItems');
const sideItems = document.getElementById('sideItems');
const dessertItems = document.getElementById('dessertItems');
const totalCalories = document.getElementById('totalCalories');
// Menu elements
const generateMenuBtn = document.getElementById('generateMenuBtn');
const menuTableBody = document.getElementById('menuTableBody');
// Report elements
const printReportBtn = document.getElementById('printReportBtn');
const reportContent = document.getElementById('reportContent');
// Initialize the app
document.addEventListener('DOMContentLoaded', () => {
loadUsers();
setupEventListeners();
updateUI();
});
// Load users from localStorage
function loadUsers() {
userSelect.innerHTML = '<option value="">Selecione um usuário</option>';
users.forEach(user => {
const option = document.createElement('option');
option.value = user.id;
option.textContent = user.name;
userSelect.appendChild(option);
});
}
// Setup event listeners
function setupEventListeners() {
// Theme toggle
themeToggle.addEventListener('click', toggleTheme);
// User management
userSelect.addEventListener('change', (e) => {
currentUser = users.find(user => user.id === e.target.value) || null;
if (currentUser) {
loadUserData();
}
updateUI();
});
newUserBtn.addEventListener('click', () => {
newUserModal.classList.remove('hidden');
});
closeUserModal.addEventListener('click', () => {
newUserModal.classList.add('hidden');
});
cancelUserBtn.addEventListener('click', () => {
newUserModal.classList.add('hidden');
});
saveUserBtn.addEventListener('click', addNewUser);
// Tab navigation
tabButtons.forEach(button => {
button.addEventListener('click', () => {
const tabId = button.getAttribute('data-tab');
showTab(tabId);
});
});
// Item management
newItemBtn.addEventListener('click', () => {
showItemModal();
});
closeItemModal.addEventListener('click', () => {
itemModal.classList.add('hidden');
});
cancelItemBtn.addEventListener('click', () => {
itemModal.classList.add('hidden');
});
itemForm.addEventListener('submit', (e) => {
e.preventDefault();
saveItem();
});
itemImage.addEventListener('change', (e) => {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = (event) => {
imagePreview.src = event.target.result;
imagePreview.classList.remove('hidden');
};
reader.readAsDataURL(file);
}
});
// Filter buttons
filterButtons.forEach(button => {
button.addEventListener('click', () => {
const filter = button.getAttribute('data-filter');
filterItems(filter);
});
});
// Dish management
newDishBtn.addEventListener('click', () => {
showDishModal();
});
closeDishModal.addEventListener('click', () => {
dishModal.classList.add('hidden');
});
cancelDishBtn.addEventListener('click', () => {
dishModal.classList.add('hidden');
});
dishForm.addEventListener('submit', (e) => {
e.preventDefault();
saveDish();
});
// Menu management
generateMenuBtn.addEventListener('click', generateWeeklyMenu);
// Report management
printReportBtn.addEventListener('click', printReport);
}
// Toggle between dark and light theme
function toggleTheme() {
const body = document.body;
if (body.classList.contains('dark-mode')) {
body.classList.remove('dark-mode');
body.classList.add('light-mode');
} else {
body.classList.remove('light-mode');
body.classList.add('dark-mode');
}
}
// Add new user
function addNewUser() {
const name = userName.value.trim();
if (name === '') return;
const newUser = {
id: Date.now().toString(),
name: name,
items: [],
dishes: [],
weeklyMenu: []
};
users.push(newUser);
localStorage.setItem('menuMasterUsers', JSON.stringify(users));
userName.value = '';
newUserModal.classList.add('hidden');
loadUsers();
// Select the new user
userSelect.value = newUser.id;
currentUser = newUser;
updateUI();
}
// Load user data
function loadUserData() {
if (!currentUser) return;
items = currentUser.items || [];
dishes = currentUser.dishes || [];
weeklyMenu = currentUser.weeklyMenu || [];
renderItems();
renderDishes();
renderWeeklyMenu();
renderReport();
}
// Save user data
function saveUserData() {
if (!currentUser) return;
currentUser.items = items;
currentUser.dishes = dishes;
currentUser.weeklyMenu = weeklyMenu;
localStorage.setItem('menuMasterUsers', JSON.stringify(users));
}
// Update UI based on current state
function updateUI() {
const hasUser = currentUser !== null;
// Enable/disable tabs based on user selection
tabButtons.forEach((button, index) => {
if (index > 0) { // Skip the first tab (items)
button.disabled = !hasUser;
}
});
// Enable/disable buttons
newItemBtn.disabled = !hasUser;
newDishBtn.disabled = !hasUser;
generateMenuBtn.disabled = !hasUser;
printReportBtn.disabled = !hasUser;
// Show appropriate content
if (!hasUser) {
showTab('items');
itemsGrid.innerHTML = '<div class="col-span-full text-center py-8 text-gray-500">Selecione um usuário para começar</div>';
}
}
// Show selected tab
function showTab(tabId) {
tabContents.forEach(content => {
content.classList.add('hidden');
});
tabButtons.forEach(button => {
button.classList.remove('border-indigo-600', 'text-indigo-600', 'dark:border-indigo-400', 'dark:text-indigo-400');
});
document.getElementById(`${tabId}-tab`).classList.remove('hidden');
document.querySelector(`[data-tab="${tabId}"]`).classList.add('border-indigo-600', 'text-indigo-600', 'dark:border-indigo-400', 'dark:text-indigo-400');
}
// Show item modal
function showItemModal(item = null) {
if (!currentUser) return;
itemForm.reset();
imagePreview.src = '#';
imagePreview.classList.add('hidden');
if (item) {
document.getElementById('itemId').value = item.id;
document.getElementById('itemName').value = item.name;
document.getElementById('itemType').value = item.type;
document.getElementById('itemCalories').value = item.calories;
document.getElementById('itemQuantity').value = item.quantity;
document.getElementById('itemDescription').value = item.description || '';
if (item.image) {
imagePreview.src = item.image;
imagePreview.classList.remove('hidden');
}
document.querySelector('#itemModal h3').textContent = 'Editar Item';
} else {
document.getElementById('itemId').value = '';
document.querySelector('#itemModal h3').textContent = 'Novo Item';
}
itemModal.classList.remove('hidden');
}
// Save item
function saveItem() {
const id = document.getElementById('itemId').value;
const name = document.getElementById('itemName').value.trim();
const type = document.getElementById('itemType').value;
const calories = parseInt(document.getElementById('itemCalories').value);
const quantity = parseInt(document.getElementById('itemQuantity').value);
const description = document.getElementById('itemDescription').value.trim();
const image = imagePreview.src !== '#' ? imagePreview.src : '';
if (!name || !type || isNaN(calories) || isNaN(quantity)) return;
const itemData = {
id: id || Date.now().toString(),
name,
type,
calories,
quantity,
description,
image
};
if (id) {
// Update existing item
const index = items.findIndex(item => item.id === id);
if (index !== -1) {
items[index] = itemData;
}
} else {
// Add new item
items.push(itemData);
}
saveUserData();
renderItems();
itemModal.classList.add('hidden');
}
// Delete item
function deleteItem(id) {
if (!confirm('Tem certeza que deseja excluir este item?')) return;
items = items.filter(item => item.id !== id);
saveUserData();
renderItems();
}
// Filter items by type
function filterItems(type) {
filterButtons.forEach(button => {
if (button.getAttribute('data-filter') === type) {
button.classList.remove('bg-indigo-100', 'dark:bg-indigo-900', 'text-indigo-800', 'dark:text-indigo-200');
button.classList.add('bg-indigo-600', 'text-white');
} else {
button.classList.remove('bg-indigo-600', 'text-white');
button.classList.add('bg-indigo-100', 'dark:bg-indigo-900', 'text-indigo-800', 'dark:text-indigo-200');
}
});
renderItems(type);
}
// Render items
function renderItems(filter = 'all') {
if (!currentUser) return;
let filteredItems = items;
if (filter !== 'all') {
filteredItems = items.filter(item => item.type === filter);
}
if (filteredItems.length === 0) {
itemsGrid.innerHTML = `<div class="col-span-full text-center py-8 text-gray-500">Nenhum item encontrado</div>`;
return;
}
itemsGrid.innerHTML = '';
filteredItems.forEach(item => {
const itemCard = document.createElement('div');
itemCard.className = 'rounded-lg overflow-hidden shadow-md transition-all hover:shadow-lg card-light dark:card-dark';
let typeBadge = '';
let badgeColor = '';
switch (item.type) {
case 'protein':
typeBadge = 'Proteína';
badgeColor = 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200';
break;
case 'side':
typeBadge = 'Acompanhamento';
badgeColor = 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200';
break;
case 'dessert':
typeBadge = 'Sobremesa';
badgeColor = 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200';
break;
}
const status = item.quantity > 0 ?
`<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200">
Disponível (${item.quantity})
</span>` :
`<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200">
Indisponível
</span>`;
itemCard.innerHTML = `
<div class="p-4">
<div class="flex justify-between items-start">
<div>
<h3 class="text-lg font-semibold dark:text-white">${item.name}</h3>
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${badgeColor} mt-1">
${typeBadge}
</span>
</div>
${status}
</div>
${item.image ? `
<div class="mt-3">
<img src="${item.image}" alt="${item.name}" class="w-full h-32 object-cover rounded-md">
</div>
` : ''}
<div class="mt-3">
<p class="text-sm text-gray-600 dark:text-gray-300">${item.description || 'Sem descrição'}</p>
</div>
<div class="mt-4 flex justify-between items-center">
<span class="text-sm font-medium dark:text-white">${item.calories} kcal</span>
<div class="flex space-x-2">
<button onclick="editItem('${item.id}')" class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300">
<i class="fas fa-edit"></i>
</button>
<button onclick="deleteItem('${item.id}')" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</div>
`;
itemsGrid.appendChild(itemCard);
});
}
// Edit item (global function)
window.editItem = function(id) {
const item = items.find(item => item.id === id);
if (item) {
showItemModal(item);
}
};
// Show dish modal
function showDishModal(dish = null) {
if (!currentUser) return;
dishForm.reset();
totalCalories.textContent = '0 kcal';
// Load protein items
proteinItems.innerHTML = '';
const proteinItemsList = items.filter(item => item.type === 'protein');
proteinItemsList.forEach(item => {
const itemElement = document.createElement('div');
itemElement.className = 'flex items-center';
itemElement.innerHTML = `
<input type="checkbox" id="item-${item.id}" value="${item.id}" class="item-checkbox h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded dark:bg-gray-700 dark:border-gray-600" data-calories="${item.calories}" data-type="protein">
<label for="item-${item.id}" class="ml-2 block text-sm text-gray-700 dark:text-gray-300">${item.name} (${item.calories} kcal)</label>
`;
proteinItems.appendChild(itemElement);
});
// Load side items
sideItems.innerHTML = '';
const sideItemsList = items.filter(item => item.type === 'side');
sideItemsList.forEach(item => {
const itemElement = document.createElement('div');
itemElement.className = 'flex items-center';
itemElement.innerHTML = `
<input type="checkbox" id="item-${item.id}" value="${item.id}" class="item-checkbox h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded dark:bg-gray-700 dark:border-gray-600" data-calories="${item.calories}" data-type="side">
<label for="item-${item.id}" class="ml-2 block text-sm text-gray-700 dark:text-gray-300">${item.name} (${item.calories} kcal)</label>
`;
sideItems.appendChild(itemElement);
});
// Load dessert items
dessertItems.innerHTML = '';
const dessertItemsList = items.filter(item => item.type === 'dessert');
dessertItemsList.forEach(item => {
const itemElement = document.createElement('div');
itemElement.className = 'flex items-center';
itemElement.innerHTML = `
<input type="checkbox" id="item-${item.id}" value="${item.id}" class="item-checkbox h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded dark:bg-gray-700 dark:border-gray-600" data-calories="${item.calories}" data-type="dessert">
<label for="item-${item.id}" class="ml-2 block text-sm text-gray-700 dark:text-gray-300">${item.name} (${item.calories} kcal)</label>
`;
dessertItems.appendChild(itemElement);
});
if (dish) {
document.getElementById('dishId').value = dish.id;
document.getElementById('dishName').value = dish.name;
document.getElementById('dishDescription').value = dish.description || '';
// Check selected items
dish.items.forEach(itemId => {
const checkbox = document.querySelector(`#item-${itemId}`);
if (checkbox) {
checkbox.checked = true;
}
});
calculateTotalCalories();
document.querySelector('#dishModal h3').textContent = 'Editar Prato';
} else {
document.getElementById('dishId').value = '';
document.querySelector('#dishModal h3').textContent = 'Novo Prato';
}
// Add event listeners to checkboxes
document.querySelectorAll('.item-checkbox').forEach(checkbox => {
checkbox.addEventListener('change', calculateTotalCalories);
});
dishModal.classList.remove('hidden');
}
// Calculate total calories for dish
function calculateTotalCalories() {
let total = 0;
document.querySelectorAll('.item-checkbox:checked').forEach(checkbox => {
total += parseInt(checkbox.getAttribute('data-calories'));
});
totalCalories.textContent = `${total} kcal`;
}
// Save dish
function saveDish() {
const id = document.getElementById('dishId').value;
const name = document.getElementById('dishName').value.trim();
const description = document.getElementById('dishDescription').value.trim();
const selectedItems = [];
document.querySelectorAll('.item-checkbox:checked').forEach(checkbox => {
selectedItems.push(checkbox.value);
});
if (!name || selectedItems.length === 0) return;
// Calculate total calories
let calories = 0;
selectedItems.forEach(itemId => {
const item = items.find(i => i.id === itemId);
if (item) {
calories += item.calories;
}
});
const dishData = {
id: id || Date.now().toString(),
name,
description,
items: selectedItems,
calories
};
if (id) {
// Update existing dish
const index = dishes.findIndex(dish => dish.id === id);
if (index !== -1) {
dishes[index] = dishData;
}
} else {
// Add new dish
dishes.push(dishData);
}
saveUserData();
renderDishes();
dishModal.classList.add('hidden');
}
// Delete dish
function deleteDish(id) {
if (!confirm('Tem certeza que deseja excluir este prato?')) return;
dishes = dishes.filter(dish => dish.id !== id);
saveUserData();
renderDishes();
}
// Render dishes
function renderDishes() {
if (!currentUser) return;
if (dishes.length === 0) {
dishesGrid.innerHTML = '<div class="col-span-full text-center py-8 text-gray-500">Nenhum prato cadastrado</div>';
return;
}
dishesGrid.innerHTML = '';
dishes.forEach(dish => {
const dishCard = document.createElement('div');
dishCard.className = 'rounded-lg overflow-hidden shadow-md transition-all hover:shadow-lg card-light dark:card-dark';
// Get dish items details
const dishItems = [];
dish.items.forEach(itemId => {
const item = items.find(i => i.id === itemId);
if (item) {
dishItems.push(item);
}
});
// Group items by type
const proteins = dishItems.filter(item => item.type === 'protein');
const sides = dishItems.filter(item => item.type === 'side');
const desserts = dishItems.filter(item => item.type === 'dessert');
dishCard.innerHTML = `
<div class="p-4">
<div class="flex justify-between items-start">
<h3 class="text-lg font-semibold dark:text-white">${dish.name}</h3>
<span class="text-sm font-medium dark:text-white">${dish.calories} kcal</span>
</div>
<div class="mt-3">
<p class="text-sm text-gray-600 dark:text-gray-300">${dish.description || 'Sem descrição'}</p>
</div>
<div class="mt-4 space-y-2">
${proteins.length > 0 ? `
<div>
<h4 class="text-sm font-medium dark:text-white">Proteínas</h4>
<ul class="text-xs text-gray-600 dark:text-gray-400 mt-1">
${proteins.map(item => `<li>• ${item.name} (${item.calories} kcal)</li>`).join('')}
</ul>
</div>
` : ''}
${sides.length > 0 ? `
<div>
<h4 class="text-sm font-medium dark:text-white">Acompanhamentos</h4>
<ul class="text-xs text-gray-600 dark:text-gray-400 mt-1">
${sides.map(item => `<li>• ${item.name} (${item.calories} kcal)</li>`).join('')}
</ul>
</div>
` : ''}
${desserts.length > 0 ? `
<div>
<h4 class="text-sm font-medium dark:text-white">Sobremesas</h4>
<ul class="text-xs text-gray-600 dark:text-gray-400 mt-1">
${desserts.map(item => `<li>• ${item.name} (${item.calories} kcal)</li>`).join('')}
</ul>
</div>
` : ''}
</div>
<div class="mt-4 flex justify-end space-x-2">
<button onclick="editDish('${dish.id}')" class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300">
<i class="fas fa-edit"></i>
</button>
<button onclick="deleteDish('${dish.id}')" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
`;
dishesGrid.appendChild(dishCard);
});
}
// Edit dish (global function)
window.editDish = function(id) {
const dish = dishes.find(dish => dish.id === id);
if (dish) {
showDishModal(dish);
}
};
// Generate weekly menu
function generateWeeklyMenu() {
if (!currentUser || dishes.length === 0) return;
const days = ['Segunda-feira', 'Terça-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'Sábado', 'Domingo'];
weeklyMenu = days.map(day => {
// Randomly select dishes for lunch and dinner
const availableDishes = [...dishes];
const lunchDish = availableDishes[Math.floor(Math.random() * availableDishes.length)];
// Remove lunch dish from available dishes for dinner
const dinnerDishes = availableDishes.filter(dish => dish.id !== lunchDish.id);
const dinnerDish = dinnerDishes.length > 0 ?
dinnerDishes[Math.floor(Math.random() * dinnerDishes.length)] :
lunchDish;
return {
day,
lunch: lunchDish.id,
dinner: dinnerDish.id
};
});
currentUser.weeklyMenu = weeklyMenu;
saveUserData();
renderWeeklyMenu();
}
// Render weekly menu
function renderWeeklyMenu() {
if (!currentUser) return;
menuTableBody.innerHTML = '';
if (weeklyMenu.length === 0) {
menuTableBody.innerHTML = `
<tr>
<td colspan="4" class="px-6 py-4 text-center text-gray-500 dark:text-gray-400">
Nenhum cardápio semanal gerado. Clique em "Gerar Cardápio" para criar um.
</td>
</tr>
`;
return;
}
weeklyMenu.forEach((menuDay, index) => {
const lunchDish = dishes.find(dish => dish.id === menuDay.lunch);
const dinnerDish = dishes.find(dish => dish.id === menuDay.dinner);
const row = document.createElement('tr');
row.className = index % 2 === 0 ? 'bg-white dark:bg-gray-800' : 'bg-gray-50 dark:bg-gray-700';
row.innerHTML = `
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium dark:text-white">
${menuDay.day}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-700 dark:text-gray-300">
${lunchDish ? `${lunchDish.name} (${lunchDish.calories} kcal)` : 'N/A'}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-700 dark:text-gray-300">
${dinnerDish ? `${dinnerDish.name} (${dinnerDish.calories} kcal)` : 'N/A'}
</td>
<td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
<button onclick="editMenuDay(${index})" class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300 mr-2">
<i class="fas fa-edit"></i>
</button>
</td>
`;
menuTableBody.appendChild(row);
});
}
// Edit menu day (global function)
window.editMenuDay = function(index) {
if (!currentUser || !weeklyMenu[index]) return;
// Create a modal to edit the menu day
const modal = document.createElement('div');
modal.className = 'fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50';
modal.innerHTML = `
<div class="bg-white dark:bg-gray-800 rounded-lg p-6 w-full max-w-md">
<div class="flex justify-between items-center mb-4">
<h3 class="text-xl font-semibold dark:text-white">Editar ${weeklyMenu[index].day}</h3>
<button id="closeMenuModal" class="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200">
<i class="fas fa-times"></i>
</button>
</div>
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Almoço</label>
<select id="lunchDish" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-white">
${dishes.map(dish => `
<option value="${dish.id}" ${dish.id === weeklyMenu[index].lunch ? 'selected' : ''}>
${dish.name} (${dish.calories} kcal)
</option>
`).join('')}
</select>
</div>
<div class="mb-4">
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Jantar</label>
<select id="dinnerDish" class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-gray-700 dark:text-white">
${dishes.map(dish => `
<option value="${dish.id}" ${dish.id === weeklyMenu[index].dinner ? 'selected' : ''}>
${dish.name} (${dish.calories} kcal)
</option>
`).join('')}
</select>
</div>
<div class="flex justify-end space-x-3">
<button id="cancelMenuEdit" class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700">Cancelar</button>
<button id="saveMenuEdit" class="px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700">Salvar</button>
</div>
</div>
`;
document.body.appendChild(modal);
// Add event listeners
document.getElementById('closeMenuModal').addEventListener('click', () => {
document.body.removeChild(modal);
});
document.getElementById('cancelMenuEdit').addEventListener('click', () => {
document.body.removeChild(modal);
});
document.getElementById('saveMenuEdit').addEventListener('click', () => {
const lunchDish = document.getElementById('lunchDish').value;
const dinnerDish = document.getElementById('dinnerDish').value;
weeklyMenu[index].lunch = lunchDish;
weeklyMenu[index].dinner = dinnerDish;
currentUser.weeklyMenu = weeklyMenu;
saveUserData();
renderWeeklyMenu();
document.body.removeChild(modal);
});
};
// Render report
function renderReport() {
if (!currentUser) return;
// Set date range (current week)
const today = new Date();
const startOfWeek = new Date(today);
startOfWeek.setDate(today.getDate() - today.getDay() + 1); // Monday
const endOfWeek = new Date(startOfWeek);
endOfWeek.setDate(startOfWeek.getDate() + 6); // Sunday
const options = { day: '2-digit', month: '2-digit', year: 'numeric' };
document.getElementById('reportDateRange').textContent =
`Semana de ${startOfWeek.toLocaleDateString('pt-BR', options)} a ${endOfWeek.toLocaleDateString('pt-BR', options)}`;
// Calculate total calories for the week
let weeklyCalories = 0;
if (weeklyMenu.length > 0) {
weeklyMenu.forEach(day => {
const lunchDish = dishes.find(dish => dish.id === day.lunch);
const dinnerDish = dishes.find(dish => dish.id === day.dinner);
if (lunchDish) weeklyCalories += lunchDish.calories;
if (dinnerDish) weeklyCalories += dinnerDish.calories;
});
}
document.getElementById('reportTotalCalories').textContent = `${weeklyCalories} kcal`;
// Render weekly menu
const weeklyMenuReport = document.getElementById('weeklyMenuReport');
weeklyMenuReport.innerHTML = '';
if (weeklyMenu.length === 0) {
weeklyMenuReport.innerHTML = '<p class="text-gray-500 dark:text-gray-400">Nenhum cardápio semanal gerado.</p>';
} else {
weeklyMenu.forEach(day => {
const lunchDish = dishes.find(dish => dish.id === day.lunch);
const dinnerDish = dishes.find(dish => dish.id === day.dinner);
const dayElement = document.createElement('div');
dayElement.className = 'border-b pb-4 dark:border-gray-700';
dayElement.innerHTML = `
<h5 class="font-medium dark:text-white mb-2">${day.day}</h5>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="bg-gray-50 dark:bg-gray-700 p-3 rounded-lg">
<h6 class="font-medium dark:text-white">Almoço</h6>
<p class="text-sm ${lunchDish ? 'text-gray-600 dark:text-gray-300' : 'text-gray-400 dark:text-gray-500'}">
${lunchDish ? `${lunchDish.name} (${lunchDish.calories} kcal)` : 'Nenhum prato selecionado'}
</p>
</div>
<div class="bg-gray-50 dark:bg-gray-700 p-3 rounded-lg">
<h6 class="font-medium dark:text-white">Jantar</h6>
<p class="text-sm ${dinnerDish ? 'text-gray-600 dark:text-gray-300' : 'text-gray-400 dark:text-gray-500'}">
${dinnerDish ? `${dinnerDish.name} (${dinnerDish.calories} kcal)` : 'Nenhum prato selecionado'}
</p>
</div>
</div>
`;
weeklyMenuReport.appendChild(dayElement);
});
}
// Render inventory report
const inventoryReport = document.getElementById('inventoryReport');
inventoryReport.innerHTML = '';
if (items.length === 0) {
inventoryReport.innerHTML = `
<tr>
<td colspan="4" class="px-6 py-4 text-center text-gray-500 dark:text-gray-400">
Nenhum item cadastrado.
</td>
</tr>
`;
} else {
items.forEach(item => {
let typeName = '';
switch (item.type) {
case 'protein': typeName = 'Proteína'; break;
case 'side': typeName = 'Acompanhamento'; break;
case 'dessert': typeName = 'Sobremesa'; break;
}
const status = item.quantity > 0 ?
`<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200">
Disponível
</span>` :
`<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200">
Indisponível
</span>`;
const row = document.createElement('tr');
row.innerHTML = `
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium dark:text-white">
${item.name}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
${typeName}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
${item.quantity}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
${status}
</td>
`;
inventoryReport.appendChild(row);
});
}
}
// Print report
function printReport() {
const printWindow = window.open('', '', 'width=800,height=600');
printWindow.document.write(`
<!DOCTYPE html>
<html>
<head>
<title>Relatório Semanal - MenuMaster</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
h1, h2, h3, h4 { color: #333; }
.header { display: flex; justify-content: space-between; margin-bottom: 20px; }
.menu-day { margin-bottom: 15px; border-bottom: 1px solid #eee; padding-bottom: 10px; }
.menu-meal { margin-bottom: 5px; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
.available { color: green; }
.unavailable { color: red; }
.total-calories { font-size: 1.2em; font-weight: bold; margin: 20px 0; }
</style>
</head>
<body>
<div class="header">
<h1>Relatório Semanal - MenuMaster</h1>
<div>${document.getElementById('reportDateRange').textContent}</div>
</div>
<div class="total-calories">
Total de Calorias: ${document.getElementById('reportTotalCalories').textContent}
</div>
<h2>Cardápio Semanal</h2>
${document.getElementById('weeklyMenuReport').innerHTML}
<h2>Estoque de Ingredientes</h2>
${document.getElementById('inventoryReport').outerHTML}
<script>
window.onload = function() {
window.print();
setTimeout(function() {
window.close();
}, 500);
};
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - <a href="https://enzostvs-deepsite.hf.space?remix=wallaceblaia/receita" style="color: #fff;text-decoration: underline;" target="_blank" >🧬 Remix</a></p></body>
</html>