added sort by metrics
This commit is contained in:
parent
435ba7450e
commit
69ac3af9b7
2 changed files with 65 additions and 4 deletions
|
@ -24,12 +24,12 @@
|
|||
</v-card-text>
|
||||
|
||||
<div class="px-4 flex-0">
|
||||
<v-chip label :color="props.markerColor ? void(0) : 'pink'" class="ma-1">
|
||||
<v-chip label :color="props.markerColor ? void(0) : 'pink'" class="ma-1" variant="outlined">
|
||||
<v-icon start icon="mdi-chart-timeline-variant"></v-icon>
|
||||
{{ company.ticker }}
|
||||
</v-chip>
|
||||
<template v-if="!props.minimal">
|
||||
<v-chip label color="green" class="ma-1">
|
||||
<v-chip label color="green" class="ma-1" variant="outlined">
|
||||
<v-icon start icon="mdi-currency-usd"></v-icon>
|
||||
{{ formatCurrency(company['market cap']) }}
|
||||
</v-chip>
|
||||
|
|
|
@ -3,12 +3,22 @@
|
|||
<v-app-bar-title>
|
||||
Stockingly
|
||||
</v-app-bar-title>
|
||||
|
||||
<v-text-field hide-details prepend-icon="mdi-magnify" single-line v-model="searchText"
|
||||
placeholder="Search company..." />
|
||||
<v-btn icon @click="clearSearch">
|
||||
<v-icon>mdi-backspace-outline</v-icon>
|
||||
</v-btn>
|
||||
<v-menu>
|
||||
<template v-slot:activator="{ props }">
|
||||
<v-btn variant="text" icon="mdi-sort" v-bind="props"></v-btn>
|
||||
</template>
|
||||
<v-list>
|
||||
<v-list-item v-for="(item, index) in sortItems" :key="index" :active="sortSelected === index" :value="index"
|
||||
@click="sortSelected = index">
|
||||
<v-list-item-title>{{ item.title }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</v-app-bar>
|
||||
<v-container class="fill-height">
|
||||
<v-row>
|
||||
|
@ -65,6 +75,45 @@ import CompanyCard from '@/components/CompanyCard.vue';
|
|||
|
||||
const MAX_SELECT = 3;
|
||||
|
||||
interface Sorter {
|
||||
title: string,
|
||||
sortBy?: keyof Company
|
||||
}
|
||||
|
||||
const sortItems: Sorter[] = [
|
||||
{
|
||||
title: 'Best Valuation',
|
||||
sortBy: 'Valuation',
|
||||
},
|
||||
{
|
||||
title: 'Best Financial Health',
|
||||
sortBy: 'Financial Health',
|
||||
},
|
||||
{
|
||||
title: 'Best Estimated Growth',
|
||||
sortBy: 'Estimated Growth',
|
||||
},
|
||||
{
|
||||
title: 'Best Past Performance',
|
||||
sortBy: 'Past Performance',
|
||||
},
|
||||
{
|
||||
title: 'Biggest Market Cap',
|
||||
sortBy: 'market cap'
|
||||
},
|
||||
{
|
||||
title: 'Relevance'
|
||||
}
|
||||
];
|
||||
|
||||
const naturalOrder = <T, Key>(getKey: (t: T) => Key) => (a: T, b: T) => {
|
||||
const aKey = getKey(a), bKey = getKey(b);
|
||||
// return reverse order since we sort in descending order
|
||||
return aKey > bKey ? -1 : aKey < bKey ? 1 : 0;
|
||||
}
|
||||
|
||||
const sortSelected = ref<number>(sortItems.length - 1);
|
||||
|
||||
const loading = ref(true);
|
||||
const companies = ref<Company[]>([]);
|
||||
const filteredCompanies = ref<(Company & { score?: number })[]>([]);
|
||||
|
@ -73,14 +122,26 @@ const searchText = ref("");
|
|||
const router = useRouter();
|
||||
let fuse: Fuse<Company> | undefined = undefined;
|
||||
|
||||
const sortCompanies = () => {
|
||||
const sorter = sortItems[sortSelected.value]!;
|
||||
if (sorter.sortBy !== undefined) {
|
||||
const key: keyof Company = sorter.sortBy;
|
||||
filteredCompanies.value = filteredCompanies.value.sort(naturalOrder(c => c[key]))
|
||||
}
|
||||
}
|
||||
|
||||
const search = debounce(() => setTimeout(() => {
|
||||
filteredCompanies.value = fuse!.search(searchText.value).map(e => ({ ...e.item, score: e.score }))
|
||||
}, 800));
|
||||
sortCompanies();
|
||||
}, 0), 1000);
|
||||
|
||||
watch(sortSelected, () => sortCompanies());
|
||||
|
||||
watch(searchText, () => {
|
||||
if (!fuse) return;
|
||||
if (searchText.value === '') {
|
||||
filteredCompanies.value = companies.value;
|
||||
sortCompanies();
|
||||
loading.value = false;
|
||||
return;
|
||||
}
|
||||
|
|
Reference in a new issue