oyvsar commited on
Commit
356bc81
·
verified ·
1 Parent(s): 2320d44

Add 1 files

Browse files
Files changed (1) hide show
  1. index.html +217 -28
index.html CHANGED
@@ -61,20 +61,20 @@
61
  <div class="text-center mb-8">
62
  <i class="fas fa-utensils text-5xl text-green-500 mb-4"></i>
63
  <h1 class="text-3xl font-bold text-gray-800">Middagsplanlegger</h1>
64
- <p class="text-gray-600 mt-2">Planlegg ukens middager</p>
65
  </div>
66
 
67
  <form id="loginForm" class="space-y-6">
68
  <div>
69
- <label for="password" class="block text-sm font-medium text-gray-700 mb-1">Tilgangskode</label>
70
  <div class="relative">
71
  <input
72
  type="password"
73
- id="password"
74
- name="password"
75
  required
76
  class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-green-500 transition"
77
- placeholder="Skriv inn koden"
78
  >
79
  <button
80
  type="button"
@@ -85,10 +85,21 @@
85
  </button>
86
  </div>
87
  <p id="errorMessage" class="text-red-500 text-sm mt-2 hidden">
88
- Feil kode, prøv igjen
89
  </p>
90
  </div>
91
 
 
 
 
 
 
 
 
 
 
 
 
92
  <button
93
  type="submit"
94
  class="w-full bg-green-500 hover:bg-green-600 text-white font-medium py-3 px-4 rounded-lg transition duration-200 flex items-center justify-center"
@@ -97,7 +108,82 @@
97
  </button>
98
 
99
  <div class="text-center text-sm text-gray-500">
100
- <p>Kontakt administrator for tilgangskode</p>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  </div>
102
  </form>
103
  </div>
@@ -111,6 +197,8 @@
111
  </h1>
112
  <p class="text-gray-600 mt-2">Planlegg ukens middager og vurder rettene</p>
113
  <p id="currentWeek" class="text-sm text-gray-500 mt-1"></p>
 
 
114
  </header>
115
 
116
  <div class="bg-white rounded-xl shadow-lg p-6 mb-8">
@@ -209,14 +297,24 @@
209
 
210
  <script>
211
  document.addEventListener('DOMContentLoaded', function() {
 
212
  const loginForm = document.getElementById('loginForm');
213
- const passwordInput = document.getElementById('password');
 
214
  const togglePassword = document.getElementById('togglePassword');
215
  const errorMessage = document.getElementById('errorMessage');
216
  const loginPage = document.getElementById('loginPage');
 
217
  const appPage = document.getElementById('appPage');
218
  const currentWeekDisplay = document.getElementById('currentWeek');
219
- const correctPassword = '1555'; // Hardcoded password for demo
 
 
 
 
 
 
 
220
 
221
  // Get current week number and year
222
  function getWeekNumber(date) {
@@ -228,10 +326,10 @@
228
  return { week: weekNo, year: d.getFullYear() };
229
  }
230
 
231
- // Get storage key for current week
232
- function getCurrentWeekKey() {
233
  const { week, year } = getWeekNumber(new Date());
234
- return `middagsplanlegger_${year}_${week}`;
235
  }
236
 
237
  // Display current week
@@ -242,26 +340,39 @@
242
 
243
  // Toggle password visibility
244
  togglePassword.addEventListener('click', function() {
245
- const type = passwordInput.getAttribute('type') === 'password' ? 'text' : 'password';
246
- passwordInput.setAttribute('type', type);
247
  this.innerHTML = type === 'password' ? '<i class="fas fa-eye"></i>' : '<i class="fas fa-eye-slash"></i>';
248
  });
249
 
250
- // Form submission
251
  loginForm.addEventListener('submit', function(e) {
252
  e.preventDefault();
253
 
254
- const enteredPassword = passwordInput.value.trim();
 
 
 
 
 
255
 
256
- if (enteredPassword === correctPassword) {
257
- // Successful login - show the app
258
  errorMessage.classList.add('hidden');
259
- passwordInput.classList.remove('border-red-500');
 
 
 
 
260
 
261
  // Hide login and show app
262
  loginPage.classList.add('hidden');
263
  appPage.classList.remove('hidden');
264
 
 
 
 
 
265
  // Display current week
266
  displayCurrentWeek();
267
 
@@ -270,7 +381,7 @@
270
  } else {
271
  // Failed login
272
  errorMessage.classList.remove('hidden');
273
- passwordInput.classList.add('border-red-500');
274
  loginForm.classList.add('shake');
275
 
276
  // Remove shake class after animation completes
@@ -279,13 +390,79 @@
279
  }, 500);
280
 
281
  // Focus and select the password field
282
- passwordInput.focus();
283
- passwordInput.select();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
284
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
285
  });
286
 
287
  // Clear error when typing
288
- passwordInput.addEventListener('input', function() {
289
  errorMessage.classList.add('hidden');
290
  this.classList.remove('border-red-500');
291
  });
@@ -298,7 +475,9 @@
298
 
299
  // Function to save data to localStorage
300
  function saveData() {
301
- const weekKey = getCurrentWeekKey();
 
 
302
  const weekData = {
303
  monday: {
304
  meal: document.getElementById('monday').value,
@@ -361,7 +540,9 @@
361
 
362
  // Function to load saved data from localStorage
363
  function loadSavedData() {
364
- const weekKey = getCurrentWeekKey();
 
 
365
  const savedData = localStorage.getItem(weekKey);
366
  if (savedData) {
367
  const weekData = JSON.parse(savedData);
@@ -382,10 +563,12 @@
382
 
383
  // Function to update the dinners list display
384
  function updateDinnersList() {
 
 
385
  const dinnersList = document.getElementById('dinnersList');
386
  const ratingSummary = document.getElementById('ratingSummary');
387
  const averageRating = document.getElementById('averageRating');
388
- const weekKey = getCurrentWeekKey();
389
  const savedData = localStorage.getItem(weekKey);
390
 
391
  if (!savedData) {
@@ -499,6 +682,8 @@
499
 
500
  // Add rateMeal function to the window object so it can be called from inline onclick
501
  window.rateMeal = function(dayKey) {
 
 
502
  const selectedRating = document.querySelector(`input[name="${dayKey}-rating"]:checked`);
503
  if (!selectedRating) {
504
  alert('Velg en vurdering først!');
@@ -506,7 +691,7 @@
506
  }
507
 
508
  const rating = parseInt(selectedRating.value);
509
- const weekKey = getCurrentWeekKey();
510
  const savedData = localStorage.getItem(weekKey);
511
 
512
  if (savedData) {
@@ -518,7 +703,11 @@
518
  }
519
 
520
  // Add the new rating
521
- weekData[dayKey].ratings.push(rating);
 
 
 
 
522
 
523
  // Save back to localStorage
524
  localStorage.setItem(weekKey, JSON.stringify(weekData));
 
61
  <div class="text-center mb-8">
62
  <i class="fas fa-utensils text-5xl text-green-500 mb-4"></i>
63
  <h1 class="text-3xl font-bold text-gray-800">Middagsplanlegger</h1>
64
+ <p class="text-gray-600 mt-2">Planlegg ukens middager for din familie</p>
65
  </div>
66
 
67
  <form id="loginForm" class="space-y-6">
68
  <div>
69
+ <label for="familyCode" class="block text-sm font-medium text-gray-700 mb-1">Familiekode</label>
70
  <div class="relative">
71
  <input
72
  type="password"
73
+ id="familyCode"
74
+ name="familyCode"
75
  required
76
  class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-green-500 transition"
77
+ placeholder="Skriv inn din familie-kode"
78
  >
79
  <button
80
  type="button"
 
85
  </button>
86
  </div>
87
  <p id="errorMessage" class="text-red-500 text-sm mt-2 hidden">
88
+ Ukjent familie-kode, prøv igjen
89
  </p>
90
  </div>
91
 
92
+ <div>
93
+ <label for="userName" class="block text-sm font-medium text-gray-700 mb-1">Ditt navn (valgfri)</label>
94
+ <input
95
+ type="text"
96
+ id="userName"
97
+ name="userName"
98
+ class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-green-500 transition"
99
+ placeholder="Hva heter du?"
100
+ >
101
+ </div>
102
+
103
  <button
104
  type="submit"
105
  class="w-full bg-green-500 hover:bg-green-600 text-white font-medium py-3 px-4 rounded-lg transition duration-200 flex items-center justify-center"
 
108
  </button>
109
 
110
  <div class="text-center text-sm text-gray-500">
111
+ <p>Familieadministrator kan opprette ny familie-kode</p>
112
+ <button
113
+ type="button"
114
+ id="createFamilyBtn"
115
+ class="mt-2 text-green-600 hover:text-green-800 font-medium"
116
+ >
117
+ Opprett ny familie
118
+ </button>
119
+ </div>
120
+ </form>
121
+ </div>
122
+ </div>
123
+
124
+ <!-- Create Family Page (hidden by default) -->
125
+ <div id="createFamilyPage" class="hidden flex items-center justify-center min-h-screen">
126
+ <div class="bg-white rounded-xl shadow-lg p-8 w-full max-w-md">
127
+ <div class="text-center mb-8">
128
+ <i class="fas fa-users text-5xl text-blue-500 mb-4"></i>
129
+ <h1 class="text-3xl font-bold text-gray-800">Opprett ny familie</h1>
130
+ <p class="text-gray-600 mt-2">Opprett en unik kode for din familie</p>
131
+ </div>
132
+
133
+ <form id="createFamilyForm" class="space-y-6">
134
+ <div>
135
+ <label for="newFamilyName" class="block text-sm font-medium text-gray-700 mb-1">Familienavn</label>
136
+ <input
137
+ type="text"
138
+ id="newFamilyName"
139
+ name="newFamilyName"
140
+ required
141
+ class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition"
142
+ placeholder="F.eks. Andersen-familien"
143
+ >
144
+ </div>
145
+
146
+ <div>
147
+ <label for="newFamilyCode" class="block text-sm font-medium text-gray-700 mb-1">Velg en familie-kode</label>
148
+ <input
149
+ type="password"
150
+ id="newFamilyCode"
151
+ name="newFamilyCode"
152
+ required
153
+ minlength="4"
154
+ maxlength="8"
155
+ class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition"
156
+ placeholder="Velg en 4-8 siffer kode"
157
+ >
158
+ <p class="text-xs text-gray-500 mt-1">Dette er koden alle familiemedlemmer bruker for å logge inn</p>
159
+ </div>
160
+
161
+ <div>
162
+ <label for="adminName" class="block text-sm font-medium text-gray-700 mb-1">Ditt navn (administrator)</label>
163
+ <input
164
+ type="text"
165
+ id="adminName"
166
+ name="adminName"
167
+ required
168
+ class="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition"
169
+ placeholder="Ditt navn"
170
+ >
171
+ </div>
172
+
173
+ <div class="flex gap-4">
174
+ <button
175
+ type="button"
176
+ id="cancelCreateFamily"
177
+ class="flex-1 bg-gray-200 hover:bg-gray-300 text-gray-800 font-medium py-3 px-4 rounded-lg transition duration-200"
178
+ >
179
+ Avbryt
180
+ </button>
181
+ <button
182
+ type="submit"
183
+ class="flex-1 bg-blue-500 hover:bg-blue-600 text-white font-medium py-3 px-4 rounded-lg transition duration-200 flex items-center justify-center"
184
+ >
185
+ <i class="fas fa-users mr-2"></i> Opprett familie
186
+ </button>
187
  </div>
188
  </form>
189
  </div>
 
197
  </h1>
198
  <p class="text-gray-600 mt-2">Planlegg ukens middager og vurder rettene</p>
199
  <p id="currentWeek" class="text-sm text-gray-500 mt-1"></p>
200
+ <p id="familyNameDisplay" class="text-lg font-medium text-blue-600 mt-2"></p>
201
+ <p id="currentUserDisplay" class="text-sm text-gray-500"></p>
202
  </header>
203
 
204
  <div class="bg-white rounded-xl shadow-lg p-6 mb-8">
 
297
 
298
  <script>
299
  document.addEventListener('DOMContentLoaded', function() {
300
+ // DOM elements
301
  const loginForm = document.getElementById('loginForm');
302
+ const createFamilyForm = document.getElementById('createFamilyForm');
303
+ const familyCodeInput = document.getElementById('familyCode');
304
  const togglePassword = document.getElementById('togglePassword');
305
  const errorMessage = document.getElementById('errorMessage');
306
  const loginPage = document.getElementById('loginPage');
307
+ const createFamilyPage = document.getElementById('createFamilyPage');
308
  const appPage = document.getElementById('appPage');
309
  const currentWeekDisplay = document.getElementById('currentWeek');
310
+ const familyNameDisplay = document.getElementById('familyNameDisplay');
311
+ const currentUserDisplay = document.getElementById('currentUserDisplay');
312
+ const createFamilyBtn = document.getElementById('createFamilyBtn');
313
+ const cancelCreateFamily = document.getElementById('cancelCreateFamily');
314
+
315
+ // Current family data
316
+ let currentFamily = null;
317
+ let currentUser = null;
318
 
319
  // Get current week number and year
320
  function getWeekNumber(date) {
 
326
  return { week: weekNo, year: d.getFullYear() };
327
  }
328
 
329
+ // Get storage key for current week and family
330
+ function getCurrentWeekKey(familyCode) {
331
  const { week, year } = getWeekNumber(new Date());
332
+ return `middagsplanlegger_${familyCode}_${year}_${week}`;
333
  }
334
 
335
  // Display current week
 
340
 
341
  // Toggle password visibility
342
  togglePassword.addEventListener('click', function() {
343
+ const type = familyCodeInput.getAttribute('type') === 'password' ? 'text' : 'password';
344
+ familyCodeInput.setAttribute('type', type);
345
  this.innerHTML = type === 'password' ? '<i class="fas fa-eye"></i>' : '<i class="fas fa-eye-slash"></i>';
346
  });
347
 
348
+ // Form submission - Login
349
  loginForm.addEventListener('submit', function(e) {
350
  e.preventDefault();
351
 
352
+ const enteredCode = familyCodeInput.value.trim();
353
+ const userName = document.getElementById('userName').value.trim() || 'Familiemedlem';
354
+
355
+ // Check if family exists
356
+ const families = JSON.parse(localStorage.getItem('middagsplanlegger_families') || '[]');
357
+ const family = families.find(f => f.code === enteredCode);
358
 
359
+ if (family) {
360
+ // Successful login
361
  errorMessage.classList.add('hidden');
362
+ familyCodeInput.classList.remove('border-red-500');
363
+
364
+ // Set current family and user
365
+ currentFamily = family;
366
+ currentUser = userName;
367
 
368
  // Hide login and show app
369
  loginPage.classList.add('hidden');
370
  appPage.classList.remove('hidden');
371
 
372
+ // Display family info
373
+ familyNameDisplay.textContent = family.name;
374
+ currentUserDisplay.textContent = `Logget inn som: ${userName}`;
375
+
376
  // Display current week
377
  displayCurrentWeek();
378
 
 
381
  } else {
382
  // Failed login
383
  errorMessage.classList.remove('hidden');
384
+ familyCodeInput.classList.add('border-red-500');
385
  loginForm.classList.add('shake');
386
 
387
  // Remove shake class after animation completes
 
390
  }, 500);
391
 
392
  // Focus and select the password field
393
+ familyCodeInput.focus();
394
+ familyCodeInput.select();
395
+ }
396
+ });
397
+
398
+ // Create new family button
399
+ createFamilyBtn.addEventListener('click', function() {
400
+ loginPage.classList.add('hidden');
401
+ createFamilyPage.classList.remove('hidden');
402
+ });
403
+
404
+ // Cancel create family
405
+ cancelCreateFamily.addEventListener('click', function() {
406
+ createFamilyPage.classList.add('hidden');
407
+ loginPage.classList.remove('hidden');
408
+ });
409
+
410
+ // Form submission - Create new family
411
+ createFamilyForm.addEventListener('submit', function(e) {
412
+ e.preventDefault();
413
+
414
+ const familyName = document.getElementById('newFamilyName').value.trim();
415
+ const familyCode = document.getElementById('newFamilyCode').value.trim();
416
+ const adminName = document.getElementById('adminName').value.trim();
417
+
418
+ // Validate code length
419
+ if (familyCode.length < 4 || familyCode.length > 8) {
420
+ alert('Familie-koden må være mellom 4 og 8 tegn');
421
+ return;
422
+ }
423
+
424
+ // Check if code is already taken
425
+ const families = JSON.parse(localStorage.getItem('middagsplanlegger_families') || '[]');
426
+ const codeExists = families.some(f => f.code === familyCode);
427
+
428
+ if (codeExists) {
429
+ alert('Denne koden er allerede i bruk. Vennligst velg en annen.');
430
+ return;
431
  }
432
+
433
+ // Create new family
434
+ const newFamily = {
435
+ name: familyName,
436
+ code: familyCode,
437
+ created: new Date().toISOString(),
438
+ admin: adminName
439
+ };
440
+
441
+ // Save to localStorage
442
+ families.push(newFamily);
443
+ localStorage.setItem('middagsplanlegger_families', JSON.stringify(families));
444
+
445
+ // Set as current family
446
+ currentFamily = newFamily;
447
+ currentUser = adminName;
448
+
449
+ // Show the app
450
+ createFamilyPage.classList.add('hidden');
451
+ appPage.classList.remove('hidden');
452
+
453
+ // Display family info
454
+ familyNameDisplay.textContent = familyName;
455
+ currentUserDisplay.textContent = `Logget inn som: ${adminName} (Administrator)`;
456
+
457
+ // Display current week
458
+ displayCurrentWeek();
459
+
460
+ // Clear form
461
+ this.reset();
462
  });
463
 
464
  // Clear error when typing
465
+ familyCodeInput.addEventListener('input', function() {
466
  errorMessage.classList.add('hidden');
467
  this.classList.remove('border-red-500');
468
  });
 
475
 
476
  // Function to save data to localStorage
477
  function saveData() {
478
+ if (!currentFamily) return;
479
+
480
+ const weekKey = getCurrentWeekKey(currentFamily.code);
481
  const weekData = {
482
  monday: {
483
  meal: document.getElementById('monday').value,
 
540
 
541
  // Function to load saved data from localStorage
542
  function loadSavedData() {
543
+ if (!currentFamily) return;
544
+
545
+ const weekKey = getCurrentWeekKey(currentFamily.code);
546
  const savedData = localStorage.getItem(weekKey);
547
  if (savedData) {
548
  const weekData = JSON.parse(savedData);
 
563
 
564
  // Function to update the dinners list display
565
  function updateDinnersList() {
566
+ if (!currentFamily) return;
567
+
568
  const dinnersList = document.getElementById('dinnersList');
569
  const ratingSummary = document.getElementById('ratingSummary');
570
  const averageRating = document.getElementById('averageRating');
571
+ const weekKey = getCurrentWeekKey(currentFamily.code);
572
  const savedData = localStorage.getItem(weekKey);
573
 
574
  if (!savedData) {
 
682
 
683
  // Add rateMeal function to the window object so it can be called from inline onclick
684
  window.rateMeal = function(dayKey) {
685
+ if (!currentFamily) return;
686
+
687
  const selectedRating = document.querySelector(`input[name="${dayKey}-rating"]:checked`);
688
  if (!selectedRating) {
689
  alert('Velg en vurdering først!');
 
691
  }
692
 
693
  const rating = parseInt(selectedRating.value);
694
+ const weekKey = getCurrentWeekKey(currentFamily.code);
695
  const savedData = localStorage.getItem(weekKey);
696
 
697
  if (savedData) {
 
703
  }
704
 
705
  // Add the new rating
706
+ weekData[dayKey].ratings.push({
707
+ value: rating,
708
+ user: currentUser || 'Anonym',
709
+ timestamp: new Date().toISOString()
710
+ });
711
 
712
  // Save back to localStorage
713
  localStorage.setItem(weekKey, JSON.stringify(weekData));