129 lines
3.9 KiB
JavaScript
129 lines
3.9 KiB
JavaScript
import { RECIPES } from '../data/catalog.js?v=8';
|
|
import { getRecipeGridSectionHTML, renderRecipeGrid } from '../ui/recipeGrid.js';
|
|
import {
|
|
getRecipeSearchFieldHTML,
|
|
syncRecipeSearchShellShadow,
|
|
} from '../ui/recipeSearchField.js';
|
|
|
|
const DEFAULT_MIN_MINUTES = 5;
|
|
const DEFAULT_MAX_MINUTES = 120;
|
|
|
|
let filterState = {
|
|
query: '',
|
|
slots: [],
|
|
tags: [],
|
|
minMinutes: DEFAULT_MIN_MINUTES,
|
|
maxMinutes: DEFAULT_MAX_MINUTES,
|
|
};
|
|
|
|
function matchesFilters(recipe) {
|
|
const { query, slots, tags, minMinutes, maxMinutes } = filterState;
|
|
|
|
if (query) {
|
|
const q = query.toLowerCase();
|
|
const haystack = `${recipe.title} ${(recipe.tags || []).join(' ')}`.toLowerCase();
|
|
if (!haystack.includes(q)) return false;
|
|
}
|
|
|
|
if (slots.length > 0) {
|
|
if (!recipe.allowedSlots.some((s) => slots.includes(s))) return false;
|
|
}
|
|
|
|
if (tags.length > 0) {
|
|
const recipeTags = (recipe.tags || []).map((t) => t.toLowerCase());
|
|
if (!tags.some((t) => recipeTags.includes(t.toLowerCase()))) return false;
|
|
}
|
|
|
|
if (minMinutes > DEFAULT_MIN_MINUTES && recipe.minutes < minMinutes) return false;
|
|
if (maxMinutes < DEFAULT_MAX_MINUTES && recipe.minutes > maxMinutes) return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
function getFilteredRecipes() {
|
|
return Object.values(RECIPES).filter(matchesFilters);
|
|
}
|
|
|
|
function syncRecipeScrollShadow() {
|
|
const searchShell = document.getElementById('recipe-search-shell');
|
|
syncRecipeSearchShellShadow(searchShell);
|
|
}
|
|
|
|
function renderGrid() {
|
|
const grid = document.getElementById('recipe-grid');
|
|
const emptyState = document.getElementById('recipe-empty-state');
|
|
if (!grid) return;
|
|
|
|
renderRecipeGrid({
|
|
gridEl: grid,
|
|
emptyStateEl: emptyState,
|
|
recipes: getFilteredRecipes(),
|
|
});
|
|
requestAnimationFrame(syncRecipeScrollShadow);
|
|
}
|
|
|
|
export function getRecipeListHTML() {
|
|
return `
|
|
<div id="main-view" class="flex flex-col h-full absolute inset-0 bg-[#2d2e2b] z-10" style="background:#2d2e2b !important;">
|
|
<div id="recipe-top-bar" class="pointer-events-none absolute inset-x-0 top-0 z-[12] px-4 pt-4" style="background:transparent !important; border:none !important;">
|
|
<div class="pointer-events-auto">
|
|
${getRecipeSearchFieldHTML({
|
|
shellId: 'recipe-search-shell',
|
|
inputId: 'recipe-search-input',
|
|
placeholder: 'Szukaj przepisów...',
|
|
filterButtonId: 'recipe-filter-btn',
|
|
filterButtonAction: 'openFilters()',
|
|
filterButtonLabel: 'Otwórz filtry',
|
|
})}
|
|
</div>
|
|
</div>
|
|
|
|
${getRecipeGridSectionHTML({
|
|
scrollId: 'recipe-scroll',
|
|
gridId: 'recipe-grid',
|
|
emptyStateId: 'recipe-empty-state',
|
|
scrollClassName: 'relative flex-1 overflow-y-auto px-4 pt-20 pb-24 bg-[#2d2e2b]',
|
|
gridClassName: 'grid grid-cols-2 gap-3 bg-[#2d2e2b]',
|
|
emptyTitle: 'Brak wyników',
|
|
emptyMessage: 'Zmień kryteria wyszukiwania lub filtry',
|
|
})}
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
export function getFilterState() {
|
|
return filterState;
|
|
}
|
|
|
|
export function applyFilters(newState) {
|
|
Object.assign(filterState, newState);
|
|
renderGrid();
|
|
}
|
|
|
|
export function getFilteredCount() {
|
|
return getFilteredRecipes().length;
|
|
}
|
|
|
|
export function refreshRecipeList() {
|
|
renderGrid();
|
|
}
|
|
|
|
export function setupRecipeList() {
|
|
renderGrid();
|
|
|
|
document.getElementById('recipe-search-input')?.addEventListener('input', (e) => {
|
|
filterState.query = e.target.value.trim();
|
|
renderGrid();
|
|
});
|
|
|
|
document.getElementById('recipe-grid')?.addEventListener('click', (e) => {
|
|
const card = e.target.closest('.recipe-browser-card');
|
|
if (!card) return;
|
|
const recipeId = card.getAttribute('data-recipe-id');
|
|
if (recipeId) window.openRecipeDetail?.(recipeId);
|
|
});
|
|
|
|
document.getElementById('recipe-scroll')?.addEventListener('scroll', syncRecipeScrollShadow);
|
|
syncRecipeScrollShadow();
|
|
}
|