wallaceblaia commited on
Commit
f007f40
·
verified ·
1 Parent(s): f67c01d

Add 2 files

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +1320 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Receita
3
- emoji: 🦀
4
- colorFrom: gray
5
- colorTo: green
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: receita
3
+ emoji: 🐳
4
+ colorFrom: yellow
5
+ colorTo: purple
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,1320 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="pt-BR">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>MenuMaster - Gerenciador de Cardápios</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ .dark-mode {
11
+ background-color: #1a202c;
12
+ color: #f7fafc;
13
+ }
14
+ .light-mode {
15
+ background-color: #f7fafc;
16
+ color: #1a202c;
17
+ }
18
+ .card-dark {
19
+ background-color: #2d3748;
20
+ border-color: #4a5568;
21
+ }
22
+ .card-light {
23
+ background-color: #ffffff;
24
+ border-color: #e2e8f0;
25
+ }
26
+ .transition-all {
27
+ transition: all 0.3s ease;
28
+ }
29
+ .max-h-0 {
30
+ max-height: 0;
31
+ overflow: hidden;
32
+ }
33
+ .max-h-screen {
34
+ max-height: 1000px;
35
+ }
36
+ #imagePreview {
37
+ max-width: 200px;
38
+ max-height: 200px;
39
+ }
40
+ </style>
41
+ </head>
42
+ <body class="light-mode min-h-screen">
43
+ <div class="container mx-auto px-4 py-8">
44
+ <!-- Header -->
45
+ <header class="flex justify-between items-center mb-8">
46
+ <h1 class="text-3xl font-bold text-indigo-600 dark:text-indigo-400">
47
+ <i class="fas fa-utensils mr-2"></i>MenuMaster
48
+ </h1>
49
+ <div class="flex items-center space-x-4">
50
+ <div class="relative">
51
+ <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">
52
+ <option value="">Selecione um usuário</option>
53
+ </select>
54
+ </div>
55
+ <button id="themeToggle" class="p-2 rounded-full bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-200">
56
+ <i class="fas fa-moon dark:hidden"></i>
57
+ <i class="fas fa-sun hidden dark:inline"></i>
58
+ </button>
59
+ <button id="newUserBtn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-md">
60
+ <i class="fas fa-user-plus mr-1"></i> Novo Usuário
61
+ </button>
62
+ </div>
63
+ </header>
64
+
65
+ <!-- New User Modal -->
66
+ <div id="newUserModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
67
+ <div class="bg-white dark:bg-gray-800 rounded-lg p-6 w-full max-w-md">
68
+ <div class="flex justify-between items-center mb-4">
69
+ <h3 class="text-xl font-semibold dark:text-white">Novo Usuário</h3>
70
+ <button id="closeUserModal" class="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200">
71
+ <i class="fas fa-times"></i>
72
+ </button>
73
+ </div>
74
+ <div class="mb-4">
75
+ <label for="userName" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Nome do Usuário</label>
76
+ <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">
77
+ </div>
78
+ <div class="flex justify-end space-x-3">
79
+ <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>
80
+ <button id="saveUserBtn" class="px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700">Salvar</button>
81
+ </div>
82
+ </div>
83
+ </div>
84
+
85
+ <!-- Tabs Navigation -->
86
+ <div class="mb-8">
87
+ <div class="flex border-b border-gray-200 dark:border-gray-700">
88
+ <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">
89
+ <i class="fas fa-cube mr-2"></i> Itens do Cardápio
90
+ </button>
91
+ <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">
92
+ <i class="fas fa-utensils mr-2"></i> Pratos
93
+ </button>
94
+ <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">
95
+ <i class="fas fa-calendar-alt mr-2"></i> Cardápio Semanal
96
+ </button>
97
+ <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">
98
+ <i class="fas fa-file-alt mr-2"></i> Relatório
99
+ </button>
100
+ </div>
101
+ </div>
102
+
103
+ <!-- Items Tab Content -->
104
+ <div id="items-tab" class="tab-content">
105
+ <div class="flex justify-between items-center mb-6">
106
+ <h2 class="text-2xl font-semibold dark:text-white">
107
+ <i class="fas fa-cube mr-2"></i> Itens do Cardápio
108
+ </h2>
109
+ <button id="newItemBtn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-md flex items-center">
110
+ <i class="fas fa-plus mr-1"></i> Novo Item
111
+ </button>
112
+ </div>
113
+
114
+ <!-- Item Type Filter -->
115
+ <div class="mb-6 flex space-x-4">
116
+ <button data-filter="all" class="filter-btn px-4 py-2 bg-indigo-600 text-white rounded-md">Todos</button>
117
+ <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>
118
+ <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>
119
+ <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>
120
+ </div>
121
+
122
+ <!-- Items Grid -->
123
+ <div id="itemsGrid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
124
+ <!-- Items will be loaded here -->
125
+ </div>
126
+ </div>
127
+
128
+ <!-- New Item Modal -->
129
+ <div id="itemModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
130
+ <div class="bg-white dark:bg-gray-800 rounded-lg p-6 w-full max-w-md max-h-screen overflow-y-auto">
131
+ <div class="flex justify-between items-center mb-4">
132
+ <h3 class="text-xl font-semibold dark:text-white">Novo Item</h3>
133
+ <button id="closeItemModal" class="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200">
134
+ <i class="fas fa-times"></i>
135
+ </button>
136
+ </div>
137
+ <form id="itemForm">
138
+ <div class="mb-4">
139
+ <label for="itemName" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Nome do Item</label>
140
+ <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">
141
+ </div>
142
+ <div class="mb-4">
143
+ <label for="itemType" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Tipo</label>
144
+ <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">
145
+ <option value="">Selecione...</option>
146
+ <option value="protein">Proteína</option>
147
+ <option value="side">Acompanhamento</option>
148
+ <option value="dessert">Sobremesa</option>
149
+ </select>
150
+ </div>
151
+ <div class="mb-4">
152
+ <label for="itemCalories" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Calorias (kcal)</label>
153
+ <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">
154
+ </div>
155
+ <div class="mb-4">
156
+ <label for="itemQuantity" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Quantidade Disponível</label>
157
+ <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">
158
+ </div>
159
+ <div class="mb-4">
160
+ <label for="itemDescription" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Descrição</label>
161
+ <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>
162
+ </div>
163
+ <div class="mb-4">
164
+ <label for="itemImage" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Imagem</label>
165
+ <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">
166
+ <div class="mt-2">
167
+ <img id="imagePreview" src="#" alt="Preview" class="hidden rounded-md">
168
+ </div>
169
+ </div>
170
+ <input type="hidden" id="itemId">
171
+ <div class="flex justify-end space-x-3">
172
+ <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>
173
+ <button type="submit" id="saveItemBtn" class="px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700">Salvar</button>
174
+ </div>
175
+ </form>
176
+ </div>
177
+ </div>
178
+
179
+ <!-- Dishes Tab Content -->
180
+ <div id="dishes-tab" class="tab-content hidden">
181
+ <div class="flex justify-between items-center mb-6">
182
+ <h2 class="text-2xl font-semibold dark:text-white">
183
+ <i class="fas fa-utensils mr-2"></i> Pratos
184
+ </h2>
185
+ <button id="newDishBtn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-md flex items-center">
186
+ <i class="fas fa-plus mr-1"></i> Novo Prato
187
+ </button>
188
+ </div>
189
+
190
+ <!-- Dishes Grid -->
191
+ <div id="dishesGrid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
192
+ <!-- Dishes will be loaded here -->
193
+ </div>
194
+ </div>
195
+
196
+ <!-- New Dish Modal -->
197
+ <div id="dishModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 hidden">
198
+ <div class="bg-white dark:bg-gray-800 rounded-lg p-6 w-full max-w-2xl max-h-screen overflow-y-auto">
199
+ <div class="flex justify-between items-center mb-4">
200
+ <h3 class="text-xl font-semibold dark:text-white">Novo Prato</h3>
201
+ <button id="closeDishModal" class="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200">
202
+ <i class="fas fa-times"></i>
203
+ </button>
204
+ </div>
205
+ <form id="dishForm">
206
+ <div class="mb-4">
207
+ <label for="dishName" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Nome do Prato</label>
208
+ <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">
209
+ </div>
210
+ <div class="mb-4">
211
+ <label for="dishDescription" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Descrição</label>
212
+ <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>
213
+ </div>
214
+
215
+ <div class="mb-6">
216
+ <h4 class="text-lg font-medium dark:text-white mb-3">Selecione os Itens</h4>
217
+
218
+ <div class="mb-4">
219
+ <h5 class="font-medium dark:text-white mb-2">Proteínas</h5>
220
+ <div id="proteinItems" class="space-y-2">
221
+ <!-- Protein items will be loaded here -->
222
+ </div>
223
+ </div>
224
+
225
+ <div class="mb-4">
226
+ <h5 class="font-medium dark:text-white mb-2">Acompanhamentos</h5>
227
+ <div id="sideItems" class="space-y-2">
228
+ <!-- Side items will be loaded here -->
229
+ </div>
230
+ </div>
231
+
232
+ <div class="mb-4">
233
+ <h5 class="font-medium dark:text-white mb-2">Sobremesas</h5>
234
+ <div id="dessertItems" class="space-y-2">
235
+ <!-- Dessert items will be loaded here -->
236
+ </div>
237
+ </div>
238
+ </div>
239
+
240
+ <div class="mb-4 p-4 rounded-lg bg-indigo-50 dark:bg-indigo-900">
241
+ <h4 class="font-medium dark:text-white mb-2">Resumo Nutricional</h4>
242
+ <div class="flex justify-between">
243
+ <span class="text-gray-700 dark:text-gray-300">Calorias totais:</span>
244
+ <span id="totalCalories" class="font-semibold">0 kcal</span>
245
+ </div>
246
+ </div>
247
+
248
+ <input type="hidden" id="dishId">
249
+ <div class="flex justify-end space-x-3">
250
+ <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>
251
+ <button type="submit" id="saveDishBtn" class="px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700">Salvar</button>
252
+ </div>
253
+ </form>
254
+ </div>
255
+ </div>
256
+
257
+ <!-- Menu Tab Content -->
258
+ <div id="menu-tab" class="tab-content hidden">
259
+ <div class="flex justify-between items-center mb-6">
260
+ <h2 class="text-2xl font-semibold dark:text-white">
261
+ <i class="fas fa-calendar-alt mr-2"></i> Cardápio Semanal
262
+ </h2>
263
+ <button id="generateMenuBtn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-md flex items-center">
264
+ <i class="fas fa-magic mr-1"></i> Gerar Cardápio
265
+ </button>
266
+ </div>
267
+
268
+ <div class="overflow-x-auto">
269
+ <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
270
+ <thead class="bg-gray-50 dark:bg-gray-800">
271
+ <tr>
272
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Dia</th>
273
+ <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>
274
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Jantar</th>
275
+ <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>
276
+ </tr>
277
+ </thead>
278
+ <tbody id="menuTableBody" class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
279
+ <!-- Menu will be loaded here -->
280
+ </tbody>
281
+ </table>
282
+ </div>
283
+ </div>
284
+
285
+ <!-- Report Tab Content -->
286
+ <div id="report-tab" class="tab-content hidden">
287
+ <div class="flex justify-between items-center mb-6">
288
+ <h2 class="text-2xl font-semibold dark:text-white">
289
+ <i class="fas fa-file-alt mr-2"></i> Relatório Semanal
290
+ </h2>
291
+ <button id="printReportBtn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-md flex items-center">
292
+ <i class="fas fa-print mr-1"></i> Imprimir Relatório
293
+ </button>
294
+ </div>
295
+
296
+ <div id="reportContent" class="bg-white dark:bg-gray-800 p-6 rounded-lg shadow">
297
+ <div class="flex justify-between items-center mb-6">
298
+ <div>
299
+ <h3 class="text-xl font-bold dark:text-white">Relatório Semanal</h3>
300
+ <p class="text-gray-600 dark:text-gray-400" id="reportDateRange">Semana de 01/01/2023 a 07/01/2023</p>
301
+ </div>
302
+ <div class="text-right">
303
+ <h4 class="text-lg font-semibold dark:text-white">Total de Calorias</h4>
304
+ <p class="text-2xl font-bold text-indigo-600 dark:text-indigo-400" id="reportTotalCalories">0 kcal</p>
305
+ </div>
306
+ </div>
307
+
308
+ <div class="mb-8">
309
+ <h4 class="text-lg font-semibold border-b pb-2 mb-4 dark:text-white dark:border-gray-700">Cardápio Semanal</h4>
310
+ <div id="weeklyMenuReport" class="space-y-6">
311
+ <!-- Weekly menu report will be loaded here -->
312
+ </div>
313
+ </div>
314
+
315
+ <div>
316
+ <h4 class="text-lg font-semibold border-b pb-2 mb-4 dark:text-white dark:border-gray-700">Estoque de Ingredientes</h4>
317
+ <div class="overflow-x-auto">
318
+ <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
319
+ <thead class="bg-gray-50 dark:bg-gray-700">
320
+ <tr>
321
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Item</th>
322
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Tipo</th>
323
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Quantidade</th>
324
+ <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider">Status</th>
325
+ </tr>
326
+ </thead>
327
+ <tbody id="inventoryReport" class="bg-white dark:bg-gray-800 divide-y divide-gray-200 dark:divide-gray-700">
328
+ <!-- Inventory report will be loaded here -->
329
+ </tbody>
330
+ </table>
331
+ </div>
332
+ </div>
333
+ </div>
334
+ </div>
335
+ </div>
336
+
337
+ <script>
338
+ // Data storage
339
+ let users = JSON.parse(localStorage.getItem('menuMasterUsers')) || [];
340
+ let currentUser = null;
341
+ let items = [];
342
+ let dishes = [];
343
+ let weeklyMenu = [];
344
+
345
+ // DOM Elements
346
+ const themeToggle = document.getElementById('themeToggle');
347
+ const userSelect = document.getElementById('userSelect');
348
+ const newUserBtn = document.getElementById('newUserBtn');
349
+ const newUserModal = document.getElementById('newUserModal');
350
+ const closeUserModal = document.getElementById('closeUserModal');
351
+ const cancelUserBtn = document.getElementById('cancelUserBtn');
352
+ const saveUserBtn = document.getElementById('saveUserBtn');
353
+ const userName = document.getElementById('userName');
354
+
355
+ // Tab elements
356
+ const tabContents = document.querySelectorAll('.tab-content');
357
+ const tabButtons = document.querySelectorAll('.tab-btn');
358
+
359
+ // Item elements
360
+ const newItemBtn = document.getElementById('newItemBtn');
361
+ const itemModal = document.getElementById('itemModal');
362
+ const closeItemModal = document.getElementById('closeItemModal');
363
+ const cancelItemBtn = document.getElementById('cancelItemBtn');
364
+ const saveItemBtn = document.getElementById('saveItemBtn');
365
+ const itemForm = document.getElementById('itemForm');
366
+ const itemsGrid = document.getElementById('itemsGrid');
367
+ const filterButtons = document.querySelectorAll('.filter-btn');
368
+ const itemImage = document.getElementById('itemImage');
369
+ const imagePreview = document.getElementById('imagePreview');
370
+
371
+ // Dish elements
372
+ const newDishBtn = document.getElementById('newDishBtn');
373
+ const dishModal = document.getElementById('dishModal');
374
+ const closeDishModal = document.getElementById('closeDishModal');
375
+ const cancelDishBtn = document.getElementById('cancelDishBtn');
376
+ const saveDishBtn = document.getElementById('saveDishBtn');
377
+ const dishForm = document.getElementById('dishForm');
378
+ const dishesGrid = document.getElementById('dishesGrid');
379
+ const proteinItems = document.getElementById('proteinItems');
380
+ const sideItems = document.getElementById('sideItems');
381
+ const dessertItems = document.getElementById('dessertItems');
382
+ const totalCalories = document.getElementById('totalCalories');
383
+
384
+ // Menu elements
385
+ const generateMenuBtn = document.getElementById('generateMenuBtn');
386
+ const menuTableBody = document.getElementById('menuTableBody');
387
+
388
+ // Report elements
389
+ const printReportBtn = document.getElementById('printReportBtn');
390
+ const reportContent = document.getElementById('reportContent');
391
+
392
+ // Initialize the app
393
+ document.addEventListener('DOMContentLoaded', () => {
394
+ loadUsers();
395
+ setupEventListeners();
396
+ updateUI();
397
+ });
398
+
399
+ // Load users from localStorage
400
+ function loadUsers() {
401
+ userSelect.innerHTML = '<option value="">Selecione um usuário</option>';
402
+ users.forEach(user => {
403
+ const option = document.createElement('option');
404
+ option.value = user.id;
405
+ option.textContent = user.name;
406
+ userSelect.appendChild(option);
407
+ });
408
+ }
409
+
410
+ // Setup event listeners
411
+ function setupEventListeners() {
412
+ // Theme toggle
413
+ themeToggle.addEventListener('click', toggleTheme);
414
+
415
+ // User management
416
+ userSelect.addEventListener('change', (e) => {
417
+ currentUser = users.find(user => user.id === e.target.value) || null;
418
+ if (currentUser) {
419
+ loadUserData();
420
+ }
421
+ updateUI();
422
+ });
423
+
424
+ newUserBtn.addEventListener('click', () => {
425
+ newUserModal.classList.remove('hidden');
426
+ });
427
+
428
+ closeUserModal.addEventListener('click', () => {
429
+ newUserModal.classList.add('hidden');
430
+ });
431
+
432
+ cancelUserBtn.addEventListener('click', () => {
433
+ newUserModal.classList.add('hidden');
434
+ });
435
+
436
+ saveUserBtn.addEventListener('click', addNewUser);
437
+
438
+ // Tab navigation
439
+ tabButtons.forEach(button => {
440
+ button.addEventListener('click', () => {
441
+ const tabId = button.getAttribute('data-tab');
442
+ showTab(tabId);
443
+ });
444
+ });
445
+
446
+ // Item management
447
+ newItemBtn.addEventListener('click', () => {
448
+ showItemModal();
449
+ });
450
+
451
+ closeItemModal.addEventListener('click', () => {
452
+ itemModal.classList.add('hidden');
453
+ });
454
+
455
+ cancelItemBtn.addEventListener('click', () => {
456
+ itemModal.classList.add('hidden');
457
+ });
458
+
459
+ itemForm.addEventListener('submit', (e) => {
460
+ e.preventDefault();
461
+ saveItem();
462
+ });
463
+
464
+ itemImage.addEventListener('change', (e) => {
465
+ const file = e.target.files[0];
466
+ if (file) {
467
+ const reader = new FileReader();
468
+ reader.onload = (event) => {
469
+ imagePreview.src = event.target.result;
470
+ imagePreview.classList.remove('hidden');
471
+ };
472
+ reader.readAsDataURL(file);
473
+ }
474
+ });
475
+
476
+ // Filter buttons
477
+ filterButtons.forEach(button => {
478
+ button.addEventListener('click', () => {
479
+ const filter = button.getAttribute('data-filter');
480
+ filterItems(filter);
481
+ });
482
+ });
483
+
484
+ // Dish management
485
+ newDishBtn.addEventListener('click', () => {
486
+ showDishModal();
487
+ });
488
+
489
+ closeDishModal.addEventListener('click', () => {
490
+ dishModal.classList.add('hidden');
491
+ });
492
+
493
+ cancelDishBtn.addEventListener('click', () => {
494
+ dishModal.classList.add('hidden');
495
+ });
496
+
497
+ dishForm.addEventListener('submit', (e) => {
498
+ e.preventDefault();
499
+ saveDish();
500
+ });
501
+
502
+ // Menu management
503
+ generateMenuBtn.addEventListener('click', generateWeeklyMenu);
504
+
505
+ // Report management
506
+ printReportBtn.addEventListener('click', printReport);
507
+ }
508
+
509
+ // Toggle between dark and light theme
510
+ function toggleTheme() {
511
+ const body = document.body;
512
+ if (body.classList.contains('dark-mode')) {
513
+ body.classList.remove('dark-mode');
514
+ body.classList.add('light-mode');
515
+ } else {
516
+ body.classList.remove('light-mode');
517
+ body.classList.add('dark-mode');
518
+ }
519
+ }
520
+
521
+ // Add new user
522
+ function addNewUser() {
523
+ const name = userName.value.trim();
524
+ if (name === '') return;
525
+
526
+ const newUser = {
527
+ id: Date.now().toString(),
528
+ name: name,
529
+ items: [],
530
+ dishes: [],
531
+ weeklyMenu: []
532
+ };
533
+
534
+ users.push(newUser);
535
+ localStorage.setItem('menuMasterUsers', JSON.stringify(users));
536
+
537
+ userName.value = '';
538
+ newUserModal.classList.add('hidden');
539
+ loadUsers();
540
+
541
+ // Select the new user
542
+ userSelect.value = newUser.id;
543
+ currentUser = newUser;
544
+ updateUI();
545
+ }
546
+
547
+ // Load user data
548
+ function loadUserData() {
549
+ if (!currentUser) return;
550
+
551
+ items = currentUser.items || [];
552
+ dishes = currentUser.dishes || [];
553
+ weeklyMenu = currentUser.weeklyMenu || [];
554
+
555
+ renderItems();
556
+ renderDishes();
557
+ renderWeeklyMenu();
558
+ renderReport();
559
+ }
560
+
561
+ // Save user data
562
+ function saveUserData() {
563
+ if (!currentUser) return;
564
+
565
+ currentUser.items = items;
566
+ currentUser.dishes = dishes;
567
+ currentUser.weeklyMenu = weeklyMenu;
568
+
569
+ localStorage.setItem('menuMasterUsers', JSON.stringify(users));
570
+ }
571
+
572
+ // Update UI based on current state
573
+ function updateUI() {
574
+ const hasUser = currentUser !== null;
575
+
576
+ // Enable/disable tabs based on user selection
577
+ tabButtons.forEach((button, index) => {
578
+ if (index > 0) { // Skip the first tab (items)
579
+ button.disabled = !hasUser;
580
+ }
581
+ });
582
+
583
+ // Enable/disable buttons
584
+ newItemBtn.disabled = !hasUser;
585
+ newDishBtn.disabled = !hasUser;
586
+ generateMenuBtn.disabled = !hasUser;
587
+ printReportBtn.disabled = !hasUser;
588
+
589
+ // Show appropriate content
590
+ if (!hasUser) {
591
+ showTab('items');
592
+ itemsGrid.innerHTML = '<div class="col-span-full text-center py-8 text-gray-500">Selecione um usuário para começar</div>';
593
+ }
594
+ }
595
+
596
+ // Show selected tab
597
+ function showTab(tabId) {
598
+ tabContents.forEach(content => {
599
+ content.classList.add('hidden');
600
+ });
601
+
602
+ tabButtons.forEach(button => {
603
+ button.classList.remove('border-indigo-600', 'text-indigo-600', 'dark:border-indigo-400', 'dark:text-indigo-400');
604
+ });
605
+
606
+ document.getElementById(`${tabId}-tab`).classList.remove('hidden');
607
+ document.querySelector(`[data-tab="${tabId}"]`).classList.add('border-indigo-600', 'text-indigo-600', 'dark:border-indigo-400', 'dark:text-indigo-400');
608
+ }
609
+
610
+ // Show item modal
611
+ function showItemModal(item = null) {
612
+ if (!currentUser) return;
613
+
614
+ itemForm.reset();
615
+ imagePreview.src = '#';
616
+ imagePreview.classList.add('hidden');
617
+
618
+ if (item) {
619
+ document.getElementById('itemId').value = item.id;
620
+ document.getElementById('itemName').value = item.name;
621
+ document.getElementById('itemType').value = item.type;
622
+ document.getElementById('itemCalories').value = item.calories;
623
+ document.getElementById('itemQuantity').value = item.quantity;
624
+ document.getElementById('itemDescription').value = item.description || '';
625
+
626
+ if (item.image) {
627
+ imagePreview.src = item.image;
628
+ imagePreview.classList.remove('hidden');
629
+ }
630
+
631
+ document.querySelector('#itemModal h3').textContent = 'Editar Item';
632
+ } else {
633
+ document.getElementById('itemId').value = '';
634
+ document.querySelector('#itemModal h3').textContent = 'Novo Item';
635
+ }
636
+
637
+ itemModal.classList.remove('hidden');
638
+ }
639
+
640
+ // Save item
641
+ function saveItem() {
642
+ const id = document.getElementById('itemId').value;
643
+ const name = document.getElementById('itemName').value.trim();
644
+ const type = document.getElementById('itemType').value;
645
+ const calories = parseInt(document.getElementById('itemCalories').value);
646
+ const quantity = parseInt(document.getElementById('itemQuantity').value);
647
+ const description = document.getElementById('itemDescription').value.trim();
648
+ const image = imagePreview.src !== '#' ? imagePreview.src : '';
649
+
650
+ if (!name || !type || isNaN(calories) || isNaN(quantity)) return;
651
+
652
+ const itemData = {
653
+ id: id || Date.now().toString(),
654
+ name,
655
+ type,
656
+ calories,
657
+ quantity,
658
+ description,
659
+ image
660
+ };
661
+
662
+ if (id) {
663
+ // Update existing item
664
+ const index = items.findIndex(item => item.id === id);
665
+ if (index !== -1) {
666
+ items[index] = itemData;
667
+ }
668
+ } else {
669
+ // Add new item
670
+ items.push(itemData);
671
+ }
672
+
673
+ saveUserData();
674
+ renderItems();
675
+ itemModal.classList.add('hidden');
676
+ }
677
+
678
+ // Delete item
679
+ function deleteItem(id) {
680
+ if (!confirm('Tem certeza que deseja excluir este item?')) return;
681
+
682
+ items = items.filter(item => item.id !== id);
683
+ saveUserData();
684
+ renderItems();
685
+ }
686
+
687
+ // Filter items by type
688
+ function filterItems(type) {
689
+ filterButtons.forEach(button => {
690
+ if (button.getAttribute('data-filter') === type) {
691
+ button.classList.remove('bg-indigo-100', 'dark:bg-indigo-900', 'text-indigo-800', 'dark:text-indigo-200');
692
+ button.classList.add('bg-indigo-600', 'text-white');
693
+ } else {
694
+ button.classList.remove('bg-indigo-600', 'text-white');
695
+ button.classList.add('bg-indigo-100', 'dark:bg-indigo-900', 'text-indigo-800', 'dark:text-indigo-200');
696
+ }
697
+ });
698
+
699
+ renderItems(type);
700
+ }
701
+
702
+ // Render items
703
+ function renderItems(filter = 'all') {
704
+ if (!currentUser) return;
705
+
706
+ let filteredItems = items;
707
+ if (filter !== 'all') {
708
+ filteredItems = items.filter(item => item.type === filter);
709
+ }
710
+
711
+ if (filteredItems.length === 0) {
712
+ itemsGrid.innerHTML = `<div class="col-span-full text-center py-8 text-gray-500">Nenhum item encontrado</div>`;
713
+ return;
714
+ }
715
+
716
+ itemsGrid.innerHTML = '';
717
+
718
+ filteredItems.forEach(item => {
719
+ const itemCard = document.createElement('div');
720
+ itemCard.className = 'rounded-lg overflow-hidden shadow-md transition-all hover:shadow-lg card-light dark:card-dark';
721
+
722
+ let typeBadge = '';
723
+ let badgeColor = '';
724
+
725
+ switch (item.type) {
726
+ case 'protein':
727
+ typeBadge = 'Proteína';
728
+ badgeColor = 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200';
729
+ break;
730
+ case 'side':
731
+ typeBadge = 'Acompanhamento';
732
+ badgeColor = 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200';
733
+ break;
734
+ case 'dessert':
735
+ typeBadge = 'Sobremesa';
736
+ badgeColor = 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200';
737
+ break;
738
+ }
739
+
740
+ const status = item.quantity > 0 ?
741
+ `<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">
742
+ Disponível (${item.quantity})
743
+ </span>` :
744
+ `<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">
745
+ Indisponível
746
+ </span>`;
747
+
748
+ itemCard.innerHTML = `
749
+ <div class="p-4">
750
+ <div class="flex justify-between items-start">
751
+ <div>
752
+ <h3 class="text-lg font-semibold dark:text-white">${item.name}</h3>
753
+ <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${badgeColor} mt-1">
754
+ ${typeBadge}
755
+ </span>
756
+ </div>
757
+ ${status}
758
+ </div>
759
+ ${item.image ? `
760
+ <div class="mt-3">
761
+ <img src="${item.image}" alt="${item.name}" class="w-full h-32 object-cover rounded-md">
762
+ </div>
763
+ ` : ''}
764
+ <div class="mt-3">
765
+ <p class="text-sm text-gray-600 dark:text-gray-300">${item.description || 'Sem descrição'}</p>
766
+ </div>
767
+ <div class="mt-4 flex justify-between items-center">
768
+ <span class="text-sm font-medium dark:text-white">${item.calories} kcal</span>
769
+ <div class="flex space-x-2">
770
+ <button onclick="editItem('${item.id}')" class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300">
771
+ <i class="fas fa-edit"></i>
772
+ </button>
773
+ <button onclick="deleteItem('${item.id}')" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">
774
+ <i class="fas fa-trash"></i>
775
+ </button>
776
+ </div>
777
+ </div>
778
+ </div>
779
+ `;
780
+
781
+ itemsGrid.appendChild(itemCard);
782
+ });
783
+ }
784
+
785
+ // Edit item (global function)
786
+ window.editItem = function(id) {
787
+ const item = items.find(item => item.id === id);
788
+ if (item) {
789
+ showItemModal(item);
790
+ }
791
+ };
792
+
793
+ // Show dish modal
794
+ function showDishModal(dish = null) {
795
+ if (!currentUser) return;
796
+
797
+ dishForm.reset();
798
+ totalCalories.textContent = '0 kcal';
799
+
800
+ // Load protein items
801
+ proteinItems.innerHTML = '';
802
+ const proteinItemsList = items.filter(item => item.type === 'protein');
803
+ proteinItemsList.forEach(item => {
804
+ const itemElement = document.createElement('div');
805
+ itemElement.className = 'flex items-center';
806
+ itemElement.innerHTML = `
807
+ <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">
808
+ <label for="item-${item.id}" class="ml-2 block text-sm text-gray-700 dark:text-gray-300">${item.name} (${item.calories} kcal)</label>
809
+ `;
810
+ proteinItems.appendChild(itemElement);
811
+ });
812
+
813
+ // Load side items
814
+ sideItems.innerHTML = '';
815
+ const sideItemsList = items.filter(item => item.type === 'side');
816
+ sideItemsList.forEach(item => {
817
+ const itemElement = document.createElement('div');
818
+ itemElement.className = 'flex items-center';
819
+ itemElement.innerHTML = `
820
+ <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">
821
+ <label for="item-${item.id}" class="ml-2 block text-sm text-gray-700 dark:text-gray-300">${item.name} (${item.calories} kcal)</label>
822
+ `;
823
+ sideItems.appendChild(itemElement);
824
+ });
825
+
826
+ // Load dessert items
827
+ dessertItems.innerHTML = '';
828
+ const dessertItemsList = items.filter(item => item.type === 'dessert');
829
+ dessertItemsList.forEach(item => {
830
+ const itemElement = document.createElement('div');
831
+ itemElement.className = 'flex items-center';
832
+ itemElement.innerHTML = `
833
+ <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">
834
+ <label for="item-${item.id}" class="ml-2 block text-sm text-gray-700 dark:text-gray-300">${item.name} (${item.calories} kcal)</label>
835
+ `;
836
+ dessertItems.appendChild(itemElement);
837
+ });
838
+
839
+ if (dish) {
840
+ document.getElementById('dishId').value = dish.id;
841
+ document.getElementById('dishName').value = dish.name;
842
+ document.getElementById('dishDescription').value = dish.description || '';
843
+
844
+ // Check selected items
845
+ dish.items.forEach(itemId => {
846
+ const checkbox = document.querySelector(`#item-${itemId}`);
847
+ if (checkbox) {
848
+ checkbox.checked = true;
849
+ }
850
+ });
851
+
852
+ calculateTotalCalories();
853
+ document.querySelector('#dishModal h3').textContent = 'Editar Prato';
854
+ } else {
855
+ document.getElementById('dishId').value = '';
856
+ document.querySelector('#dishModal h3').textContent = 'Novo Prato';
857
+ }
858
+
859
+ // Add event listeners to checkboxes
860
+ document.querySelectorAll('.item-checkbox').forEach(checkbox => {
861
+ checkbox.addEventListener('change', calculateTotalCalories);
862
+ });
863
+
864
+ dishModal.classList.remove('hidden');
865
+ }
866
+
867
+ // Calculate total calories for dish
868
+ function calculateTotalCalories() {
869
+ let total = 0;
870
+ document.querySelectorAll('.item-checkbox:checked').forEach(checkbox => {
871
+ total += parseInt(checkbox.getAttribute('data-calories'));
872
+ });
873
+ totalCalories.textContent = `${total} kcal`;
874
+ }
875
+
876
+ // Save dish
877
+ function saveDish() {
878
+ const id = document.getElementById('dishId').value;
879
+ const name = document.getElementById('dishName').value.trim();
880
+ const description = document.getElementById('dishDescription').value.trim();
881
+
882
+ const selectedItems = [];
883
+ document.querySelectorAll('.item-checkbox:checked').forEach(checkbox => {
884
+ selectedItems.push(checkbox.value);
885
+ });
886
+
887
+ if (!name || selectedItems.length === 0) return;
888
+
889
+ // Calculate total calories
890
+ let calories = 0;
891
+ selectedItems.forEach(itemId => {
892
+ const item = items.find(i => i.id === itemId);
893
+ if (item) {
894
+ calories += item.calories;
895
+ }
896
+ });
897
+
898
+ const dishData = {
899
+ id: id || Date.now().toString(),
900
+ name,
901
+ description,
902
+ items: selectedItems,
903
+ calories
904
+ };
905
+
906
+ if (id) {
907
+ // Update existing dish
908
+ const index = dishes.findIndex(dish => dish.id === id);
909
+ if (index !== -1) {
910
+ dishes[index] = dishData;
911
+ }
912
+ } else {
913
+ // Add new dish
914
+ dishes.push(dishData);
915
+ }
916
+
917
+ saveUserData();
918
+ renderDishes();
919
+ dishModal.classList.add('hidden');
920
+ }
921
+
922
+ // Delete dish
923
+ function deleteDish(id) {
924
+ if (!confirm('Tem certeza que deseja excluir este prato?')) return;
925
+
926
+ dishes = dishes.filter(dish => dish.id !== id);
927
+ saveUserData();
928
+ renderDishes();
929
+ }
930
+
931
+ // Render dishes
932
+ function renderDishes() {
933
+ if (!currentUser) return;
934
+
935
+ if (dishes.length === 0) {
936
+ dishesGrid.innerHTML = '<div class="col-span-full text-center py-8 text-gray-500">Nenhum prato cadastrado</div>';
937
+ return;
938
+ }
939
+
940
+ dishesGrid.innerHTML = '';
941
+
942
+ dishes.forEach(dish => {
943
+ const dishCard = document.createElement('div');
944
+ dishCard.className = 'rounded-lg overflow-hidden shadow-md transition-all hover:shadow-lg card-light dark:card-dark';
945
+
946
+ // Get dish items details
947
+ const dishItems = [];
948
+ dish.items.forEach(itemId => {
949
+ const item = items.find(i => i.id === itemId);
950
+ if (item) {
951
+ dishItems.push(item);
952
+ }
953
+ });
954
+
955
+ // Group items by type
956
+ const proteins = dishItems.filter(item => item.type === 'protein');
957
+ const sides = dishItems.filter(item => item.type === 'side');
958
+ const desserts = dishItems.filter(item => item.type === 'dessert');
959
+
960
+ dishCard.innerHTML = `
961
+ <div class="p-4">
962
+ <div class="flex justify-between items-start">
963
+ <h3 class="text-lg font-semibold dark:text-white">${dish.name}</h3>
964
+ <span class="text-sm font-medium dark:text-white">${dish.calories} kcal</span>
965
+ </div>
966
+ <div class="mt-3">
967
+ <p class="text-sm text-gray-600 dark:text-gray-300">${dish.description || 'Sem descrição'}</p>
968
+ </div>
969
+ <div class="mt-4 space-y-2">
970
+ ${proteins.length > 0 ? `
971
+ <div>
972
+ <h4 class="text-sm font-medium dark:text-white">Proteínas</h4>
973
+ <ul class="text-xs text-gray-600 dark:text-gray-400 mt-1">
974
+ ${proteins.map(item => `<li>• ${item.name} (${item.calories} kcal)</li>`).join('')}
975
+ </ul>
976
+ </div>
977
+ ` : ''}
978
+ ${sides.length > 0 ? `
979
+ <div>
980
+ <h4 class="text-sm font-medium dark:text-white">Acompanhamentos</h4>
981
+ <ul class="text-xs text-gray-600 dark:text-gray-400 mt-1">
982
+ ${sides.map(item => `<li>• ${item.name} (${item.calories} kcal)</li>`).join('')}
983
+ </ul>
984
+ </div>
985
+ ` : ''}
986
+ ${desserts.length > 0 ? `
987
+ <div>
988
+ <h4 class="text-sm font-medium dark:text-white">Sobremesas</h4>
989
+ <ul class="text-xs text-gray-600 dark:text-gray-400 mt-1">
990
+ ${desserts.map(item => `<li>• ${item.name} (${item.calories} kcal)</li>`).join('')}
991
+ </ul>
992
+ </div>
993
+ ` : ''}
994
+ </div>
995
+ <div class="mt-4 flex justify-end space-x-2">
996
+ <button onclick="editDish('${dish.id}')" class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300">
997
+ <i class="fas fa-edit"></i>
998
+ </button>
999
+ <button onclick="deleteDish('${dish.id}')" class="text-red-600 hover:text-red-900 dark:text-red-400 dark:hover:text-red-300">
1000
+ <i class="fas fa-trash"></i>
1001
+ </button>
1002
+ </div>
1003
+ </div>
1004
+ `;
1005
+
1006
+ dishesGrid.appendChild(dishCard);
1007
+ });
1008
+ }
1009
+
1010
+ // Edit dish (global function)
1011
+ window.editDish = function(id) {
1012
+ const dish = dishes.find(dish => dish.id === id);
1013
+ if (dish) {
1014
+ showDishModal(dish);
1015
+ }
1016
+ };
1017
+
1018
+ // Generate weekly menu
1019
+ function generateWeeklyMenu() {
1020
+ if (!currentUser || dishes.length === 0) return;
1021
+
1022
+ const days = ['Segunda-feira', 'Terça-feira', 'Quarta-feira', 'Quinta-feira', 'Sexta-feira', 'Sábado', 'Domingo'];
1023
+
1024
+ weeklyMenu = days.map(day => {
1025
+ // Randomly select dishes for lunch and dinner
1026
+ const availableDishes = [...dishes];
1027
+ const lunchDish = availableDishes[Math.floor(Math.random() * availableDishes.length)];
1028
+
1029
+ // Remove lunch dish from available dishes for dinner
1030
+ const dinnerDishes = availableDishes.filter(dish => dish.id !== lunchDish.id);
1031
+ const dinnerDish = dinnerDishes.length > 0 ?
1032
+ dinnerDishes[Math.floor(Math.random() * dinnerDishes.length)] :
1033
+ lunchDish;
1034
+
1035
+ return {
1036
+ day,
1037
+ lunch: lunchDish.id,
1038
+ dinner: dinnerDish.id
1039
+ };
1040
+ });
1041
+
1042
+ currentUser.weeklyMenu = weeklyMenu;
1043
+ saveUserData();
1044
+ renderWeeklyMenu();
1045
+ }
1046
+
1047
+ // Render weekly menu
1048
+ function renderWeeklyMenu() {
1049
+ if (!currentUser) return;
1050
+
1051
+ menuTableBody.innerHTML = '';
1052
+
1053
+ if (weeklyMenu.length === 0) {
1054
+ menuTableBody.innerHTML = `
1055
+ <tr>
1056
+ <td colspan="4" class="px-6 py-4 text-center text-gray-500 dark:text-gray-400">
1057
+ Nenhum cardápio semanal gerado. Clique em "Gerar Cardápio" para criar um.
1058
+ </td>
1059
+ </tr>
1060
+ `;
1061
+ return;
1062
+ }
1063
+
1064
+ weeklyMenu.forEach((menuDay, index) => {
1065
+ const lunchDish = dishes.find(dish => dish.id === menuDay.lunch);
1066
+ const dinnerDish = dishes.find(dish => dish.id === menuDay.dinner);
1067
+
1068
+ const row = document.createElement('tr');
1069
+ row.className = index % 2 === 0 ? 'bg-white dark:bg-gray-800' : 'bg-gray-50 dark:bg-gray-700';
1070
+
1071
+ row.innerHTML = `
1072
+ <td class="px-6 py-4 whitespace-nowrap text-sm font-medium dark:text-white">
1073
+ ${menuDay.day}
1074
+ </td>
1075
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-700 dark:text-gray-300">
1076
+ ${lunchDish ? `${lunchDish.name} (${lunchDish.calories} kcal)` : 'N/A'}
1077
+ </td>
1078
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-700 dark:text-gray-300">
1079
+ ${dinnerDish ? `${dinnerDish.name} (${dinnerDish.calories} kcal)` : 'N/A'}
1080
+ </td>
1081
+ <td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
1082
+ <button onclick="editMenuDay(${index})" class="text-indigo-600 hover:text-indigo-900 dark:text-indigo-400 dark:hover:text-indigo-300 mr-2">
1083
+ <i class="fas fa-edit"></i>
1084
+ </button>
1085
+ </td>
1086
+ `;
1087
+
1088
+ menuTableBody.appendChild(row);
1089
+ });
1090
+ }
1091
+
1092
+ // Edit menu day (global function)
1093
+ window.editMenuDay = function(index) {
1094
+ if (!currentUser || !weeklyMenu[index]) return;
1095
+
1096
+ // Create a modal to edit the menu day
1097
+ const modal = document.createElement('div');
1098
+ modal.className = 'fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50';
1099
+ modal.innerHTML = `
1100
+ <div class="bg-white dark:bg-gray-800 rounded-lg p-6 w-full max-w-md">
1101
+ <div class="flex justify-between items-center mb-4">
1102
+ <h3 class="text-xl font-semibold dark:text-white">Editar ${weeklyMenu[index].day}</h3>
1103
+ <button id="closeMenuModal" class="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200">
1104
+ <i class="fas fa-times"></i>
1105
+ </button>
1106
+ </div>
1107
+ <div class="mb-4">
1108
+ <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Almoço</label>
1109
+ <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">
1110
+ ${dishes.map(dish => `
1111
+ <option value="${dish.id}" ${dish.id === weeklyMenu[index].lunch ? 'selected' : ''}>
1112
+ ${dish.name} (${dish.calories} kcal)
1113
+ </option>
1114
+ `).join('')}
1115
+ </select>
1116
+ </div>
1117
+ <div class="mb-4">
1118
+ <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Jantar</label>
1119
+ <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">
1120
+ ${dishes.map(dish => `
1121
+ <option value="${dish.id}" ${dish.id === weeklyMenu[index].dinner ? 'selected' : ''}>
1122
+ ${dish.name} (${dish.calories} kcal)
1123
+ </option>
1124
+ `).join('')}
1125
+ </select>
1126
+ </div>
1127
+ <div class="flex justify-end space-x-3">
1128
+ <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>
1129
+ <button id="saveMenuEdit" class="px-4 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700">Salvar</button>
1130
+ </div>
1131
+ </div>
1132
+ `;
1133
+
1134
+ document.body.appendChild(modal);
1135
+
1136
+ // Add event listeners
1137
+ document.getElementById('closeMenuModal').addEventListener('click', () => {
1138
+ document.body.removeChild(modal);
1139
+ });
1140
+
1141
+ document.getElementById('cancelMenuEdit').addEventListener('click', () => {
1142
+ document.body.removeChild(modal);
1143
+ });
1144
+
1145
+ document.getElementById('saveMenuEdit').addEventListener('click', () => {
1146
+ const lunchDish = document.getElementById('lunchDish').value;
1147
+ const dinnerDish = document.getElementById('dinnerDish').value;
1148
+
1149
+ weeklyMenu[index].lunch = lunchDish;
1150
+ weeklyMenu[index].dinner = dinnerDish;
1151
+
1152
+ currentUser.weeklyMenu = weeklyMenu;
1153
+ saveUserData();
1154
+ renderWeeklyMenu();
1155
+ document.body.removeChild(modal);
1156
+ });
1157
+ };
1158
+
1159
+ // Render report
1160
+ function renderReport() {
1161
+ if (!currentUser) return;
1162
+
1163
+ // Set date range (current week)
1164
+ const today = new Date();
1165
+ const startOfWeek = new Date(today);
1166
+ startOfWeek.setDate(today.getDate() - today.getDay() + 1); // Monday
1167
+ const endOfWeek = new Date(startOfWeek);
1168
+ endOfWeek.setDate(startOfWeek.getDate() + 6); // Sunday
1169
+
1170
+ const options = { day: '2-digit', month: '2-digit', year: 'numeric' };
1171
+ document.getElementById('reportDateRange').textContent =
1172
+ `Semana de ${startOfWeek.toLocaleDateString('pt-BR', options)} a ${endOfWeek.toLocaleDateString('pt-BR', options)}`;
1173
+
1174
+ // Calculate total calories for the week
1175
+ let weeklyCalories = 0;
1176
+ if (weeklyMenu.length > 0) {
1177
+ weeklyMenu.forEach(day => {
1178
+ const lunchDish = dishes.find(dish => dish.id === day.lunch);
1179
+ const dinnerDish = dishes.find(dish => dish.id === day.dinner);
1180
+
1181
+ if (lunchDish) weeklyCalories += lunchDish.calories;
1182
+ if (dinnerDish) weeklyCalories += dinnerDish.calories;
1183
+ });
1184
+ }
1185
+
1186
+ document.getElementById('reportTotalCalories').textContent = `${weeklyCalories} kcal`;
1187
+
1188
+ // Render weekly menu
1189
+ const weeklyMenuReport = document.getElementById('weeklyMenuReport');
1190
+ weeklyMenuReport.innerHTML = '';
1191
+
1192
+ if (weeklyMenu.length === 0) {
1193
+ weeklyMenuReport.innerHTML = '<p class="text-gray-500 dark:text-gray-400">Nenhum cardápio semanal gerado.</p>';
1194
+ } else {
1195
+ weeklyMenu.forEach(day => {
1196
+ const lunchDish = dishes.find(dish => dish.id === day.lunch);
1197
+ const dinnerDish = dishes.find(dish => dish.id === day.dinner);
1198
+
1199
+ const dayElement = document.createElement('div');
1200
+ dayElement.className = 'border-b pb-4 dark:border-gray-700';
1201
+ dayElement.innerHTML = `
1202
+ <h5 class="font-medium dark:text-white mb-2">${day.day}</h5>
1203
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
1204
+ <div class="bg-gray-50 dark:bg-gray-700 p-3 rounded-lg">
1205
+ <h6 class="font-medium dark:text-white">Almoço</h6>
1206
+ <p class="text-sm ${lunchDish ? 'text-gray-600 dark:text-gray-300' : 'text-gray-400 dark:text-gray-500'}">
1207
+ ${lunchDish ? `${lunchDish.name} (${lunchDish.calories} kcal)` : 'Nenhum prato selecionado'}
1208
+ </p>
1209
+ </div>
1210
+ <div class="bg-gray-50 dark:bg-gray-700 p-3 rounded-lg">
1211
+ <h6 class="font-medium dark:text-white">Jantar</h6>
1212
+ <p class="text-sm ${dinnerDish ? 'text-gray-600 dark:text-gray-300' : 'text-gray-400 dark:text-gray-500'}">
1213
+ ${dinnerDish ? `${dinnerDish.name} (${dinnerDish.calories} kcal)` : 'Nenhum prato selecionado'}
1214
+ </p>
1215
+ </div>
1216
+ </div>
1217
+ `;
1218
+
1219
+ weeklyMenuReport.appendChild(dayElement);
1220
+ });
1221
+ }
1222
+
1223
+ // Render inventory report
1224
+ const inventoryReport = document.getElementById('inventoryReport');
1225
+ inventoryReport.innerHTML = '';
1226
+
1227
+ if (items.length === 0) {
1228
+ inventoryReport.innerHTML = `
1229
+ <tr>
1230
+ <td colspan="4" class="px-6 py-4 text-center text-gray-500 dark:text-gray-400">
1231
+ Nenhum item cadastrado.
1232
+ </td>
1233
+ </tr>
1234
+ `;
1235
+ } else {
1236
+ items.forEach(item => {
1237
+ let typeName = '';
1238
+ switch (item.type) {
1239
+ case 'protein': typeName = 'Proteína'; break;
1240
+ case 'side': typeName = 'Acompanhamento'; break;
1241
+ case 'dessert': typeName = 'Sobremesa'; break;
1242
+ }
1243
+
1244
+ const status = item.quantity > 0 ?
1245
+ `<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">
1246
+ Disponível
1247
+ </span>` :
1248
+ `<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">
1249
+ Indisponível
1250
+ </span>`;
1251
+
1252
+ const row = document.createElement('tr');
1253
+ row.innerHTML = `
1254
+ <td class="px-6 py-4 whitespace-nowrap text-sm font-medium dark:text-white">
1255
+ ${item.name}
1256
+ </td>
1257
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
1258
+ ${typeName}
1259
+ </td>
1260
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
1261
+ ${item.quantity}
1262
+ </td>
1263
+ <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-400">
1264
+ ${status}
1265
+ </td>
1266
+ `;
1267
+
1268
+ inventoryReport.appendChild(row);
1269
+ });
1270
+ }
1271
+ }
1272
+
1273
+ // Print report
1274
+ function printReport() {
1275
+ const printWindow = window.open('', '', 'width=800,height=600');
1276
+ printWindow.document.write(`
1277
+ <!DOCTYPE html>
1278
+ <html>
1279
+ <head>
1280
+ <title>Relatório Semanal - MenuMaster</title>
1281
+ <style>
1282
+ body { font-family: Arial, sans-serif; margin: 20px; }
1283
+ h1, h2, h3, h4 { color: #333; }
1284
+ .header { display: flex; justify-content: space-between; margin-bottom: 20px; }
1285
+ .menu-day { margin-bottom: 15px; border-bottom: 1px solid #eee; padding-bottom: 10px; }
1286
+ .menu-meal { margin-bottom: 5px; }
1287
+ table { width: 100%; border-collapse: collapse; margin-top: 20px; }
1288
+ th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
1289
+ th { background-color: #f2f2f2; }
1290
+ .available { color: green; }
1291
+ .unavailable { color: red; }
1292
+ .total-calories { font-size: 1.2em; font-weight: bold; margin: 20px 0; }
1293
+ </style>
1294
+ </head>
1295
+ <body>
1296
+ <div class="header">
1297
+ <h1>Relatório Semanal - MenuMaster</h1>
1298
+ <div>${document.getElementById('reportDateRange').textContent}</div>
1299
+ </div>
1300
+
1301
+ <div class="total-calories">
1302
+ Total de Calorias: ${document.getElementById('reportTotalCalories').textContent}
1303
+ </div>
1304
+
1305
+ <h2>Cardápio Semanal</h2>
1306
+ ${document.getElementById('weeklyMenuReport').innerHTML}
1307
+
1308
+ <h2>Estoque de Ingredientes</h2>
1309
+ ${document.getElementById('inventoryReport').outerHTML}
1310
+
1311
+ <script>
1312
+ window.onload = function() {
1313
+ window.print();
1314
+ setTimeout(function() {
1315
+ window.close();
1316
+ }, 500);
1317
+ };
1318
+ </script>
1319
+ <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>
1320
+ </html>