forked from M-Labs/web2019
Prototype search bar for the backlog
Signed-off-by: Egor Savkin <es@m-labs.hk>
This commit is contained in:
parent
2ba10dd2e8
commit
4bc6f6a3ee
@ -1,9 +1,11 @@
|
||||
import React from 'react';
|
||||
import {Droppable} from "@hello-pangea/dnd";
|
||||
import {ProductItem} from "./ProductItem";
|
||||
import {useShopStore} from "./shop_store";
|
||||
// #!render_count
|
||||
import {useRenderCount} from "@uidotdev/usehooks";
|
||||
import {BacklogGroups} from "./BacklogGroups";
|
||||
import {SearchBar} from "./SearchBar";
|
||||
import {BacklogSearchResult} from "./BacklogSearchResult";
|
||||
|
||||
/**
|
||||
* Component that renders the backlog in the aside
|
||||
@ -14,43 +16,13 @@ export function Backlog() {
|
||||
|
||||
const data = useShopStore((state) => state.groups);
|
||||
const items = useShopStore((state) => state.cards);
|
||||
|
||||
const onClickToggleMobileSideMenu = useShopStore((state) => state.switchSideMenu);
|
||||
const isMobile = useShopStore((state) => state.isMobile);
|
||||
|
||||
// #!render_count
|
||||
console.log("Backlog renders: ", renderCount)
|
||||
|
||||
const ordered_groups = data.categories.map(groupItem => ({
|
||||
name: groupItem.name,
|
||||
items: groupItem.itemIds.map(itemId => items[itemId])
|
||||
}));
|
||||
let item_index = -1;
|
||||
const groups = ordered_groups.map((group, g_index) => {
|
||||
return (
|
||||
<div className="accordion-item" key={`${group.name}`}>
|
||||
<h2 className="accordion-header">
|
||||
<button className="accordion-button collapsed" type="button" data-bs-toggle="collapse"
|
||||
data-bs-target={`#collapse${g_index}`} aria-expanded="true"
|
||||
aria-controls={`collapse${g_index}`}>
|
||||
{group.name}
|
||||
</button>
|
||||
</h2>
|
||||
<div id={`collapse${g_index}`} className="accordion-collapse collapse" aria-labelledby="headingOne"
|
||||
data-bs-parent="#accordion_categories">
|
||||
<div className="accordion-body">
|
||||
{group.items.map(item => {
|
||||
item_index++;
|
||||
return (
|
||||
<ProductItem card_index={item_index} key={item.id} />
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<Droppable
|
||||
droppableId={data.id}
|
||||
@ -70,9 +42,11 @@ export function Backlog() {
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
<div className="accordion accordion-flush" id="accordion_categories">
|
||||
{groups}
|
||||
</div>
|
||||
<SearchBar/>
|
||||
|
||||
<BacklogSearchResult/>
|
||||
|
||||
<BacklogGroups/>
|
||||
|
||||
{provided.placeholder && (
|
||||
<div style={{display: 'none'}}>
|
||||
|
44
static/js/shop/BacklogGroups.jsx
Normal file
44
static/js/shop/BacklogGroups.jsx
Normal file
@ -0,0 +1,44 @@
|
||||
import {ProductItem} from "./ProductItem";
|
||||
import React from "react";
|
||||
import {useShopStore} from "./shop_store";
|
||||
|
||||
export function BacklogGroups() {
|
||||
const data = useShopStore((state) => state.groups);
|
||||
const items = useShopStore((state) => state.cards);
|
||||
|
||||
const ordered_groups = data.categories.map(groupItem => ({
|
||||
name: groupItem.name,
|
||||
items: groupItem.itemIds.map(itemId => items[itemId])
|
||||
}));
|
||||
let item_index = -1;
|
||||
const groups = ordered_groups.map((group, g_index) => {
|
||||
return (
|
||||
<div className="accordion-item" key={`${group.name}`}>
|
||||
<h2 className="accordion-header">
|
||||
<button className="accordion-button collapsed" type="button" data-bs-toggle="collapse"
|
||||
data-bs-target={`#collapse${g_index}`} aria-expanded="true"
|
||||
aria-controls={`collapse${g_index}`}>
|
||||
{group.name}
|
||||
</button>
|
||||
</h2>
|
||||
<div id={`collapse${g_index}`} className="accordion-collapse collapse" aria-labelledby="headingOne"
|
||||
data-bs-parent="#accordion_categories">
|
||||
<div className="accordion-body">
|
||||
{group.items.map(item => {
|
||||
item_index++;
|
||||
return (
|
||||
<ProductItem card_index={item_index} key={item.id} />
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
return (
|
||||
<div className="accordion accordion-flush" id="accordion_categories">
|
||||
{groups}
|
||||
</div>
|
||||
)
|
||||
}
|
16
static/js/shop/BacklogSearchResult.jsx
Normal file
16
static/js/shop/BacklogSearchResult.jsx
Normal file
@ -0,0 +1,16 @@
|
||||
import React from 'react';
|
||||
import {useShopStore} from "./shop_store";
|
||||
import {ProductItem} from "./ProductItem";
|
||||
|
||||
|
||||
export function BacklogSearchResult() {
|
||||
const cards_to_display = useShopStore((state) => state.listed_cards);
|
||||
return ( <>
|
||||
{cards_to_display.map((item, _) => {
|
||||
return (
|
||||
<ProductItem card_index={item} key={"searched_" + item} />
|
||||
)
|
||||
})}
|
||||
</>
|
||||
)
|
||||
}
|
19
static/js/shop/SearchBar.jsx
Normal file
19
static/js/shop/SearchBar.jsx
Normal file
@ -0,0 +1,19 @@
|
||||
import React from 'react';
|
||||
import {useShopStore} from "./shop_store";
|
||||
|
||||
export function SearchBar() {
|
||||
const search_bar_value = useShopStore((state) => state.search_bar_value);
|
||||
const updateSearchBar = useShopStore((state) => state.updateSearchBar);
|
||||
|
||||
return (
|
||||
<div className="form-outline">
|
||||
<input type="search"
|
||||
id="search_bar"
|
||||
className="form-control"
|
||||
placeholder="Search through cards"
|
||||
value={search_bar_value}
|
||||
onChange={event => updateSearchBar(event.target.value)}
|
||||
aria-label="Search"/>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -29,6 +29,21 @@ const useBacklog = ((set, get) => ({
|
||||
cardIndexById: card_id => get().cards_list.findIndex((element) => (card_id === element))
|
||||
}));
|
||||
|
||||
const useSearch = ((set, get) => ({
|
||||
search_index: Array.from(Object.values(shared_data.items)
|
||||
.map((card, _) => (
|
||||
[(card.name + " " + card.name_number + " " + card.name_codename).toLowerCase(), card.id]
|
||||
))),
|
||||
search_bar_value: "",
|
||||
listed_cards: [],
|
||||
updateSearchBar: text => set(state => ({
|
||||
search_bar_value: text,
|
||||
listed_cards: text.length > 0 ? Array.from(get().search_index
|
||||
.filter((card, _) => card[0].includes(text.toLowerCase()))
|
||||
.map(([index, card_id], _) => get().cards_list.findIndex(elem => elem === card_id))) : []
|
||||
}))
|
||||
}));
|
||||
|
||||
const useCrateModes = ((set, get) => ({
|
||||
crate_modes: shared_data.crateModes,
|
||||
modes_order: shared_data.crateModeOrder,
|
||||
@ -569,6 +584,7 @@ const useCart = ((set, get) => ({
|
||||
|
||||
export const useShopStore = createWithEqualityFn((...params) => ({
|
||||
...useBacklog(...params),
|
||||
...useSearch(...params),
|
||||
...useCrateModes(...params),
|
||||
...useCart(...params),
|
||||
...useSubmitForm(...params),
|
||||
|
Loading…
Reference in New Issue
Block a user