feat(CategoryFilter): create CategoryFilter component
This commit is contained in:
@@ -1,17 +1,37 @@
|
|||||||
|
import type { FilterModel } from '$shared/store/createFilterStore';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model of state for CategoryFilter
|
* Model of state for CategoryFilter
|
||||||
*/
|
*/
|
||||||
export interface CategoryFilterStateModel {
|
export type CategoryFilterModel = FilterModel;
|
||||||
/**
|
|
||||||
* Search query
|
export const FONT_CATEGORIES = [
|
||||||
*/
|
{
|
||||||
searchQuery?: string;
|
id: 'serif',
|
||||||
/**
|
name: 'Serif',
|
||||||
* Categories
|
},
|
||||||
*/
|
{
|
||||||
categories: string[];
|
id: 'sans-serif',
|
||||||
/**
|
name: 'Sans-serif',
|
||||||
* Selected categories
|
},
|
||||||
*/
|
{
|
||||||
selectedCategories: string[];
|
id: 'display',
|
||||||
}
|
name: 'Display',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'handwriting',
|
||||||
|
name: 'Handwriting',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'monospace',
|
||||||
|
name: 'Monospace',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'script',
|
||||||
|
name: 'Script',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'slab',
|
||||||
|
name: 'Slab',
|
||||||
|
},
|
||||||
|
] as const;
|
||||||
|
|||||||
@@ -1,35 +1,16 @@
|
|||||||
import { writable } from 'svelte/store';
|
import { FONT_CATEGORIES } from '$entities/Font/model/font';
|
||||||
import type { CategoryFilterStateModel } from '../model/state';
|
import { createFilterStore } from '$shared/store/createFilterStore';
|
||||||
|
import type { CategoryFilterModel } from '../model/state';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initial state for CategoryFilter
|
* Initial state for CategoryFilter
|
||||||
*/
|
*/
|
||||||
export const initialState: CategoryFilterStateModel = {
|
export const initialState: CategoryFilterModel = {
|
||||||
searchQuery: '',
|
searchQuery: '',
|
||||||
categories: [],
|
categories: FONT_CATEGORIES,
|
||||||
selectedCategories: [],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const { subscribe, set, update } = writable<CategoryFilterStateModel>(initialState);
|
|
||||||
|
|
||||||
export const categoryFilterStore = {
|
|
||||||
subscribe,
|
|
||||||
set,
|
|
||||||
update,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the search query filter.
|
* CategoryFilter store
|
||||||
*
|
|
||||||
* @param searchQuery - Search text (undefined to clear)
|
|
||||||
*
|
|
||||||
* Learning Note:
|
|
||||||
* We use update() to modify the store based on current state.
|
|
||||||
* This is like a Redux reducer but without the boilerplate!
|
|
||||||
*/
|
*/
|
||||||
setSearchQuery: (searchQuery: string | undefined) => {
|
export const categoryFilterStore = createFilterStore(initialState);
|
||||||
update(state => ({
|
|
||||||
...state,
|
|
||||||
searchQuery: searchQuery || undefined,
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|||||||
20
src/features/CategoryFilter/ui/CategoryFilter.svelte
Normal file
20
src/features/CategoryFilter/ui/CategoryFilter.svelte
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import CheckboxFilter from '$shared/ui/CheckboxFilter/CheckboxFilter.svelte';
|
||||||
|
import { categoryFilterStore } from '../store/categoryFilterStore';
|
||||||
|
|
||||||
|
const { categories } = $derived($categoryFilterStore);
|
||||||
|
|
||||||
|
function didCategoryToggle(categoryId: string) {
|
||||||
|
if (categories?.find(category => category.id === categoryId)) {
|
||||||
|
categoryFilterStore.deselectCategory(categoryId);
|
||||||
|
} else {
|
||||||
|
categoryFilterStore.selectCategory(categoryId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<CheckboxFilter
|
||||||
|
filterName="Font category"
|
||||||
|
categories={categories}
|
||||||
|
onCategoryToggle={didCategoryToggle}
|
||||||
|
/>
|
||||||
Reference in New Issue
Block a user