Client - add Sport administration

This commit is contained in:
Sam
2021-10-27 18:51:59 +02:00
parent 95dec79814
commit e4434acc94
14 changed files with 342 additions and 113 deletions

View File

@ -23,7 +23,11 @@
}}
</span>
</dd>
<dt>{{ capitalize($t('workouts.SPORT', 0)) }}</dt>
<dt>
<router-link to="/admin/SPORTS">
{{ capitalize($t('workouts.SPORT', 0)) }}
</router-link>
</dt>
<dd>
{{ $t('admin.ENABLE_DISABLE_SPORTS') }}
</dd>

View File

@ -0,0 +1,171 @@
<template>
<div id="admin-sports" class="admin-card">
<Card>
<template #title>{{ $t('admin.SPORTS.TITLE') }}</template>
<template #content>
<button class="top-button" @click.prevent="$router.push('/admin')">
{{ $t('admin.BACK_TO_ADMIN') }}
</button>
<div class="responsive-table">
<table>
<thead>
<tr>
<th>#</th>
<th>{{ $t('admin.SPORTS.TABLE.IMAGE') }}</th>
<th class="text-left">
{{ $t('admin.SPORTS.TABLE.LABEL') }}
</th>
<th>{{ $t('admin.SPORTS.TABLE.ACTIVE') }}</th>
<th class="text-left sport-action">
{{ $t('admin.SPORTS.TABLE.ACTION') }}
</th>
<th />
</tr>
</thead>
<tbody>
<tr v-for="sport in translatedSports" :key="sport.id">
<td class="center-text">
<span class="cell-heading">id</span>
{{ sport.id }}
</td>
<td>
<span class="cell-heading">
{{ $t('admin.SPORTS.TABLE.IMAGE') }}
</span>
<SportImage
:title="sport.translatedLabel"
:sport-label="sport.label"
/>
</td>
<td class="sport-label">
<span class="cell-heading">
{{ $t('admin.SPORTS.TABLE.LABEL') }}
</span>
{{ sport.translatedLabel }}
</td>
<td class="center-text">
<span class="cell-heading">
{{ $t('admin.SPORTS.TABLE.ACTIVE') }}
</span>
<i
:class="`fa fa${sport.is_active ? '-check' : ''}-square-o`"
aria-hidden="true"
/>
</td>
<td class="sport-action">
<span class="cell-heading">
{{ $t('admin.SPORTS.TABLE.ACTION') }}
</span>
<div class="action-button">
<button
:class="{ danger: sport.is_active }"
@click="updateSportStatus(sport.id, !sport.is_active)"
>
{{ $t(`buttons.${sport.is_active ? 'DIS' : 'EN'}ABLE`) }}
</button>
<span v-if="sport.has_workouts" class="has-workouts">
<i class="fa fa-warning" aria-hidden="true" />
{{ $t('admin.SPORTS.TABLE.HAS_WORKOUTS') }}
</span>
</div>
</td>
</tr>
</tbody>
</table>
<ErrorMessage :message="errorMessages" v-if="errorMessages" />
<button @click.prevent="$router.push('/admin')">
{{ $t('admin.BACK_TO_ADMIN') }}
</button>
</div>
</template>
</Card>
</div>
</template>
<script lang="ts">
import { ComputedRef, computed, defineComponent } from 'vue'
import { useI18n } from 'vue-i18n'
import { ROOT_STORE, SPORTS_STORE } from '@/store/constants'
import { ITranslatedSport } from '@/types/sports'
import { useStore } from '@/use/useStore'
import { translateSports } from '@/utils/sports'
export default defineComponent({
name: 'AdminSports',
setup() {
const { t } = useI18n()
const store = useStore()
const translatedSports: ComputedRef<ITranslatedSport[]> = computed(() =>
translateSports(store.getters[SPORTS_STORE.GETTERS.SPORTS], t)
)
const errorMessages: ComputedRef<string | string[] | null> = computed(
() => store.getters[ROOT_STORE.GETTERS.ERROR_MESSAGES]
)
function updateSportStatus(id: number, isActive: boolean) {
store.dispatch(SPORTS_STORE.ACTIONS.UPDATE_SPORTS, {
id,
isActive,
})
}
return { errorMessages, translatedSports, updateSportStatus }
},
})
</script>
<style lang="scss" scoped>
@import '~@/scss/base.scss';
#admin-sports {
table {
td {
font-size: 1.1em;
}
}
.center-text {
text-align: center;
}
.sport-img {
height: 35px;
width: 35px;
margin: 0 auto;
}
.has-workouts {
font-size: 0.95em;
font-style: italic;
padding: 0 $default-padding;
}
.text-left {
text-align: left;
}
.sport-action {
padding-left: $default-padding * 4;
}
.action-button {
display: block;
}
.top-button {
display: none;
}
@media screen and (max-width: $small-limit) {
.sport-action {
padding-left: $default-padding;
}
.has-workouts {
padding-top: $default-padding * 0.5;
}
.action-button {
display: flex;
align-items: center;
flex-wrap: wrap;
flex-direction: column;
}
.top-button {
display: block;
margin-bottom: $default-margin * 2;
}
}
}
</style>

View File

@ -1,7 +1,7 @@
<template>
<div class="workouts-list">
<div class="box" :class="{ 'empty-table': workouts.length === 0 }">
<div class="workouts-table">
<div class="workouts-table responsive-table">
<table>
<thead>
<tr>
@ -210,122 +210,35 @@
}
}
.workouts-table {
margin-bottom: 15px;
/* responsive table, adapted from: */
/* https://uglyduck.ca/making-tables-responsive-with-minimal-css/ */
table {
width: 100%;
padding: $default-padding;
font-size: 0.9em;
border-collapse: collapse;
thead th {
vertical-align: center;
padding: $default-padding;
border-bottom: 2px solid var(--card-border-color);
.sport-col {
padding-right: 0;
}
.workout-title {
max-width: 90px;
position: relative;
.fa-map-o {
font-size: 0.75em;
}
tbody {
font-size: 0.95em;
td {
padding: $default-padding;
border-bottom: 1px solid var(--card-border-color);
}
tr:last-child td {
border: none;
}
}
.sport-col {
padding-right: 0;
}
.workout-title {
max-width: 90px;
position: relative;
.fa-map-o {
font-size: 0.75em;
}
.static-map {
display: none;
box-shadow: 3px 3px 3px 1px lightgrey;
}
}
.workout-title:hover .static-map {
display: block;
}
.cell-heading {
background: var(--cell-heading-bg-color);
color: var(--cell-heading-color);
.static-map {
display: none;
font-size: 10px;
font-weight: bold;
padding: 5px;
position: absolute;
text-transform: uppercase;
top: 0;
left: 0;
}
.sport-img {
height: 20px;
width: 20px;
box-shadow: 3px 3px 3px 1px lightgrey;
}
}
.workout-title:hover .static-map {
display: block;
}
.sport-img {
height: 20px;
width: 20px;
}
@media screen and (max-width: $small-limit) {
table {
thead {
left: -9999px;
position: absolute;
visibility: hidden;
}
tr {
border-bottom: 0;
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin-bottom: 40px;
}
td {
border: 1px solid var(--card-border-color);
margin: 0 -1px -1px 0;
padding-top: 25px !important;
position: relative;
text-align: center;
width: 45%;
}
tbody {
tr:last-child td {
border: 1px solid var(--card-border-color);
}
}
.sport-col {
display: flex;
justify-content: center;
padding: $default-padding;
}
.cell-heading {
display: flex;
}
.workout-title {
max-width: initial;
}
.sport-col {
display: flex;
justify-content: center;
padding: $default-padding;
}
}
@media screen and (max-width: $x-small-limit) {
table {
td {
width: 100%;
}
.workout-title {
max-width: initial;
}
}
}