Skip to content

Commit

Permalink
Extract devicesearch as separate component
Browse files Browse the repository at this point in the history
  • Loading branch information
pkong-ds committed Sep 2, 2024
1 parent 0ccb0bc commit f6c665f
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 292 deletions.
31 changes: 31 additions & 0 deletions src/components/DeviceSearch/DeviceSearch.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
import "./search.css";
import { DEVICE_MANAGER } from "../../scripts/deviceManager";
import { getModelItems, getBrandItems } from "../../scripts/algolia/generate";
const modelItems = getModelItems(DEVICE_MANAGER);
const brandItems = getBrandItems(DEVICE_MANAGER);
interface Props {
id: string;
}
const { id } = Astro.props;
---

<script define:vars={{ modelItems, brandItems, containerId: id }}>
window.modelItems = modelItems;
window.brandItems = brandItems;
if (window.containerIds != null) {
window.containerIds.push(containerId);
} else {
window.containerIds = [containerId];
}

console.log("hihi", containerId);
</script>

<>
<div id={id}></div>
<script src="./search.js"></script>
</>
43 changes: 40 additions & 3 deletions src/styles/search.css → src/components/DeviceSearch/search.css
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,47 @@
height: 100%;
}

/* .aa-InputWrapperPrefix > .aa-DetachedCancelButton {
height: 100%;
} */
.aa-InputWrapperSuffix {
width: 48px;
}
}

/* header variant styles */

#device-list__header__autocomplete {
max-width: 38%; /* 543 / 1440 */
flex: 1 1 0%;
margin: 0;
height: 56px;
background: var(--white);
}

@media (width >= 992px) {
#device-list__header__autocomplete {
margin: 0 0 0 144px; /* to prevent search bar overlapping with mockuphone logo */
}
}

@media (width >= 1300px) {
#device-list__header__autocomplete {
margin: 0;
}
}

.search-device {
display: flex;
padding: 40px 20px 0;
}

@media (width >= 992px) {
.search-device {
display: none;
}
}

#device-list__page__autocomplete {
flex: 1 1 0%;
margin: 0;
height: 56px;
background: var(--white);
}
64 changes: 31 additions & 33 deletions src/pages/_home.js → src/components/DeviceSearch/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,22 @@ import * as autocompletePluginRecentSearchesPkg from "@algolia/autocomplete-plug
const { createLocalStorageRecentSearchesPlugin } =
autocompletePluginRecentSearchesPkg;
import * as autocompleteJsPkg from "@algolia/autocomplete-js";
const { autocomplete } = autocompleteJsPkg;

const NUM_DEFAULT_MODEL_ITEMS_TO_DISPLAY = 0;
const NUM_DEFAULT_BRAND_ITEMS_TO_DISPLAY = 0;
const MAX_SEARCH_HISTORY_ITEM = 5;
const ALGOLIA_SEARCH_HISTORY_KEY = "brandModelSearch";
const LOCAL_STORAGE_KEY = `AUTOCOMPLETE_RECENT_SEARCHES:${ALGOLIA_SEARCH_HISTORY_KEY}`;

class RootViewModel {
searchText = "";
_modelItems;
_brandItems;

constructor(modelItems, brandItems) {
mobx.makeObservable(this, {
searchText: mobx.observable,
shouldShowSearchClear: mobx.computed,
});
this._modelItems = modelItems;
this._brandItems = brandItems;
}
const { autocomplete } = autocompleteJsPkg;

get shouldShowSearchClear() {
return this.searchText !== "";
}
}
const NUM_DEFAULT_MODEL_ITEMS_TO_DISPLAY = 0;
const NUM_DEFAULT_BRAND_ITEMS_TO_DISPLAY = 0;
const MAX_SEARCH_HISTORY_ITEM = 5;

function isArray(obj) {
return Object.prototype.toString.call(obj) === "[object Array]";
}

function appendToLocalStorageRecentSearches(item, type) {
const existingStr = localStorage.getItem(LOCAL_STORAGE_KEY);
const existingStr = localStorage.getItem(LOCAL_STORAGE_KEY) ?? "";
const existing = JSON.parse(existingStr);

const newHistoryItem = { id: item.id, label: item.name, type };
Expand Down Expand Up @@ -73,23 +56,31 @@ function moveOldHistoryToTop(oldHistoryItem) {
localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(newHistory));
}

function initializeAutocomplete(viewModel) {
function injectVariables() {
return {
modelItems: window.modelItems,
brandItems: window.brandItems,
containerIds: window.containerIds,
};
}

function initializeAutocomplete(containerId) {
const recentSearchesPlugin = createLocalStorageRecentSearchesPlugin({
key: ALGOLIA_SEARCH_HISTORY_KEY,
MAX_SEARCH_HISTORY_ITEM,
transformSource({ source }) {
return {
...source,
onSelect({ item }) {
const { id, label } = item;
const { id: itemId, label } = item;
const type = item.type ?? "";
moveOldHistoryToTop(item); // move most recent to top
switch (type) {
case "model":
window.location.href = `/model/${id}`;
window.location.href = `/model/${itemId}`;
break;
case "brand":
window.location.href = `/type/all/?brand=${id}`;
window.location.href = `/type/all/?brand=${itemId}`;
break;
default:
window.location.href = `/type/all/?query=${label}`;
Expand All @@ -98,12 +89,8 @@ function initializeAutocomplete(viewModel) {
};
},
});

const modelItems = viewModel._modelItems;
const brandItems = viewModel._brandItems;

autocomplete({
container: "#homepage-autocomplete",
container: `#${containerId}`,
openOnFocus: true,
plugins: [recentSearchesPlugin],
placeholder: "Search Device",
Expand Down Expand Up @@ -167,6 +154,18 @@ function initializeAutocomplete(viewModel) {
window.location.href = `${window.location.origin}/type/all/?query=${state.query}`;
},
});
}

function initialize() {
const { modelItems, brandItems, containerIds } = injectVariables();
console.log(modelItems, brandItems, containerIds);
containerIds.forEach((containerId) =>
console.log(document.querySelector(`#${containerId}`)),
);

containerIds.forEach((containerId) => {
initializeAutocomplete(containerId);
});

tippy(".aa-ClearButton", {
content: "Clear",
Expand Down Expand Up @@ -208,8 +207,7 @@ function ready(fn) {
}

function main() {
const viewModel = new RootViewModel(window.modelItems, window.brandItems);
initializeAutocomplete(viewModel);
initialize();
}

ready(main);
9 changes: 8 additions & 1 deletion src/layouts/BaseLayout/BaseLayout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import "bootstrap/dist/css/bootstrap.min.css";
import "/src/styles/main.css";
import "/src/styles/tailwind.css";
import { Image } from "@astrojs/image/components";
import DeviceSearch from "../../components/DeviceSearch/DeviceSearch.astro";
const title = "MockUPhone";
const description =
Expand All @@ -13,6 +14,12 @@ const social_url = "home_url";
const social_icon = `${
import.meta.env.PUBLIC_BASE_URL
}/images/mockuphone-logo.png`;
interface Props {
shouldRenderSearchBar?: boolean;
isHeaderTransparent?: boolean;
mainContainerClass?: string;
}
const {
shouldRenderSearchBar,
isHeaderTransparent = false,
Expand Down Expand Up @@ -134,7 +141,7 @@ const {
{
!!shouldRenderSearchBar ? (
<div class="header__search-container">
<div id="device-list__header__autocomplete" />
<DeviceSearch id="device-list__header__autocomplete" />
</div>
) : undefined
}
Expand Down
12 changes: 2 additions & 10 deletions src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,13 @@ import "/src/styles/home.css";
import BaseLayout from "../layouts/BaseLayout/BaseLayout.astro";
import { Image } from "@astrojs/image/components";
import { DEVICE_MANAGER } from "../scripts/deviceManager";
import { getModelItems, getBrandItems } from "../scripts/algolia/generate";
const modelItems = getModelItems(DEVICE_MANAGER);
const brandItems = getBrandItems(DEVICE_MANAGER);
import DeviceSearch from "../components/DeviceSearch/DeviceSearch.astro";
---

<BaseLayout
isHeaderTransparent={true}
mainContainerClass="main--landing-content"
>
<script define:vars={{ modelItems, brandItems }}>
window.modelItems = modelItems;
window.brandItems = brandItems;
</script>
<script src="./_home.js"></script>
<div class="landing-content">
<header class="headline">
<h2 class="headline__title">
Expand All @@ -27,7 +19,7 @@ const brandItems = getBrandItems(DEVICE_MANAGER);
Wrap your design in mobile devices in a few clicks!
</p>
</header>
<div id="homepage-autocomplete"></div>
<DeviceSearch id="homepage-autocomplete" />
<ul class="quick-device-list">
<li class="quick-device-list__item quick-device-list__item__light-blue">
<a
Expand Down
15 changes: 4 additions & 11 deletions src/pages/type/[type].astro
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@ import RequestDeviceCard from "../../components/RequestDeviceCard/RequestDeviceC
import "./index.css";
import { DEVICE_MANAGER } from "../../scripts/deviceManager";
import type { BrandValue, ModelThumbnail } from "../../scripts/model";
import { BrandEnum, DeviceTypeEnum } from "../../scripts/parse";
import { getModelItems, getBrandItems } from "../../scripts/algolia/generate";
const modelItems = getModelItems(DEVICE_MANAGER);
const brandItems = getBrandItems(DEVICE_MANAGER);
import { DEVICE_MANAGER } from "../../scripts/deviceManager";
import DeviceSearch from "../../components/DeviceSearch/DeviceSearch.astro";
export async function getStaticPaths() {
const devicePaths = DeviceTypeEnum.options.map((deviceType) => ({
Expand Down Expand Up @@ -47,17 +45,12 @@ const brandList: Array<BrandEnum | "all"> = ["all", ...nonEmptyBrands];
content="MockUPhone supports devices including iPhone mockup, iPad mockup, Android mockup and TV mockup. You can check out the whole device list via this page."
/>
<script src="./_device.js"></script>
<script
define:vars={{ thumbnailList, brandThumbnailList, modelItems, brandItems }}
>
<script define:vars={{ thumbnailList, brandThumbnailList }}>
window.thumbnailList = thumbnailList;
window.brandThumbnailList = brandThumbnailList;
window.modelItems = modelItems;
window.brandItems = brandItems;
</script>
<section class="search-device">
<div id="device-list__page__autocomplete"></div>
{/* Add suggestion list here */}
<DeviceSearch id="device-list__page__autocomplete" />
</section>
<section class="device-type">
<header>
Expand Down
Loading

0 comments on commit f6c665f

Please sign in to comment.