diff --git a/index.html b/index.html index 8a075ee..544cab0 100644 --- a/index.html +++ b/index.html @@ -1,5 +1,5 @@ - +
diff --git a/js/app.js b/js/app.js index 0ce03e6..d7a3d52 100644 --- a/js/app.js +++ b/js/app.js @@ -1,18 +1,77 @@ import { getRecipeListHTML } from './views/RecipeList.js'; import { getFilterHTML, setupFilter } from './views/Filter.js'; import { getRecipeDetailHTML, setupRecipeDetail } from './views/RecipeDetail.js'; +import { getMealPlannerHTML, setupMealPlanner } from './views/MealPlanner.js'; + +function getBottomNavHTML() { + return ` + + `; +} + +function setupTabs() { + const main = document.getElementById('main-view'); + const planner = document.getElementById('planner-view'); + const nav = document.getElementById('app-bottom-nav'); + if (!main || !planner || !nav) return; + + const activeTab = 'nav-tab flex flex-col items-center gap-1 text-black min-w-[3.5rem]'; + const idleTab = 'nav-tab flex flex-col items-center gap-1 text-gray-500 hover:text-gray-700 min-w-[3.5rem]'; + + const apply = (tab) => { + const showRecipes = tab === 'recipes'; + main.classList.toggle('hidden', !showRecipes); + planner.classList.toggle('hidden', showRecipes); + + nav.querySelectorAll('.nav-tab[data-tab]').forEach((btn) => { + const id = btn.getAttribute('data-tab'); + if (btn.hasAttribute('disabled')) return; + if (id === 'recipes' || id === 'planner') { + btn.className = id === tab ? activeTab : idleTab; + } + }); + }; + + nav.addEventListener('click', (e) => { + const btn = e.target.closest('.nav-tab[data-tab]'); + if (!btn || btn.hasAttribute('disabled')) return; + const tab = btn.getAttribute('data-tab'); + if (tab === 'recipes' || tab === 'planner') apply(tab); + }); + + apply('recipes'); +} document.addEventListener('DOMContentLoaded', () => { const appContainer = document.getElementById('app-container'); - // Inject all views into the main container appContainer.innerHTML = ` ${getRecipeListHTML()} + ${getMealPlannerHTML()} + ${getBottomNavHTML()} ${getRecipeDetailHTML()} ${getFilterHTML()} `; - // Initialize logic for the injected views + setupTabs(); + setupMealPlanner(); setupFilter(); setupRecipeDetail(); }); diff --git a/js/views/MealPlanner.js b/js/views/MealPlanner.js new file mode 100644 index 0000000..96ea896 --- /dev/null +++ b/js/views/MealPlanner.js @@ -0,0 +1,307 @@ +const MONTHS_SHORT = [ + 'sty', 'lut', 'mar', 'kwi', 'maj', 'cze', + 'lip', 'sie', 'wrz', 'paź', 'lis', 'gru', +]; +const WEEKDAYS_SHORT = ['pn', 'wt', 'śr', 'cz', 'pt', 'so', 'nd']; + +function startOfDay(d) { + const x = new Date(d); + x.setHours(0, 0, 0, 0); + return x; +} + +function sameDay(a, b) { + return a.getFullYear() === b.getFullYear() + && a.getMonth() === b.getMonth() + && a.getDate() === b.getDate(); +} + +function addDays(d, n) { + const x = new Date(d); + x.setDate(x.getDate() + n); + return startOfDay(x); +} + +/** Poniedziałek jako pierwszy dzień tygodnia (PL) */ +function startOfWeekMonday(d) { + const date = startOfDay(d); + const day = date.getDay(); + const diff = day === 0 ? -6 : 1 - day; + return addDays(date, diff); +} + +function startOfMonth(d) { + const x = new Date(d.getFullYear(), d.getMonth(), 1); + return startOfDay(x); +} + +function addMonths(d, n) { + const x = new Date(d); + x.setMonth(x.getMonth() + n); + return startOfDay(x); +} + +function addWeeks(d, n) { + return addDays(d, n * 7); +} + +function weekContains(weekStart, d) { + const t = startOfDay(d).getTime(); + const ws = weekStart.getTime(); + const we = addDays(weekStart, 6).getTime(); + return t >= ws && t <= we; +} + +function sameMonth(a, b) { + return a.getMonth() === b.getMonth() && a.getFullYear() === b.getFullYear(); +} + +function isCalendarOnToday(mode, weekStart, monthAnchor, selected) { + const today = startOfDay(new Date()); + if (!sameDay(selected, today)) return false; + if (mode === 'week') return weekContains(weekStart, today); + return sameMonth(monthAnchor, today); +} + +function syncTodayButton(mode, weekStart, monthAnchor, selected) { + const btn = document.getElementById('cal-go-today'); + if (!btn) return; + const onToday = isCalendarOnToday(mode, weekStart, monthAnchor, selected); + const active = 'h-6 shrink-0 inline-flex items-center justify-center gap-1 rounded-md border border-gray-200 bg-white px-2 text-[10px] font-semibold text-gray-700 shadow-sm hover:bg-gray-50 hover:text-gray-900 transition-colors'; + const dim = 'h-6 shrink-0 inline-flex items-center justify-center gap-1 rounded-md border border-gray-100 bg-gray-50 px-2 text-[10px] font-semibold text-gray-400 shadow-none cursor-default transition-colors'; + btn.className = onToday ? dim : active; + btn.disabled = onToday; +} + +export function getMealPlannerHTML() { + return ` +Dotknij dnia w kalendarzu, aby później przypisać posiłki. Ta sekcja na razie jest zapowiedzią rozbudowy planera.
+