mirror of
https://github.com/Spythere/stacjownik.git
synced 2026-05-03 05:18:11 +00:00
chore(profile): journal history list design
This commit is contained in:
@@ -0,0 +1,31 @@
|
|||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
|
||||||
|
export function calculateDuration(timestampMs: number) {
|
||||||
|
const secondsTotal = Math.floor(timestampMs / 1000);
|
||||||
|
const minsTotal = Math.round(timestampMs / 60000);
|
||||||
|
const hoursTotal = Math.floor(minsTotal / 60);
|
||||||
|
const minsInHour = minsTotal % 60;
|
||||||
|
|
||||||
|
return {
|
||||||
|
secondsTotal,
|
||||||
|
minsTotal,
|
||||||
|
hoursTotal,
|
||||||
|
minsInHour
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function humanizeDuration(timestampMs: number, showSeconds = false) {
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const duration = calculateDuration(timestampMs);
|
||||||
|
|
||||||
|
return duration.minsTotal >= 60
|
||||||
|
? `${t('journal.hours', { value: duration.hoursTotal }, duration.hoursTotal)} ${t(
|
||||||
|
'journal.minutes',
|
||||||
|
{ value: duration.minsInHour },
|
||||||
|
duration.minsInHour
|
||||||
|
)}`
|
||||||
|
: showSeconds && duration.secondsTotal <= 60
|
||||||
|
? t('journal.seconds', { value: duration.secondsTotal }, duration.secondsTotal)
|
||||||
|
: t('journal.minutes', { value: duration.minsTotal }, duration.minsTotal);
|
||||||
|
}
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="stats-dispatcher">
|
<div class="stats-dispatcher">
|
||||||
<img src="/images/icon-user.svg" width="35" alt="clock icon" />
|
<img src="/images/icon-user.svg" width="35" alt="user icon" />
|
||||||
<h3>STATYSTYKI DYŻURNEGO RUCHU</h3>
|
<h3>STATYSTYKI DYŻURNEGO RUCHU</h3>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="month-stat">
|
<div class="month-stat">
|
||||||
<div><img src="/images/icon-spawn.svg" width="30" alt="train icon" /></div>
|
<div><img src="/images/icon-spawn.svg" width="30" alt="spawn icon" /></div>
|
||||||
<div><h3 class="text--primary">5500</h3></div>
|
<div><h3 class="text--primary">5500</h3></div>
|
||||||
<div>
|
<div>
|
||||||
POKONANYCH <br />
|
POKONANYCH <br />
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="month-stat">
|
<div class="month-stat">
|
||||||
<div><img src="/images/icon-user.svg" width="30" alt="train icon" /></div>
|
<div><img src="/images/icon-user.svg" width="30" alt="user icon" /></div>
|
||||||
<div><h3 class="text--primary">15</h3></div>
|
<div><h3 class="text--primary">15</h3></div>
|
||||||
<div>
|
<div>
|
||||||
SŁUŻB <br />
|
SŁUŻB <br />
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="month-stat">
|
<div class="month-stat">
|
||||||
<div><img src="/images/icon-timetable.svg" width="30" alt="train icon" /></div>
|
<div><img src="/images/icon-timetable.svg" width="30" alt="timetable icon" /></div>
|
||||||
<div><h3 class="text--primary">12</h3></div>
|
<div><h3 class="text--primary">12</h3></div>
|
||||||
<div>
|
<div>
|
||||||
WYSTAWIONYCH <br />
|
WYSTAWIONYCH <br />
|
||||||
@@ -104,7 +104,54 @@
|
|||||||
|
|
||||||
<div class="history-list-box">
|
<div class="history-list-box">
|
||||||
<ul>
|
<ul>
|
||||||
<li v-for="entry in combinedJournal">{{ entry.type }} - {{ entry.date }}</li>
|
<li v-for="entry in combinedJournal">
|
||||||
|
<img
|
||||||
|
v-if="entry.type == 'Dispatcher'"
|
||||||
|
src="/images/icon-user.svg"
|
||||||
|
width="20"
|
||||||
|
alt="user icon"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<img
|
||||||
|
v-else-if="entry.type == 'Timetable'"
|
||||||
|
src="/images/icon-train.svg"
|
||||||
|
width="20"
|
||||||
|
alt="train icon"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<img v-else src="/images/icon-timetable.svg" width="20" alt="timetable icon" />
|
||||||
|
|
||||||
|
<b class="text--grayed">
|
||||||
|
{{
|
||||||
|
entry.date.toLocaleString('pl-PL', { dateStyle: 'long', timeStyle: 'short' })
|
||||||
|
}}
|
||||||
|
</b>
|
||||||
|
|
||||||
|
<!-- Timetables -->
|
||||||
|
<span v-if="'trainNo' in entry.value">
|
||||||
|
<b class="text--primary">
|
||||||
|
{{ entry.value.trainCategoryCode }} {{ entry.value.trainNo }}
|
||||||
|
</b>
|
||||||
|
<b class="text--grayed" v-if="entry.type == 'IssuedTimetable'">
|
||||||
|
dla: {{ entry.value.driverName }}
|
||||||
|
</b>
|
||||||
|
{{ ' ' }}
|
||||||
|
<b>{{ entry.value.route.replace('|', ' > ') }}</b>
|
||||||
|
{{ ' ' }}
|
||||||
|
<b>({{ entry.value.currentDistance }} / {{ entry.value.routeDistance }}km) </b>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<!-- Dispatchers -->
|
||||||
|
<span v-else>
|
||||||
|
<b>{{ entry.value.stationName }}</b>
|
||||||
|
{{ ' - ' }}
|
||||||
|
<b>{{
|
||||||
|
humanizeDuration(
|
||||||
|
(entry.value.timestampTo || Date.now()) - entry.value.timestampFrom
|
||||||
|
)
|
||||||
|
}}</b>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -117,6 +164,8 @@ 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';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { humanizeDuration } from '../composables/time';
|
||||||
|
|
||||||
type JournalEntryType = 'Timetable' | 'Dispatcher' | 'IssuedTimetable';
|
type JournalEntryType = 'Timetable' | 'Dispatcher' | 'IssuedTimetable';
|
||||||
|
|
||||||
@@ -128,6 +177,7 @@ interface JournalEntry {
|
|||||||
|
|
||||||
const apiStore = useApiStore();
|
const apiStore = useApiStore();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
const playerName = ref('');
|
const playerName = ref('');
|
||||||
const playerInfo = ref<API.PlayerInfo.Data | null>(null);
|
const playerInfo = ref<API.PlayerInfo.Data | null>(null);
|
||||||
@@ -210,7 +260,8 @@ async function fetchPlayerJournal() {
|
|||||||
try {
|
try {
|
||||||
const response = await apiStore.client.get<API.PlayerJournal.Data>('api/getPlayerJournal', {
|
const response = await apiStore.client.get<API.PlayerJournal.Data>('api/getPlayerJournal', {
|
||||||
params: {
|
params: {
|
||||||
playerId: playerId
|
playerId: playerId,
|
||||||
|
countLimit: 15
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -335,6 +386,18 @@ $tileColor: #181818;
|
|||||||
overflow: auto;
|
overflow: auto;
|
||||||
height: 650px;
|
height: 650px;
|
||||||
margin-top: 1em;
|
margin-top: 1em;
|
||||||
|
|
||||||
|
& > ul > li {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.25em;
|
||||||
|
|
||||||
|
background-color: $tileColor;
|
||||||
|
padding: 0.5em;
|
||||||
|
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
text-align: initial;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@include responsive.midScreen {
|
@include responsive.midScreen {
|
||||||
|
|||||||
Reference in New Issue
Block a user