mirror of
https://github.com/shadoll/sLogos.git
synced 2026-02-04 11:03:24 +00:00
feat: Enhance filtering capabilities by adding support for variants in Filter, Header, and Home components
This commit is contained in:
@@ -3,18 +3,21 @@
|
||||
export let allTags = [];
|
||||
export let selectedTags = [];
|
||||
export let selectedBrands = [];
|
||||
export let selectedVariants = [];
|
||||
export let tagDropdownOpen = false;
|
||||
export let toggleDropdown = () => console.log("toggleDropdown not provided");
|
||||
export let addTag = () => console.log("addTag not provided");
|
||||
export let removeTag = () => console.log("removeTag not provided");
|
||||
export let addBrand = () => console.log("addBrand not provided");
|
||||
export let removeBrand = () => console.log("removeBrand not provided");
|
||||
export let addVariant = () => console.log("addVariant not provided");
|
||||
export let removeVariant = () => console.log("removeVariant not provided");
|
||||
export let getTagObj = (tag) => ({ text: tag });
|
||||
export let compactMode = false;
|
||||
export let setCompactMode = () => {};
|
||||
|
||||
let tagSearchQuery = ""; // Search query for filtering tags
|
||||
let activeTab = "categories"; // "categories" or "brands"
|
||||
let activeTab = "categories"; // "categories", "brands", or "variants"
|
||||
|
||||
// Filter available tags based on search query
|
||||
$: filteredAvailableTags = allTags.filter(
|
||||
@@ -37,11 +40,26 @@
|
||||
)
|
||||
).sort();
|
||||
|
||||
// Compute all unique variants
|
||||
$: allVariants = Array.from(
|
||||
new Set(
|
||||
allLogos
|
||||
.filter((logo) => logo.variants && Array.isArray(logo.variants))
|
||||
.flatMap((logo) => logo.variants)
|
||||
.filter((variant) => variant && variant.trim() !== "")
|
||||
)
|
||||
).sort();
|
||||
|
||||
// Filter brands based on search query
|
||||
$: filteredAllBrands = allBrands.filter((brand) =>
|
||||
brand.toLowerCase().includes(tagSearchQuery.toLowerCase())
|
||||
);
|
||||
|
||||
// Filter variants based on search query
|
||||
$: filteredAllVariants = allVariants.filter((variant) =>
|
||||
variant.toLowerCase().includes(tagSearchQuery.toLowerCase())
|
||||
);
|
||||
|
||||
function toggleBrand(brand) {
|
||||
if (selectedBrands.includes(brand)) {
|
||||
selectedBrands = selectedBrands.filter(b => b !== brand);
|
||||
@@ -56,6 +74,17 @@
|
||||
updateFilterParams();
|
||||
}
|
||||
|
||||
function toggleVariant(variant) {
|
||||
if (selectedVariants.includes(variant)) {
|
||||
removeVariant(variant);
|
||||
} else {
|
||||
addVariant(variant);
|
||||
}
|
||||
|
||||
// Update URL parameters
|
||||
updateFilterParams();
|
||||
}
|
||||
|
||||
function updateFilterParams() {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
|
||||
@@ -73,6 +102,13 @@
|
||||
params.delete("brands");
|
||||
}
|
||||
|
||||
// Update variants
|
||||
if (selectedVariants.length > 0) {
|
||||
params.set("variants", selectedVariants.join(","));
|
||||
} else {
|
||||
params.delete("variants");
|
||||
}
|
||||
|
||||
const newUrl = window.location.pathname + (params.toString() ? "?" + params.toString() : "");
|
||||
history.replaceState(null, "", newUrl);
|
||||
}
|
||||
@@ -98,9 +134,9 @@
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
{#if selectedTags.length + selectedBrands.length + (compactMode ? 1 : 0) > 0}
|
||||
{#if selectedTags.length + selectedBrands.length + selectedVariants.length + (compactMode ? 1 : 0) > 0}
|
||||
<span class="filter-count"
|
||||
>{selectedTags.length + selectedBrands.length + (compactMode ? 1 : 0)}</span
|
||||
>{selectedTags.length + selectedBrands.length + selectedVariants.length + (compactMode ? 1 : 0)}</span
|
||||
>
|
||||
{/if}
|
||||
</button>
|
||||
@@ -138,7 +174,7 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{#if filteredAvailableTags.length > 0 || tagSearchQuery || allBrands.length > 0}
|
||||
{#if filteredAvailableTags.length > 0 || tagSearchQuery || allBrands.length > 0 || allVariants.length > 0}
|
||||
<div class="filter-separator"></div>
|
||||
<div class="filter-tabs-section">
|
||||
<div class="filter-tabs">
|
||||
@@ -156,12 +192,19 @@
|
||||
>
|
||||
Brands
|
||||
</button>
|
||||
<button
|
||||
class="filter-tab"
|
||||
class:active={activeTab === "variants"}
|
||||
on:click={() => activeTab = "variants"}
|
||||
>
|
||||
Variants
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="tags-search-bar">
|
||||
<input
|
||||
type="text"
|
||||
placeholder={activeTab === "categories" ? "Search categories..." : "Search brands..."}
|
||||
placeholder={activeTab === "categories" ? "Search categories..." : activeTab === "brands" ? "Search brands..." : "Search variants..."}
|
||||
bind:value={tagSearchQuery}
|
||||
class="tags-search-input"
|
||||
/>
|
||||
@@ -234,7 +277,7 @@
|
||||
: "No available categories"}
|
||||
</div>
|
||||
{/if}
|
||||
{:else}
|
||||
{:else if activeTab === "brands"}
|
||||
{#if filteredAllBrands.length > 0}
|
||||
<div class="filter-tags-list">
|
||||
{#each filteredAllBrands as brand}
|
||||
@@ -275,11 +318,49 @@
|
||||
: "No available brands"}
|
||||
</div>
|
||||
{/if}
|
||||
{:else if activeTab === "variants"}
|
||||
{#if filteredAllVariants.length > 0}
|
||||
<div class="filter-tags-list">
|
||||
{#each filteredAllVariants as variant}
|
||||
{@const isSelected = selectedVariants.includes(variant)}
|
||||
<button
|
||||
class="filter-tag-item filter-variant-item"
|
||||
class:selected={isSelected}
|
||||
on:click={() => toggleVariant(variant)}
|
||||
aria-label={isSelected
|
||||
? `Remove variant: ${variant}`
|
||||
: `Add variant: ${variant}`}
|
||||
>
|
||||
<span class="tag-icon">
|
||||
<span class="permanent-icon">
|
||||
{#if isSelected}
|
||||
✔︎
|
||||
{/if}
|
||||
</span>
|
||||
<span class="hover-icon">
|
||||
{#if isSelected}
|
||||
✕
|
||||
{:else}
|
||||
✔︎
|
||||
{/if}
|
||||
</span>
|
||||
</span>
|
||||
<span class="variant-text">{variant}</span>
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="no-tags">
|
||||
{tagSearchQuery
|
||||
? "No variants match your search"
|
||||
: "No available variants"}
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if selectedTags.length > 0 || selectedBrands.length > 0 || compactMode}
|
||||
{#if selectedTags.length > 0 || selectedBrands.length > 0 || selectedVariants.length > 0 || compactMode}
|
||||
<div class="filter-separator"></div>
|
||||
<div class="clear-all-section">
|
||||
<button
|
||||
@@ -287,6 +368,7 @@
|
||||
on:click={() => {
|
||||
selectedTags.forEach(tag => removeTag(tag));
|
||||
selectedBrands.forEach(brand => removeBrand(brand));
|
||||
[...selectedVariants].forEach(variant => removeVariant(variant));
|
||||
if (compactMode) {
|
||||
setCompactMode(false);
|
||||
compactMode = false;
|
||||
@@ -326,6 +408,17 @@
|
||||
</button>
|
||||
{/each}
|
||||
|
||||
{#each selectedVariants as variant}
|
||||
<button
|
||||
class="selected-filter-btn selected-variant"
|
||||
aria-label={`Remove variant: ${variant}`}
|
||||
on:click={() => removeVariant(variant)}
|
||||
>
|
||||
{variant}
|
||||
<span class="close">×</span>
|
||||
</button>
|
||||
{/each}
|
||||
|
||||
{#if compactMode}
|
||||
<button
|
||||
class="selected-filter-btn compact-indicator"
|
||||
@@ -438,6 +531,15 @@
|
||||
background: var(--additional-color);
|
||||
}
|
||||
|
||||
.selected-variant {
|
||||
background: #9b59b6;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.selected-variant:hover {
|
||||
background: #8e44ad;
|
||||
}
|
||||
|
||||
.compact-indicator {
|
||||
background: var(--color-border);
|
||||
color: var(--color-text);
|
||||
@@ -648,6 +750,15 @@
|
||||
background: var(--color-border);
|
||||
}
|
||||
|
||||
.filter-variant-item.selected {
|
||||
background: none;
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
.filter-variant-item.selected:hover {
|
||||
background: var(--color-border);
|
||||
}
|
||||
|
||||
.tag-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
@@ -691,6 +802,11 @@
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.variant-text {
|
||||
font-size: 0.85em;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.no-tags {
|
||||
color: #888;
|
||||
font-size: 0.85em;
|
||||
|
||||
@@ -18,12 +18,15 @@
|
||||
export let allTags = [];
|
||||
export let selectedTags = [];
|
||||
export let selectedBrands = [];
|
||||
export let selectedVariants = [];
|
||||
export let tagDropdownOpen = false;
|
||||
export let toggleDropdown = () => console.log("toggleDropdown not provided");
|
||||
export let addTag = () => console.log("addTag not provided");
|
||||
export let removeTag = () => console.log("removeTag not provided");
|
||||
export let addBrand = () => console.log("addBrand not provided");
|
||||
export let removeBrand = () => console.log("removeBrand not provided");
|
||||
export let addVariant = () => console.log("addVariant not provided");
|
||||
export let removeVariant = () => console.log("removeVariant not provided");
|
||||
export let getTagObj = (tag) => ({ text: tag });
|
||||
export let compactMode = false;
|
||||
export let setCompactMode = () => {};
|
||||
@@ -38,7 +41,7 @@
|
||||
<h1>Logo Gallery</h1>
|
||||
</div>
|
||||
<span class="logo-count">
|
||||
{#if (searchQuery && searchQuery.trim() !== "") || selectedTags.length > 0 || selectedBrands.length > 0 || compactMode}
|
||||
{#if (searchQuery && searchQuery.trim() !== "") || selectedTags.length > 0 || selectedBrands.length > 0 || selectedVariants.length > 0 || compactMode}
|
||||
{displayLogos ? displayLogos.length : 0} of {allLogos ? allLogos.length : 0} images
|
||||
displayed
|
||||
{:else}
|
||||
@@ -55,12 +58,15 @@
|
||||
{allTags}
|
||||
{selectedTags}
|
||||
{selectedBrands}
|
||||
{selectedVariants}
|
||||
{tagDropdownOpen}
|
||||
{toggleDropdown}
|
||||
{addTag}
|
||||
{removeTag}
|
||||
{addBrand}
|
||||
{removeBrand}
|
||||
{addVariant}
|
||||
{removeVariant}
|
||||
{getTagObj}
|
||||
{compactMode}
|
||||
{setCompactMode}
|
||||
|
||||
Reference in New Issue
Block a user