Client - refacto + display fix and improvements
This commit is contained in:
parent
3d56eb3c93
commit
60a5df70a9
@ -1,20 +1,13 @@
|
||||
<template>
|
||||
<div id="about">
|
||||
<img class="bike-img" v-bind:src="bike_image_url" alt="mountain bike" />
|
||||
<img class="bike-img" :src="'/img/bike.svg'" alt="mountain bike" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
<script>
|
||||
export default {
|
||||
name: 'About',
|
||||
setup() {
|
||||
return {
|
||||
bike_image_url: './img/bike.svg',
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
@ -15,9 +15,7 @@
|
||||
},
|
||||
setup() {
|
||||
const { t } = useI18n()
|
||||
return {
|
||||
t,
|
||||
}
|
||||
return { t }
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
@ -16,7 +16,7 @@
|
||||
props: {
|
||||
withoutTitle: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="dropdown-wrapper">
|
||||
<div class="dropdown-selected" @click="openDropdown">
|
||||
<div class="dropdown-selected" @click="toggleDropdown">
|
||||
<slot></slot>
|
||||
</div>
|
||||
<ul class="dropdown-list" v-if="isOpen">
|
||||
@ -41,25 +41,19 @@
|
||||
let isOpen = ref(false)
|
||||
let dropdownOptions = props.options.map((option) => option)
|
||||
|
||||
function openDropdown() {
|
||||
isOpen.value = true
|
||||
function toggleDropdown() {
|
||||
isOpen.value = !isOpen.value
|
||||
}
|
||||
function updateSelected(option: IDropdownOption) {
|
||||
emit('selected', option)
|
||||
isOpen.value = false
|
||||
}
|
||||
function getSelectedLabel(selectedValue: string) {
|
||||
return props.options.filter(
|
||||
(option: IDropdownOption) => option.value === selectedValue
|
||||
)[0].label
|
||||
}
|
||||
|
||||
return {
|
||||
dropdownOptions,
|
||||
updateSelected,
|
||||
getSelectedLabel,
|
||||
isOpen,
|
||||
openDropdown,
|
||||
toggleDropdown,
|
||||
updateSelected,
|
||||
}
|
||||
},
|
||||
})
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div id="error404">
|
||||
<div id="error">
|
||||
<div class="error-content">
|
||||
<h1>{{ title }}</h1>
|
||||
<p>{{ message }}</p>
|
||||
@ -37,7 +37,7 @@
|
||||
<style scoped lang="scss">
|
||||
@import '~@/scss/base';
|
||||
|
||||
#error404 {
|
||||
#error {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div class="error-message">
|
||||
<ul v-if="Array.isArray(message)">
|
||||
<li v-for="(submessage, index) in message" :key="index">
|
||||
{{ t(submessage) }}
|
||||
<li v-for="(subMessage, index) in message" :key="index">
|
||||
{{ t(subMessage) }}
|
||||
</li>
|
||||
</ul>
|
||||
<div v-else>{{ t(message) }}</div>
|
||||
@ -20,9 +20,7 @@
|
||||
},
|
||||
setup() {
|
||||
const { t } = useI18n()
|
||||
return {
|
||||
t,
|
||||
}
|
||||
return { t }
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div id="modal">
|
||||
<div class="custom-modal">
|
||||
<Card :without-title="false">
|
||||
<Card>
|
||||
<template #title>
|
||||
{{ title }}
|
||||
</template>
|
||||
@ -79,6 +79,15 @@
|
||||
margin: 25% auto;
|
||||
z-index: 1250;
|
||||
|
||||
@media screen and (max-width: $medium-limit) {
|
||||
margin: 15% auto;
|
||||
width: 100%;
|
||||
}
|
||||
@media screen and (max-width: $small-limit) {
|
||||
margin: 50% 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
::v-deep(.card) {
|
||||
border: 0;
|
||||
margin: 0;
|
||||
@ -102,12 +111,5 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $small-limit) {
|
||||
.custom-modal {
|
||||
margin: 50% 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -13,7 +13,7 @@
|
||||
import Error from '@/components/Common/Error.vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'NotFoundView',
|
||||
name: 'NotFound',
|
||||
components: {
|
||||
Error,
|
||||
},
|
||||
|
@ -17,12 +17,12 @@
|
||||
import { defineComponent } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import CyclingSport from '@/components/Common/Sports/CyclingSport.vue'
|
||||
import CyclingTransport from '@/components/Common/Sports/CyclingTransport.vue'
|
||||
import Hiking from '@/components/Common/Sports/Hiking.vue'
|
||||
import MountainBiking from '@/components/Common/Sports/MountainBiking.vue'
|
||||
import Running from '@/components/Common/Sports/Running.vue'
|
||||
import Walking from '@/components/Common/Sports/Walking.vue'
|
||||
import CyclingSport from '@/components/Common/SportImage/CyclingSport.vue'
|
||||
import CyclingTransport from '@/components/Common/SportImage/CyclingTransport.vue'
|
||||
import Hiking from '@/components/Common/SportImage/Hiking.vue'
|
||||
import MountainBiking from '@/components/Common/SportImage/MountainBiking.vue'
|
||||
import Running from '@/components/Common/SportImage/Running.vue'
|
||||
import Walking from '@/components/Common/SportImage/Walking.vue'
|
||||
import { sportColors } from '@/utils/sports'
|
||||
|
||||
export default defineComponent({
|
@ -10,7 +10,7 @@
|
||||
<span class="map-attribution-text">©</span>
|
||||
<a
|
||||
class="map-attribution-text"
|
||||
href="http://www.openstreetmap.org/copyright"
|
||||
href="https://www.openstreetmap.org/copyright"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
|
@ -35,11 +35,11 @@
|
||||
},
|
||||
setup(props) {
|
||||
const { t } = useI18n()
|
||||
// eslint-disable-next-line
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function getNumber(value: any): number {
|
||||
return isNaN(value) ? 0 : +value
|
||||
}
|
||||
// eslint-disable-next-line
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function getSum(total: any, value: any): number {
|
||||
return getNumber(total) + getNumber(value)
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="timeline-workout">
|
||||
<Card>
|
||||
<Card :without-title="true">
|
||||
<template #content>
|
||||
<div class="workout-user-date">
|
||||
<div class="workout-user">
|
||||
@ -83,7 +83,7 @@
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import Card from '@/components/Common/Card.vue'
|
||||
import SportImage from '@/components/Common/Sports/SportImage.vue'
|
||||
import SportImage from '@/components/Common/SportImage/index.vue'
|
||||
import StaticMap from '@/components/Common/StaticMap.vue'
|
||||
import { ROOT_STORE } from '@/store/constants'
|
||||
import { ISport } from '@/types/sports'
|
||||
|
@ -1,24 +1,33 @@
|
||||
<template>
|
||||
<div id="timeline">
|
||||
<div class="section-title">{{ t('workouts.LATEST_WORKOUTS') }}</div>
|
||||
<WorkoutCard
|
||||
v-for="workout in workouts"
|
||||
:workout="workout"
|
||||
:sport="
|
||||
workouts.length > 0
|
||||
? sports.filter((s) => s.id === workout.sport_id)[0]
|
||||
: null
|
||||
"
|
||||
:user="user"
|
||||
:key="workout.id"
|
||||
/>
|
||||
<div v-if="workouts.length === 0" class="no-workouts">
|
||||
{{ t('workouts.NO_WORKOUTS') }}
|
||||
<div v-if="user.nb_workouts > 0 && workouts.length === 0">
|
||||
<WorkoutCard
|
||||
v-for="index in [...Array(initWorkoutsCount).keys()]"
|
||||
:user="user"
|
||||
:key="index"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="moreWorkoutsExist" class="more-workouts">
|
||||
<button @click="loadMoreWorkouts">
|
||||
{{ t('workouts.LOAD_MORE_WORKOUT') }}
|
||||
</button>
|
||||
<div v-else>
|
||||
<WorkoutCard
|
||||
v-for="workout in workouts"
|
||||
:workout="workout"
|
||||
:sport="
|
||||
workouts.length > 0
|
||||
? sports.filter((s) => s.id === workout.sport_id)[0]
|
||||
: null
|
||||
"
|
||||
:user="user"
|
||||
:key="workout.id"
|
||||
/>
|
||||
<div v-if="workouts.length === 0" class="no-workouts">
|
||||
{{ t('workouts.NO_WORKOUTS') }}
|
||||
</div>
|
||||
<div v-if="moreWorkoutsExist" class="more-workouts">
|
||||
<button @click="loadMoreWorkouts">
|
||||
{{ t('workouts.LOAD_MORE_WORKOUT') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -56,12 +65,14 @@
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
setup(props) {
|
||||
const store = useStore()
|
||||
const { t } = useI18n()
|
||||
|
||||
let page = ref(1)
|
||||
const per_page = 5
|
||||
const initWorkoutsCount =
|
||||
props.user.nb_workouts >= per_page ? per_page : props.user.nb_workouts
|
||||
onBeforeMount(() => loadWorkouts())
|
||||
|
||||
const workouts: ComputedRef<IWorkout[]> = computed(
|
||||
@ -85,6 +96,7 @@
|
||||
}
|
||||
|
||||
return {
|
||||
initWorkoutsCount,
|
||||
moreWorkoutsExist,
|
||||
per_page,
|
||||
workouts,
|
||||
|
@ -23,6 +23,7 @@
|
||||
<script lang="ts">
|
||||
import { format } from 'date-fns'
|
||||
import { defineComponent } from 'vue'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'CalendarHeader',
|
||||
props: {
|
||||
|
@ -25,11 +25,11 @@
|
||||
import { defineComponent, PropType } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import SportImage from '@/components/Common/Sports/SportImage.vue'
|
||||
import SportImage from '@/components/Common/SportImage/index.vue'
|
||||
import { IWorkout } from '@/types/workouts'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'CalendarWorkouts',
|
||||
name: 'CalendarWorkout',
|
||||
components: {
|
||||
SportImage,
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div id="user-calendar">
|
||||
<Card class="calendar-card">
|
||||
<Card class="calendar-card" :without-title="true">
|
||||
<template #content>
|
||||
<CalendarHeader
|
||||
:day="day"
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="user-month-stats">
|
||||
<Card :without-title="false">
|
||||
<Card>
|
||||
<template #title>{{ $t('dashboard.THIS_MONTH') }}</template>
|
||||
<template #content>
|
||||
<div v-if="Object.keys(statistics).length === 0">
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="records-card">
|
||||
<Card :without-title="false">
|
||||
<Card>
|
||||
<template #title>
|
||||
<SportImage :sport-label="records.label" />
|
||||
{{ sportTranslatedLabel }}
|
||||
@ -31,7 +31,7 @@
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import Card from '@/components/Common/Card.vue'
|
||||
import SportImage from '@/components/Common/Sports/SportImage.vue'
|
||||
import SportImage from '@/components/Common/SportImage/index.vue'
|
||||
import { IRecord } from '@/types/workouts'
|
||||
|
||||
export default defineComponent({
|
||||
@ -93,7 +93,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: $small-limit) {
|
||||
@media screen and (max-width: $medium-limit) {
|
||||
font-size: 1em;
|
||||
.card-title {
|
||||
font-size: 1em;
|
||||
|
@ -52,10 +52,7 @@
|
||||
props.user.timezone
|
||||
)
|
||||
)
|
||||
return {
|
||||
recordsBySport,
|
||||
t,
|
||||
}
|
||||
return { recordsBySport, t }
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="user-stat-card">
|
||||
<Card>
|
||||
<Card :without-title="true">
|
||||
<template #content>
|
||||
<div class="stat-content">
|
||||
<div class="stat-icon">
|
||||
|
@ -7,6 +7,10 @@
|
||||
disabled: registration_disabled,
|
||||
}"
|
||||
>
|
||||
<AlertMessage
|
||||
message="user.REGISTER_DISABLED"
|
||||
v-if="registration_disabled"
|
||||
/>
|
||||
<form @submit.prevent="onSubmit(action)">
|
||||
<div class="form-items">
|
||||
<input
|
||||
@ -48,10 +52,6 @@
|
||||
</button>
|
||||
</form>
|
||||
<ErrorMessage :message="errorMessages" v-if="errorMessages" />
|
||||
<AlertMessage
|
||||
message="user.REGISTER_DISABLED"
|
||||
v-if="registration_disabled"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -133,9 +133,9 @@
|
||||
buttonText,
|
||||
errorMessages,
|
||||
formData,
|
||||
onSubmit,
|
||||
registration_disabled,
|
||||
router,
|
||||
onSubmit,
|
||||
}
|
||||
},
|
||||
})
|
||||
@ -162,15 +162,16 @@
|
||||
border-color: var(--disabled-color);
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: $medium-limit) {
|
||||
margin-top: $default-margin;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $medium-limit) {
|
||||
height: auto;
|
||||
margin-bottom: 50px;
|
||||
|
||||
#user-form {
|
||||
margin-top: $default-margin;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div id="workout-chart">
|
||||
<Card :without-title="false">
|
||||
<Card>
|
||||
<template #title>{{ t('workouts.ANALYSIS') }} </template>
|
||||
<template #content>
|
||||
<div class="chart-radio">
|
||||
|
@ -84,7 +84,7 @@
|
||||
import { PropType, defineComponent } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import SportImage from '@/components/Common/Sports/SportImage.vue'
|
||||
import SportImage from '@/components/Common/SportImage/index.vue'
|
||||
import { ISport } from '@/types/sports'
|
||||
import { IWorkoutObject } from '@/types/workouts'
|
||||
|
||||
|
@ -28,7 +28,11 @@
|
||||
class="workout-data"
|
||||
v-if="workoutObject.maxAlt !== null && workoutObject.minAlt !== null"
|
||||
>
|
||||
<img class="mountains" src="/img/workouts/mountains.svg" />
|
||||
<img
|
||||
class="mountains"
|
||||
src="/img/workouts/mountains.svg"
|
||||
:alt="t('workouts.ELEVATION')"
|
||||
/>
|
||||
{{ t('workouts.MIN_ALTITUDE') }}: <span>{{ workoutObject.minAlt }} m</span
|
||||
><br />
|
||||
{{ t('workouts.MAX_ALTITUDE') }}:
|
||||
|
@ -5,7 +5,7 @@
|
||||
<div class="leaflet-container" v-if="workoutData.workout.with_gpx">
|
||||
<LMap
|
||||
v-if="geoJson.jsonData && center && bounds.length === 2"
|
||||
:zoom="options.zoom"
|
||||
:zoom="13"
|
||||
:center="center"
|
||||
:bounds="bounds"
|
||||
ref="workoutMap"
|
||||
@ -108,17 +108,18 @@
|
||||
const appConfig: ComputedRef<IAppConfig> = computed(
|
||||
() => store.getters[ROOT_STORE.GETTERS.APP_CONFIG]
|
||||
)
|
||||
const center = computed(() => getCenter(bounds))
|
||||
const geoJson = computed(() =>
|
||||
props.workoutData && props.workoutData.gpx
|
||||
? getGeoJson(props.workoutData.gpx)
|
||||
: {}
|
||||
)
|
||||
|
||||
return {
|
||||
appConfig,
|
||||
bounds: bounds,
|
||||
center: computed(() => getCenter(bounds)),
|
||||
geoJson: computed(() =>
|
||||
props.workoutData && props.workoutData.gpx
|
||||
? getGeoJson(props.workoutData.gpx)
|
||||
: {}
|
||||
),
|
||||
options: { zoom: 13 },
|
||||
bounds,
|
||||
center,
|
||||
geoJson,
|
||||
t,
|
||||
workoutMap,
|
||||
fitBounds,
|
||||
|
@ -7,7 +7,7 @@
|
||||
@confirmAction="deleteWorkout(workoutObject.workoutId)"
|
||||
@cancelAction="updateDisplayModal(false)"
|
||||
/>
|
||||
<Card :without-title="false">
|
||||
<Card>
|
||||
<template #title>
|
||||
<WorkoutCardTitle
|
||||
:sport="sport"
|
||||
@ -213,7 +213,7 @@
|
||||
.card-content {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@media screen and (max-width: $small-limit) {
|
||||
@media screen and (max-width: $medium-limit) {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
<template>
|
||||
<div id="workout-edition">
|
||||
<Card :without-title="false">
|
||||
<div
|
||||
id="workout-edition"
|
||||
:class="{ 'center-form': workout && workout.with_gpx }"
|
||||
>
|
||||
<Card>
|
||||
<template #title>{{
|
||||
t(`workouts.${isCreation ? 'ADD' : 'EDIT'}_WORKOUT`)
|
||||
}}</template>
|
||||
@ -424,10 +427,15 @@
|
||||
#workout-edition {
|
||||
margin: 100px auto;
|
||||
width: 700px;
|
||||
@media screen and (max-width: $small-limit) {
|
||||
@media screen and (max-width: $medium-limit) {
|
||||
width: 100%;
|
||||
margin: 0 auto 50px auto;
|
||||
}
|
||||
@media screen and (max-width: $small-limit) {
|
||||
&.center-form {
|
||||
margin: 50px auto;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep(.card) {
|
||||
.card-title {
|
||||
@ -436,7 +444,7 @@
|
||||
}
|
||||
|
||||
.card-content {
|
||||
@media screen and (max-width: $small-limit) {
|
||||
@media screen and (max-width: $medium-limit) {
|
||||
padding: $default-padding 0;
|
||||
}
|
||||
|
||||
@ -454,7 +462,7 @@
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
|
||||
@media screen and (max-width: $small-limit) {
|
||||
@media screen and (max-width: $medium-limit) {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
@ -481,7 +489,7 @@
|
||||
justify-content: space-around;
|
||||
label {
|
||||
font-weight: normal;
|
||||
@media screen and (max-width: $small-limit) {
|
||||
@media screen and (max-width: $medium-limit) {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
}
|
||||
@ -513,7 +521,7 @@
|
||||
padding: $default-padding;
|
||||
div {
|
||||
display: flex;
|
||||
@media screen and (max-width: $small-limit) {
|
||||
@media screen and (max-width: $medium-limit) {
|
||||
flex-direction: column;
|
||||
}
|
||||
ul {
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div id="workout-note">
|
||||
<Card :without-title="false">
|
||||
<Card>
|
||||
<template #title>{{ t('workouts.NOTES') }}</template>
|
||||
<template #content>
|
||||
{{ notes && notes !== '' ? notes : t('workouts.NO_NOTES') }}</template
|
||||
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div id="workout-segments">
|
||||
<Card :without-title="false">
|
||||
<Card>
|
||||
<template #title>{{ t('workouts.SEGMENT', 2) }}</template>
|
||||
<template #content>
|
||||
<ul>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div id="dashboard" v-if="authUser.username && sports.length > 0">
|
||||
<div class="container mobile-menu">
|
||||
<Card>
|
||||
<Card :without-title="true">
|
||||
<template #content>
|
||||
<button
|
||||
class="mobile-menu-item"
|
||||
@ -145,7 +145,7 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media screen and (max-width: $small-limit) {
|
||||
@media screen and (max-width: $medium-limit) {
|
||||
padding-bottom: 60px;
|
||||
.dashboard-container {
|
||||
display: flex;
|
||||
|
@ -66,7 +66,3 @@
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '~@/scss/base';
|
||||
</style>
|
||||
|
@ -36,28 +36,36 @@
|
||||
@import '~@/scss/base';
|
||||
|
||||
#loginOrRegister {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-evenly;
|
||||
|
||||
height: 100%;
|
||||
margin-bottom: $default-margin * 2;
|
||||
width: 100%;
|
||||
|
||||
.container-sub {
|
||||
min-width: 50%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@media screen and (max-width: $medium-limit) {
|
||||
display: block;
|
||||
}
|
||||
@media screen and (max-width: $medium-limit) {
|
||||
height: auto;
|
||||
.container {
|
||||
.container-sub {
|
||||
align-items: center;
|
||||
.bike-img {
|
||||
margin-top: $default-margin * 1.5;
|
||||
max-width: 60%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: $small-limit) {
|
||||
.container {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
Loading…
Reference in New Issue
Block a user