Files
geovisio-website/src/components/sequence/PanelOrientationManagement.vue
2024-05-02 12:03:05 +00:00

161 lines
4.3 KiB
Vue

<template>
<div class="wrapper-orientation">
<h2 class="orientation-title">
{{ $t('pages.sequence.orientation_panel_title') }}
</h2>
<div class="entry-information-card">
<InformationCard>
<template v-slot:title>
<h3 class="subtitle">
{{ $t('pages.sequence.orientation_panel_tooltip') }}
</h3>
</template>
</InformationCard>
<div class="wrapper-input-angle">
<label for="inputAngle" name="inputAngle">{{
$t('pages.sequence.orientation_input_label')
}}</label>
<Input
id="inputAngle"
name="inputAngle"
type="number"
min="-180"
max="180"
:text="Number(angleInputValue)"
:placeholder="$t('pages.sequence.orientation_input_placeholder')"
@input="captureAngle"
/>
<span v-if="errorAngleValue" class="errorValue">{{
$t('pages.sequence.orientation_input_error_value')
}}</span>
</div>
</div>
<div class="entry-compass">
<WidgetOrientation
:road-degrees="roadDegrees"
:seq-brute-deg="angleValue"
@triggerAngle="captureAngle"
@triggerMovingAngle="triggerMovingAngle"
/>
</div>
<div class="entry-button">
<Button
look="button--blue"
:text="$t('pages.sequence.orientation_panel_button')"
:disabled="isDisabled(Number(angleInputValue)) || isLoading"
@trigger="triggerAngle"
/>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, watchEffect, onMounted, onUnmounted } from 'vue'
import InformationCard from '@/components/InformationCard.vue'
import Button from '@/components/Button.vue'
import Input from '@/components/Input.vue'
import WidgetOrientation from '@/components/sequence/WidgetOrientation.vue'
import { modulo180 } from '@/utils/calc'
const emit = defineEmits<{
(e: 'triggerAngle', value: number): void
(e: 'triggerMovingAngle', value: number): void
}>()
let angleValue = ref<number>(0)
let angleInputValue = ref<number>(0)
let errorAngleValue = ref<boolean>(false)
const props = defineProps({
roadDegrees: { type: Number, default: 0 },
seqBruteDeg: { type: Number, default: 0 },
isLoading: { type: Boolean, default: false }
})
onMounted(() => {
triggerMovingAngle(angleInputValue.value)
})
onUnmounted(() => {
triggerMovingAngle(angleInputValue.value)
})
watchEffect(() => {
angleValue.value = props.seqBruteDeg
angleInputValue.value = Math.round(props.seqBruteDeg - props.roadDegrees)
})
function isDisabled(value: number): boolean {
return value < -180 || value > 180
}
function captureAngle(value: number | string) {
errorAngleValue.value = false
const valueNum = Number(value)
angleInputValue.value = valueNum
angleValue.value = valueNum + props.roadDegrees
const movingAngle = modulo180(angleValue.value, Math.round(props.roadDegrees))
emit('triggerMovingAngle', movingAngle)
if (isDisabled(valueNum)) return (errorAngleValue.value = true)
}
function triggerMovingAngle(value: number) {
emit('triggerMovingAngle', value)
}
function triggerAngle() {
const valueToSend = angleValue.value - Number(props.roadDegrees)
if (isDisabled(valueToSend)) return
emit('triggerAngle', valueToSend)
}
</script>
<style scoped lang="scss">
.wrapper-orientation {
background-color: var(--blue-semi-pale);
}
.orientation-title {
@include text(h4);
margin-bottom: toRem(2);
}
.subtitle {
@include text(m-r-regular);
color: var(--blue-dark);
margin-bottom: 0;
}
.entry-compass {
width: 100%;
margin-bottom: toRem(2);
}
.entry-information-card {
margin-top: toRem(2);
margin-bottom: toRem(2.5);
display: flex;
}
.wrapper-input-angle {
margin-left: toRem(1);
width: 45%;
background-color: var(--white);
padding: toRem(1);
border-radius: toRem(1);
}
.entry-button {
width: 100%;
display: flex;
justify-content: center;
}
.errorValue {
color: var(--red);
@include text(xs-r-regular);
text-align: center;
}
@media (max-width: toRem(102.4)) {
.entry-information-card {
flex-direction: column;
}
.wrapper-input-angle {
margin-left: 0;
width: 100%;
margin-top: toRem(1);
}
}
@media (max-width: toRem(50)) {
.orientation-title {
@include text(m-regular);
margin-bottom: toRem(2);
}
}
</style>