I have this sortedArray where I am using v-for to display all service items. Each item has a stationName, startDate, and endDate. I am using lodash to sortBy a specific key inside the array.
Can't see what I am doing wrong. Can someone help? I tried multiple things but can't make it work. I want to be able to sort by end date, start date, and station name.
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue';
import { orderBy } from 'lodash';
// Types
import type { Stationwork } from 'types/store/stationworks';
// Store
import { useStationStore } from 'store/stations';
import { useStationworksStore } from 'store/stationworks';
// Components
import BaseIcon from 'components/atoms/BaseIcon.vue';
import MultiSelect from 'components/molecules/MultiSelect.vue';
import StationWorksListItem from 'components/molecules/StationWorksListItem.vue';
// Composables
import { useComponent } from 'composable/component';
const stationStore = useStationStore();
const stationworksStore = useStationworksStore();
const module = 'v-station-works-list';
const selectedStations = ref<any>([]);
const selectedFields = ref<string[]>(['filterCurrent']);
const filterFieldOptions = ref([
{ id: 1, text: 'Filter zichtbaarheid in infobox', value: 'filterVisible' },
{ id: 2, text: 'Filter actuele werkzaamheden', value: 'filterCurrent' }
]);
const { childClass } = useComponent(module);
const handleSelectUpdate = (selected: string) => {
selectedStations.value = selected;
};
const currentStationsOptions = computed(() => stationworksStore.currentStationsOptions);
const mapStation = (station: Stationwork) => ({
uuid: station.uuid,
stationCode: station.stationCode,
stationName: stationStore.getStationName(station.stationCode),
workSubject: station.workSubject,
startDate: station.startDate,
endDate: station.endDate,
workContent: station.workContent,
showWork: station.showWork
});
const currentStationWorks = computed(() => {
const filterCurrent = selectedFields.value.includes('filterCurrent');
const filterVisible = selectedFields.value.includes('filterVisible');
const works = stationworksStore.works
.filter((station: Stationwork) => {
const isSelectedStation = selectedStations.value.includes(
stationStore.getStationName(station.stationCode)
);
if (!isSelectedStation) {
return false;
}
if (filterCurrent) {
const startDate = station.startDate ? Date.parse(station.startDate) : false;
const endDate = station.endDate ? Date.parse(station.endDate) : false;
if (!startDate) {
return false;
}
const isBeforeToday = startDate <= Date.now();
let isInFuture = false;
if (endDate) {
isInFuture = endDate >= Date.now();
}
const isInCurrentRange =
startDate && endDate ? isBeforeToday && isInFuture : isBeforeToday;
if (!isInCurrentRange) {
return false;
}
}
if (filterVisible && !station.showWork) {
return false;
}
return true;
})
.map(mapStation);
return works;
});
const moduleClasses = computed(() => ({
[module]: true
}));
enum SortCriteria {
STATION = 'stationName',
START_DATE = 'startDate',
END_DATE = 'endDate'
}
const sortOrder = ref<'asc' | 'desc'>('asc');
const sortCriteria = ref<SortCriteria | string>('');
const sortedArray = computed(() => {
return orderBy(currentStationWorks.value, [sortCriteria.value], [sortOrder.value]);
});
const sortBy = (criteria: SortCriteria) => {
sortOrder.value = sortOrder.value === 'asc' ? 'desc' : 'asc';
const sortedWorks = orderBy(currentStationWorks.value, [criteria], [sortOrder.value]);
console.log(sortedWorks);
return sortedWorks;
};
onMounted(async () => {
selectedStations.value = stationworksStore.currentStationsOptions;
if (!stationStore.stations.length) {
await stationStore.fetchAll();
selectedStations.value = stationworksStore.currentStationsOptions;
}
});
</script>
<template>
<div :class="moduleClasses">
<div :class="childClass('container')">
<div :class="childClass('content')">
<h1 :class="childClass('title')">Stationswerkzaamheden</h1>
<p :class="childClass('text')">
Mogelijkheid filteren op station, selecteer station(s)
</p>
</div>
<div :class="childClass('holder')">
<div :class="childClass('header')">
<MultiSelect
class="w-full max-w-2xl"
v-if="currentStationsOptions.length"
all_option_text="Alle stations"
num_text=" stations geselecteerd"
all_text="Alle stations geselecteerd"
placeholder="Selecteer station(s)"
:initial_value="currentStationsOptions"
:choices="currentStationsOptions"
:update_while_opened="true"
:options_show_full="1"
@select-update="handleSelectUpdate"
/>
<BaseIcon
v-else
icon="loader"
class="animate-spin text-lg text-ns-light-blue"
/>
<div class="ml-auto flex flex-col items-center gap-x-6 gap-y-2 lg:flex-row">
<div
class="flex items-center"
v-for="field in filterFieldOptions"
:key="field.id"
>
<input
:id="field.value"
type="checkbox"
class="h-5 w-5 shrink-0 border-ns-light-gray bg-gray-100 accent-ns-light-blue focus:ring-ns-blue"
:name="field.text"
v-model="selectedFields"
:value="field.value"
/>
<label :for="field.value" class="ms-2 cursor-pointer text-sm">{{
field.text
}}</label>
</div>
</div>
</div>
<div :class="childClass('station-header')">
<span class="col-span-2" @click="sortBy(SortCriteria.STATION)">Station</span>
<span class="col-span-3 lg:col-span-4">Omschrijving</span>
<span class="col-span-2 lg:col-span-1" @click="sortBy(SortCriteria.START_DATE)"
>Startdatum</span
>
<span class="col-span-2 lg:col-span-1" @click="sortBy(SortCriteria.END_DATE)"
>Einddatum</span
>
<span class="col-span-3 lg:col-span-4">Uitgebreide omschrijving</span>
</div>
<div v-if="currentStationsOptions.length" :class="childClass('overview')">
<StationWorksListItem
v-for="station in sortedArray"
:key="station.uuid"
:station="station"
/>
</div>
</div>
</div>
</div>
</template>
In your template, you're using sortedArray
which always sorts by [SortCriteria.STATION]
.
Your sortBy
function is indeed called when clicking what I assume is your column header, but its result is never used (except in your console.log), and so, is lost.
Make a state for the sort criteria itself and use it in your computed value 'sortedArray
'.