Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(pages): update search results filtering #224

Merged
merged 5 commits into from Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
51 changes: 26 additions & 25 deletions client/src/pages/SearchResultPage.vue
Expand Up @@ -42,32 +42,31 @@
</div>

<div data-test="search-results">
<GridContainer
<section
v-for="section in uiShape"
:key="section.header"
:columns="3"
template-rows="auto auto 1fr"
component="section"
data-test="search"
class="p-0 w-full md:max-w-[unset] lg:max-w-[unset]"
class="mt-8 p-0 w-full"
>
<GridItem class="section-subheading" component="h2" :span-column="3">
<h2 class="section-subheading w-full">
{{ section.header }}
</GridItem>
</h2>

<SearchResultCard
v-for="record in section.records"
:key="record.type"
data-test="search-results-cards"
:data-source="searchResult[record.type]"
/>
</GridContainer>
<div class="grid pdap-grid-container-column-3 gap-4">
<SearchResultCard
v-for="result in [...getAllRecordsFromSection(section)]"
:key="result.record"
data-test="search-results-cards"
:data-source="result"
/>
</div>
</section>
</div>
</main>
</template>

<script>
import { Button, GridContainer, GridItem } from 'pdap-design-system';
import { Button } from 'pdap-design-system';
import SearchResultCard from '../components/SearchResultCard.vue';
import axios from 'axios';
import pluralize from '../util/pluralize';
Expand All @@ -78,8 +77,6 @@ export default {
components: {
Button,
SearchResultCard,
GridContainer,
GridItem,
},
data: () => ({
count: 0,
Expand All @@ -95,6 +92,11 @@ export default {
this.search();
},
methods: {
getAllRecordsFromSection(section) {
return section.records.reduce((acc, cur) => {
return [...acc, ...this.searchResult[cur.type]];
}, []);
},
getResultsCopy() {
return `${this.count} ${pluralize('result', this.count)}`;
},
Expand All @@ -110,7 +112,12 @@ export default {

// Format results into object keyed by record_type
const resultFormatted = res.data.data.reduce((acc, cur) => {
return { ...acc, [cur.record_type]: cur };
return {
...acc,
[cur.record_type]: Array.isArray(acc[cur.record_type])
? [...acc[cur.record_type], cur]
: [cur],
};
Comment on lines +115 to +120
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maxachis see this part of the code wrt bug fix for #217. The previous logic was keying an object by record_type but forgot to take into account that there might be multiple records of the same type. To fix this bug, we're instead assigning an array to each of those keys, to accommodate multiple values of each key. The updates to the template above are in service of this change (as well as some general cleanup, as we're moving away from the GridContainer and GridItem components).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that would make sense. So regardless of whether there's one record or multiple, it is formatted into an array, simplifying the logic on the backend.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that would make sense. So regardless of whether there's one record or multiple, it is formatted into an array, simplifying the logic on the backend.

Yeah @maxachis I think @mbodeantor and I are aligned on the idea that the API should be as simple as possible, and any complex manipulation required by UX or design requirements should be handled by the client.

}, {});

// Modify ui shape object to exclude any sections / data sources that do not have records returned by API
Expand All @@ -125,7 +132,7 @@ export default {

// Set data and away we go
this.searchResult = resultFormatted;
this.count = Object.entries(this.searchResult).length;
this.count = res.data.count;
} catch (error) {
console.error(error);
} finally {
Expand All @@ -135,9 +142,3 @@ export default {
},
};
</script>

<style scoped>
.section-subheading {
@apply mt-4;
}
</style>
Expand Up @@ -4,7 +4,7 @@ exports[`SearchResultPage renders with data > Calls API and renders search resul
<main class="flex flex-col p-8 h-auto">
<div>
<h1>Data Sources Search results</h1>
<p class="text-2xl"> Searching for <span class="font-semibold">"calls"</span> in <span class="font-semibold">"Cook"</span>. <span>Found 1 result.</span>
<p class="text-2xl"> Searching for <span class="font-semibold">"calls"</span> in <span class="font-semibold">"Cook"</span>. <span>Found 3 results.</span>
</p>
<button class="pdap-button pdap-button-secondary my-4">
<i class="fa fa-plus"></i> New search
Expand All @@ -19,19 +19,92 @@ exports[`SearchResultPage renders with data > Calls API and renders search resul
</p>
</div>
<div>
<section class="pdap-grid-container pdap-grid-container-column-3 p-0 w-full md:max-w-[unset] lg:max-w-[unset]" style="grid-template-rows: auto auto 1fr;">
<h2 class="pdap-grid-item pdap-grid-item-span-column-3 section-subheading">Police & public interactions</h2>
<div class="pdap-grid-item flex flex-col border border-neutral-400 p-3 text-lg leading-snug">
<h3 class="text-xl font-semibold line-clamp-2 normal-case tracking-normal min-h-[50px]">311 Calls for City of Chicago</h3>
<button class="pdap-button pdap-button-primary text-lg font-medium px-4 py-1 mt-4 mb-2 lg:mx-0 max-w-full"> Visit data source <i class="fa fa-external-link"></i>
</button>
<p class="text-brand-wine dark:text-white font-semibold text-sm uppercase tracking-wider mb-0 mt-4"> Record type </p>
<div class="mt-1 py-[.125rem] px-3 rounded-full bg-brand-wine/10 dark:bg-brand-wine dark:text-white w-fit">Calls for Service</div>
<div class="search-result-agency">
<p class="text-brand-wine dark:text-white font-semibold text-sm uppercase tracking-wider mb-0 mt-4"> Agency </p>
<p>Chicago Police Department - IL</p>
<section class="mt-8 p-0 w-full">
<h2 class="section-subheading w-full">Police & public interactions</h2>
<div class="grid pdap-grid-container-column-3 gap-4">
<div class="pdap-grid-item flex flex-col border border-neutral-400 p-3 text-lg leading-snug">
<h3 class="text-xl font-semibold line-clamp-2 normal-case tracking-normal min-h-[50px]">Calls for Service for Cicero Police Department - IN</h3>
<button class="pdap-button pdap-button-primary text-lg font-medium px-4 py-1 mt-4 mb-2 lg:mx-0 max-w-full"> Visit data source <i class="fa fa-external-link"></i>
</button>
<p class="text-brand-wine dark:text-white font-semibold text-sm uppercase tracking-wider mb-0 mt-4"> Record type </p>
<div class="mt-1 py-[.125rem] px-3 rounded-full bg-brand-wine/10 dark:bg-brand-wine dark:text-white w-fit">Calls for Service</div>
<div class="search-result-agency">
<p class="text-brand-wine dark:text-white font-semibold text-sm uppercase tracking-wider mb-0 mt-4"> Agency </p>
<p>Cicero Police Department - IN</p>
</div>
<!-- hiding place for now
<div data-test="search-result-place">
<p
v-if="dataSource.municipality && dataSource.state_iso"
data-test="search-result-place-state-municipality"
>
{{ dataSource.municipality }}, {{ dataSource.state_iso }}
</p>
<p v-else-if="dataSource.municipality" data-test="search-result-place-municipality">
{{ dataSource.municipality }}
</p>
<p v-else-if="dataSource.state_iso" data-test="search-result-place-state">
{{ dataSource.state_iso }}
</p>
<p v-else data-test="search-result-place-unknown">Location Unknown</p>
</div>
-->
<p class="text-brand-wine dark:text-white font-semibold text-sm uppercase tracking-wider mb-0 mt-4"> Time range </p>
<p>2016–Unknown end </p>
<p class="text-brand-wine dark:text-white font-semibold text-sm uppercase tracking-wider mb-0 mt-4"> Formats available </p>
<ul class="mb-4">
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">[</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">]</li>
</ul>
<button class="pdap-button pdap-button-secondary text-lg font-medium px-4 py-1 lg:mx-0 max-w-full mt-auto"> More details </button>
</div>
<div class="pdap-grid-item flex flex-col border border-neutral-400 p-3 text-lg leading-snug">
<h3 class="text-xl font-semibold line-clamp-2 normal-case tracking-normal min-h-[50px]">Calls for Service for Chicago Police Department - IL</h3>
<button class="pdap-button pdap-button-primary text-lg font-medium px-4 py-1 mt-4 mb-2 lg:mx-0 max-w-full"> Visit data source <i class="fa fa-external-link"></i>
</button>
<p class="text-brand-wine dark:text-white font-semibold text-sm uppercase tracking-wider mb-0 mt-4"> Record type </p>
<div class="mt-1 py-[.125rem] px-3 rounded-full bg-brand-wine/10 dark:bg-brand-wine dark:text-white w-fit">Calls for Service</div>
<div class="search-result-agency">
<p class="text-brand-wine dark:text-white font-semibold text-sm uppercase tracking-wider mb-0 mt-4"> Agency </p>
<p>Chicago Police Department - IL</p>
</div>
<!-- hiding place for now
<div data-test="search-result-place">
<p
v-if="dataSource.municipality && dataSource.state_iso"
data-test="search-result-place-state-municipality"
>
{{ dataSource.municipality }}, {{ dataSource.state_iso }}
</p>
<p v-else-if="dataSource.municipality" data-test="search-result-place-municipality">
{{ dataSource.municipality }}
</p>
<p v-else-if="dataSource.state_iso" data-test="search-result-place-state">
{{ dataSource.state_iso }}
</p>
<p v-else data-test="search-result-place-unknown">Location Unknown</p>
</div>
-->
<p class="text-brand-wine dark:text-white font-semibold text-sm uppercase tracking-wider mb-0 mt-4"> Time range </p>
<p>2018–Unknown end </p>
<p class="text-brand-wine dark:text-white font-semibold text-sm uppercase tracking-wider mb-0 mt-4"> Formats available </p>
<ul class="mb-4">
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">[</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">]</li>
</ul>
<button class="pdap-button pdap-button-secondary text-lg font-medium px-4 py-1 lg:mx-0 max-w-full mt-auto"> More details </button>
</div>
<!-- hiding place for now
<div class="pdap-grid-item flex flex-col border border-neutral-400 p-3 text-lg leading-snug">
<h3 class="text-xl font-semibold line-clamp-2 normal-case tracking-normal min-h-[50px]">311 Calls for City of Chicago</h3>
<button class="pdap-button pdap-button-primary text-lg font-medium px-4 py-1 mt-4 mb-2 lg:mx-0 max-w-full"> Visit data source <i class="fa fa-external-link"></i>
</button>
<p class="text-brand-wine dark:text-white font-semibold text-sm uppercase tracking-wider mb-0 mt-4"> Record type </p>
<div class="mt-1 py-[.125rem] px-3 rounded-full bg-brand-wine/10 dark:bg-brand-wine dark:text-white w-fit">Calls for Service</div>
<div class="search-result-agency">
<p class="text-brand-wine dark:text-white font-semibold text-sm uppercase tracking-wider mb-0 mt-4"> Agency </p>
<p>Chicago Police Department - IL</p>
</div>
<!-- hiding place for now
<div data-test="search-result-place">
<p
v-if="dataSource.municipality && dataSource.state_iso"
Expand All @@ -48,40 +121,41 @@ exports[`SearchResultPage renders with data > Calls API and renders search resul
<p v-else data-test="search-result-place-unknown">Location Unknown</p>
</div>
-->
<p class="text-brand-wine dark:text-white font-semibold text-sm uppercase tracking-wider mb-0 mt-4"> Time range </p>
<p>12/17/2018–Unknown end </p>
<p class="text-brand-wine dark:text-white font-semibold text-sm uppercase tracking-wider mb-0 mt-4"> Formats available </p>
<ul class="mb-4">
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">[</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">'</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">C</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">S</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">V</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">'</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">,</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit"> </li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">'</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">X</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">M</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">L</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">'</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">,</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit"> </li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">'</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">R</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">D</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">F</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">'</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">,</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit"> </li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">'</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">R</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">S</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">S</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">'</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">]</li>
</ul>
<button class="pdap-button pdap-button-secondary text-lg font-medium px-4 py-1 lg:mx-0 max-w-full mt-auto"> More details </button>
<p class="text-brand-wine dark:text-white font-semibold text-sm uppercase tracking-wider mb-0 mt-4"> Time range </p>
<p>12/17/2018–Unknown end </p>
<p class="text-brand-wine dark:text-white font-semibold text-sm uppercase tracking-wider mb-0 mt-4"> Formats available </p>
<ul class="mb-4">
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">[</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">'</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">C</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">S</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">V</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">'</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">,</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit"> </li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">'</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">X</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">M</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">L</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">'</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">,</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit"> </li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">'</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">R</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">D</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">F</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">'</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">,</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit"> </li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">'</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">R</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">S</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">S</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">'</li>
<li class="mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit">]</li>
</ul>
<button class="pdap-button pdap-button-secondary text-lg font-medium px-4 py-1 lg:mx-0 max-w-full mt-auto"> More details </button>
</div>
</div>
</section>
</div>
Expand Down