chore(profile): player activity section design

This commit is contained in:
2026-02-15 17:13:42 +01:00
parent 87ad7b8ede
commit 83b22e5978
2 changed files with 70 additions and 19 deletions
@@ -48,27 +48,31 @@
</div> </div>
</div> </div>
</div> </div>
</div>
<div class="info-activity" v-if="playerInfo.currentActivity.dispatcher.length > 0"> <!-- Current activity -->
<b class="text--primary">{{ t('profile.stats.online-as-dispatcher') }}</b> <div class="player-activity" v-if="activeDispatches.length > 0 || activeTrains.length > 0">
{{ <h3>{{ t('profile.stats.currently-online') }}</h3>
playerInfo.currentActivity.dispatcher
.map((d) => `${d.stationName} (${d.stationHash})`) <div class="info-activity" v-if="activeDispatches.length > 0">
.join(', ') <router-link
}} v-for="d in activeDispatches"
class="dispatcher-badge"
:to="`/scenery?station=${d.stationName}`"
>
<img src="/images/icon-user.svg" width="25" alt="user icon" />
<b>{{ d.stationName }}</b>
<StationStatusBadge :isOnline="true" :dispatcherStatus="d.dispatcherStatus" />
</router-link>
</div> </div>
<div <div class="info-activity" v-if="activeTrains.length > 0">
class="info-activity" <router-link v-for="d in activeTrains" :to="`/driver?trainId=${d.id}`" class="driver-badge">
v-if="playerInfo.currentActivity.driver && playerInfo.currentActivity.driver.length > 0" <img src="/images/icon-train.svg" width="25" alt="train icon" />
> <span v-if="d.timetable" class="text--primary">{{ d.timetable.category }}</span>
<b>{{ t('profile.stats.online-as-driver') }}</b> <span>{{ d.trainNo }}</span>
{{ playerInfo.currentActivity.driver.trainNo }} {{ t('profile.stats.on-scenery') }} </router-link>
{{ playerInfo.currentActivity.driver.currentStationName }}
</div> </div>
<!-- <p v-if="useMainStore"></p> -->
<!-- <p>Stacjosponsor od 01.01.2024</p> -->
</div> </div>
<div class="player-stats"> <div class="player-stats">
@@ -181,19 +185,22 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { PropType } from 'vue'; import { computed, PropType } from 'vue';
import { API, Td2API } from '../../typings/api'; import { API, Td2API } from '../../typings/api';
import { calculateExpStyles } from '../../composables/badge'; import { calculateExpStyles } from '../../composables/badge';
import { getCountPercentage } from '../../utils/calcUtils'; import { getCountPercentage } from '../../utils/calcUtils';
import { humanizeDuration } from '../../composables/time'; import { humanizeDuration } from '../../composables/time';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useApiStore } from '../../store/apiStore';
import StationStatusBadge from '../Global/StationStatusBadge.vue';
const { t } = useI18n(); const { t } = useI18n();
const route = useRoute(); const route = useRoute();
const apiStore = useApiStore();
defineProps({ const props = defineProps({
playerInfo: { playerInfo: {
type: Object as PropType<API.PlayerInfo.Data>, type: Object as PropType<API.PlayerInfo.Data>,
required: true required: true
@@ -207,6 +214,25 @@ defineProps({
type: String type: String
} }
}); });
const activeDispatches = computed(() => {
if (!props.playerName) return [];
if (!apiStore.activeData || !apiStore.activeData.activeSceneries) return [];
return apiStore.activeData.activeSceneries.filter(
(sc) =>
sc.dispatcherName == props.playerName && (sc.lastSeen >= Date.now() - 60000 || sc.isOnline)
);
});
const activeTrains = computed(() => {
if (!props.playerName) return [];
if (!apiStore.activeData || !apiStore.activeData.trains) return [];
return apiStore.activeData.trains.filter(
(t) => t.driverName == props.playerName && (t.lastSeen >= Date.now() - 60000 || t.online)
);
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@@ -231,6 +257,7 @@ defineProps({
} }
.player-info, .player-info,
.player-activity,
.player-stats > div { .player-stats > div {
background-color: var(--clr-tile); background-color: var(--clr-tile);
border-radius: 0.5em; border-radius: 0.5em;
@@ -261,9 +288,31 @@ defineProps({
} }
.info-activity { .info-activity {
display: flex;
justify-content: center;
align-items: center;
flex-wrap: wrap;
gap: 1em;
margin-top: 1em; margin-top: 1em;
} }
.info-activity > .dispatcher-badge {
display: flex;
align-items: center;
gap: 0.25em;
}
.info-activity > .driver-badge {
display: flex;
align-items: center;
gap: 0.25em;
font-weight: bold;
background-color: #3b3b3b;
padding: 0.25em 0.5em;
border-radius: 0.5em;
}
@include responsive.midScreen { @include responsive.midScreen {
.player-stats { .player-stats {
display: grid; display: grid;
+2
View File
@@ -616,6 +616,8 @@
}, },
"stats": { "stats": {
"currently-online": "OBECNIE ONLINE",
"driver": "MASZYNISTA", "driver": "MASZYNISTA",
"dispatcher": "DYŻURNY RUCHU", "dispatcher": "DYŻURNY RUCHU",
"online-as-driver": "ONLINE JAKO MASZYNISTA", "online-as-driver": "ONLINE JAKO MASZYNISTA",