mirror of
https://github.com/Spythere/stacjownik.git
synced 2026-05-03 05:18:11 +00:00
chore(profile): added combined journal with timetables and dispatchers; added journal filters
This commit is contained in:
@@ -41,6 +41,8 @@ export namespace API {
|
|||||||
|
|
||||||
export interface Data {
|
export interface Data {
|
||||||
id: number;
|
id: number;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
currentDuration: number;
|
currentDuration: number;
|
||||||
dispatcherId: number;
|
dispatcherId: number;
|
||||||
dispatcherName: string;
|
dispatcherName: string;
|
||||||
|
|||||||
@@ -93,14 +93,18 @@
|
|||||||
<h3 class="main-header">OSTATNIA AKTYWNOŚĆ GRACZA</h3>
|
<h3 class="main-header">OSTATNIA AKTYWNOŚĆ GRACZA</h3>
|
||||||
|
|
||||||
<div class="history-menu">
|
<div class="history-menu">
|
||||||
<button class="history-menu-button">ROZKŁADY JAZDY</button>
|
<button class="history-menu-button" @click="toggleFilter('Timetable')">
|
||||||
<button class="history-menu-button">SŁUŻBY DR</button>
|
ROZKŁADY JAZDY
|
||||||
<button class="history-menu-button">WYSTAWIONE RJ</button>
|
</button>
|
||||||
|
<button class="history-menu-button" @click="toggleFilter('Dispatcher')">SŁUŻBY DR</button>
|
||||||
|
<button class="history-menu-button" @click="toggleFilter('IssuedTimetable')">
|
||||||
|
WYSTAWIONE RJ
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="history-list-box">
|
<div class="history-list-box">
|
||||||
<ul>
|
<ul>
|
||||||
<li></li>
|
<li v-for="entry in combinedJournal">{{ entry.type }} - {{ entry.date }}</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -109,22 +113,77 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { onMounted, ref } from 'vue';
|
import { computed, onMounted, reactive, ref } from 'vue';
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import { useApiStore } from '../store/apiStore';
|
import { useApiStore } from '../store/apiStore';
|
||||||
import { API } from '../typings/api';
|
import { API } from '../typings/api';
|
||||||
|
|
||||||
|
type JournalEntryType = 'Timetable' | 'Dispatcher' | 'IssuedTimetable';
|
||||||
|
|
||||||
|
interface JournalEntry {
|
||||||
|
type: JournalEntryType;
|
||||||
|
date: Date;
|
||||||
|
value: API.TimetableHistory.DataShort | API.DispatcherHistory.Data;
|
||||||
|
}
|
||||||
|
|
||||||
const apiStore = useApiStore();
|
const apiStore = useApiStore();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
|
const playerName = ref('');
|
||||||
const playerInfo = ref<API.PlayerInfo.Data | null>(null);
|
const playerInfo = ref<API.PlayerInfo.Data | null>(null);
|
||||||
const playerJournal = ref<API.PlayerJournal.Data | null>(null);
|
const playerJournal = ref<API.PlayerJournal.Data | null>(null);
|
||||||
|
|
||||||
|
const activeFilterTypes = reactive<Record<JournalEntryType, boolean>>({
|
||||||
|
Timetable: true,
|
||||||
|
Dispatcher: true,
|
||||||
|
IssuedTimetable: true
|
||||||
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
fetchPlayerInfoData();
|
fetchPlayerInfoData();
|
||||||
fetchPlayerJournal();
|
fetchPlayerJournal();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const combinedJournal = computed<JournalEntry[]>(() => {
|
||||||
|
if (!playerJournal.value) return [];
|
||||||
|
|
||||||
|
const list = [
|
||||||
|
...playerJournal.value.timetables,
|
||||||
|
...playerJournal.value.duties,
|
||||||
|
...playerJournal.value.issuedTimetables
|
||||||
|
]
|
||||||
|
.reduce<JournalEntry[]>((acc, v) => {
|
||||||
|
// Timetable or dispatcher type
|
||||||
|
if ('trainNo' in v) {
|
||||||
|
const isIssued = v.authorName == playerName.value;
|
||||||
|
|
||||||
|
if (!isIssued && !activeFilterTypes['Timetable']) return acc;
|
||||||
|
if (isIssued && !activeFilterTypes['IssuedTimetable']) return acc;
|
||||||
|
|
||||||
|
acc.push({
|
||||||
|
date: new Date(v.createdAt),
|
||||||
|
type: isIssued ? 'IssuedTimetable' : 'Timetable',
|
||||||
|
value: v
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (!activeFilterTypes['Dispatcher']) return acc;
|
||||||
|
|
||||||
|
acc.push({
|
||||||
|
date: new Date(v.timestampFrom),
|
||||||
|
type: 'Dispatcher',
|
||||||
|
value: v
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, [])
|
||||||
|
.sort((a, b) => {
|
||||||
|
return a.date.getTime() - b.date.getTime() > 0 ? -1 : 1;
|
||||||
|
});
|
||||||
|
|
||||||
|
return list;
|
||||||
|
});
|
||||||
|
|
||||||
async function fetchPlayerInfoData() {
|
async function fetchPlayerInfoData() {
|
||||||
const playerId = route.params.id.toString();
|
const playerId = route.params.id.toString();
|
||||||
|
|
||||||
@@ -156,10 +215,28 @@ async function fetchPlayerJournal() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
playerJournal.value = response.data;
|
playerJournal.value = response.data;
|
||||||
|
playerName.value =
|
||||||
|
response.data.timetables.at(0)?.driverName ||
|
||||||
|
response.data.duties.at(0)?.dispatcherName ||
|
||||||
|
'';
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toggleFilter(filterType: JournalEntryType) {
|
||||||
|
const toggledState = !activeFilterTypes[filterType];
|
||||||
|
|
||||||
|
// Prevent switching off all filters at the same time (at least one must be active)
|
||||||
|
if (
|
||||||
|
toggledState === false &&
|
||||||
|
Object.values(activeFilterTypes).filter((v) => v === false).length ==
|
||||||
|
Object.values(activeFilterTypes).length - 1
|
||||||
|
)
|
||||||
|
return;
|
||||||
|
|
||||||
|
activeFilterTypes[filterType] = toggledState;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@@ -182,7 +259,7 @@ $tileColor: #181818;
|
|||||||
|
|
||||||
max-width: var(--max-container-width);
|
max-width: var(--max-container-width);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: calc(100vh - 0.5em);
|
// height: calc(100vh - 0.5em);
|
||||||
min-height: 900px;
|
min-height: 900px;
|
||||||
|
|
||||||
padding: 1rem 0;
|
padding: 1rem 0;
|
||||||
@@ -191,7 +268,6 @@ $tileColor: #181818;
|
|||||||
|
|
||||||
.view-container > div {
|
.view-container > div {
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: auto;
|
|
||||||
|
|
||||||
// border-radius: 0.5em;
|
// border-radius: 0.5em;
|
||||||
}
|
}
|
||||||
@@ -220,7 +296,7 @@ $tileColor: #181818;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.profile-main {
|
.profile-main {
|
||||||
max-height: 2000px;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-header {
|
.main-header {
|
||||||
@@ -255,6 +331,12 @@ $tileColor: #181818;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.history-list-box {
|
||||||
|
overflow: auto;
|
||||||
|
height: 650px;
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
@include responsive.midScreen {
|
@include responsive.midScreen {
|
||||||
.view-container {
|
.view-container {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
|
|||||||
Reference in New Issue
Block a user