Files
station-manager-2.0/src/components/VehiclesManager/VehicleEditModal.vue
T

270 lines
7.4 KiB
Vue

<template>
<div class="modal-bg" @click="closeModal()"></div>
<div class="modal" @keydown.esc="closeModal()" ref="modal" tabindex="0">
<div class="modal-content">
<h1 class="modal-header">
<span>{{ mode == 'update' ? 'Edytuj' : 'Dodaj' }} pojazd</span>
</h1>
<div class="modal-details" v-if="vehicleRef">
<div><b>ID:</b> {{ vehicleRef.id }}</div>
<div><b>Nazwa:</b> <input type="text" v-model="vehicleValues.name" /></div>
<div><b>Typ:</b> <input type="text" v-model="vehicleValues.type" /></div>
<div><b>Kabina lokomotywy:</b> <input type="text" v-model="vehicleValues.cabinName" /></div>
<div>
<b>Grupa: </b>
<select id="select-group" ref="select-group" v-model="vehicleValues.vehicleGroupsId">
<option
v-for="value in vehiclesStore.vehicleGroupsTable"
:value="value.vehicleGroupRef.id"
:selected="vehicleRef.group.id == value.vehicleGroupRef.id"
>
{{ value.vehicleGroupRef.name }}
</option>
</select>
</div>
<div>
<label>Sponsorzy do: </label>
<input type="number" v-model="vehicleValues.restrictions!.sponsorOnly" />
</div>
<div>
<span>
<input
type="checkbox"
name="vehicle-team-only"
id="vehicle-team-only"
v-model="vehicleValues.restrictions!.teamOnly"
/>
<label for="vehicle-team-only">Tylko dla zespołu</label>
</span>
&nbsp;
<span>
<input type="checkbox" name="vehicle-hidden" id="vehicle-hidden" v-model="vehicleValues.hidden" />
<label for="vehicle-hidden">Ukryty</label>
</span>
</div>
<div>
<b>Miniaturka:</b>
<div>
<img
:src="`https://stacjownik.spythere.eu/static/thumbnails/${vehicleRef.name}.png`"
height="60"
alt="thumbnail image"
/>
</div>
</div>
<div>
<b>Podgląd - 300px:</b>
<div>
<img
:src="`https://stacjownik.spythere.eu/static/images/${vehicleRef.name}--300px.jpg`"
width="200"
alt="thumbnail"
/>
</div>
</div>
<div>
<b>Podgląd - 800px:</b>
<div>
<img
:src="`https://stacjownik.spythere.eu/static/images/${vehicleRef.name}--800px.jpg`"
width="300"
alt="thumbnail"
/>
</div>
</div>
</div>
<div class="modal-actions">
<button @click="updateVehicle">Aktualizuj dane</button>
<button @click="removeVehicle">Usuń pojazd</button>
<button @click="closeModal">Wyjdź</button>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { computed, onMounted, PropType, reactive, ref, Ref, useTemplateRef, watch } from 'vue';
import { useVehiclesStore } from '../../stores/vehicles.store';
import { IVehicle, RemoveVehicleGroupAPIResponse, UpdateVehicleAPIResponse } from '../../types/vehicles.types';
import client from '../../common/http';
import { AxiosError } from 'axios';
const modalElementRef = useTemplateRef('modal');
const vehiclesStore = useVehiclesStore();
const currentVehicleRef: Ref<IVehicle | null> = ref(null);
let vehicleValues: Partial<IVehicle> = reactive({
name: '',
cabinName: '',
restrictions: {
teamOnly: false,
sponsorOnly: null,
},
type: '',
vehicleGroupsId: 0,
hidden: false,
});
const props = defineProps({
mode: {
type: String as PropType<'update' | 'create'>,
required: true,
},
});
const vehicleRef = computed(
() => vehiclesStore.vehiclesTable.find((v) => v.vehicleRef.id == vehiclesStore.selectedVehicleId)?.vehicleRef,
);
onMounted(() => {
currentVehicleRef.value =
vehiclesStore.vehiclesTable.find((v) => v.vehicleRef.id == vehiclesStore.selectedVehicleId)?.vehicleRef ?? null;
if (currentVehicleRef.value) {
const lastProps = vehiclesStore.lastVehicleUpdateProps;
vehicleValues.name = currentVehicleRef.value.name || '';
vehicleValues.cabinName = lastProps.cabinName || currentVehicleRef.value.cabinName;
vehicleValues.type = lastProps.type || currentVehicleRef.value.type || '';
vehicleValues.vehicleGroupsId = lastProps.vehicleGroupsId || currentVehicleRef.value.vehicleGroupsId || 0;
vehicleValues.hidden = lastProps.hidden || currentVehicleRef.value.hidden;
vehicleValues.restrictions = {
sponsorOnly: lastProps.restrictions?.sponsorOnly ?? currentVehicleRef.value.restrictions?.sponsorOnly ?? null,
teamOnly: lastProps.restrictions?.teamOnly ?? currentVehicleRef.value.restrictions?.teamOnly ?? false,
};
}
modalElementRef.value?.focus();
});
function closeModal() {
vehiclesStore.selectedVehicleId = -1;
}
function handleAPIErrors(error: unknown) {
console.error(error);
if (error instanceof AxiosError) {
return `Nie zaktualizowano pojazdu: ${error.response?.data.message}`;
} else {
return `Nie zaktualizowano pojazdu: ${error}`;
}
}
async function updateVehicle() {
const vehicle = vehicleRef.value;
if (!vehicle) return;
try {
const updatedData = (
await client.put<UpdateVehicleAPIResponse>(`/manager/vehicles/${vehicle.id}`, {
...vehicleValues,
restrictions: {
teamOnly: vehicleValues.restrictions?.teamOnly ?? false,
sponsorOnly: vehicleValues.restrictions?.sponsorOnly || null,
},
})
).data;
const oldGroup = vehicle.group;
vehicle.name = updatedData.name;
vehicle.type = updatedData.type;
vehicle.vehicleGroupsId = updatedData.vehicleGroupsId;
vehicle.cabinName = updatedData.cabinName;
vehicle.hidden = updatedData.hidden;
vehicle.restrictions = updatedData.restrictions;
vehicle.group = vehiclesStore.vehicleGroupsTable.find(
(g) => g.vehicleGroupRef.id == updatedData.vehicleGroupsId,
)!.vehicleGroupRef;
const newGroup = vehicle.group;
// Updating group counts
oldGroup._count.vehicles -= 1;
newGroup._count.vehicles += 1;
vehiclesStore.lastVehicleUpdateProps = updatedData;
alert('Zaktualizowano pojazd: ' + updatedData.name);
} catch (error) {
alert(handleAPIErrors(error));
}
vehiclesStore.selectedVehicleId = -1;
}
async function removeVehicle() {
const vehicle = vehicleRef.value;
if (!vehicle) return;
const removeConfirm = confirm('Czy na pewno chcesz usunąć ten pojazd?');
if (!removeConfirm) return;
try {
const removedData = (await client.delete<RemoveVehicleGroupAPIResponse>(`/manager/vehicles/${vehicle.id}`)).data;
vehicle.group._count.vehicles -= 1;
vehiclesStore.vehiclesTable = vehiclesStore.vehiclesTable.filter((v) => v.vehicleRef.id != vehicle.id);
alert('Usunięto pojazd: ' + removedData.name);
} catch (error) {
alert(handleAPIErrors(error));
}
vehiclesStore.selectedVehicleId = -1;
}
</script>
<style lang="scss" scoped>
@use '../../styles/modal';
.modal-content {
display: grid;
gap: 0.5em;
grid-template-rows: auto 1fr auto;
height: 100%;
}
.modal-details {
display: flex;
flex-direction: column;
gap: 0.5em;
overflow: auto;
padding: 1em;
}
h1.modal-header {
justify-content: center;
}
.modal-actions {
display: flex;
gap: 0.5em;
font-size: 1.1em;
padding: 1em;
button {
width: 100%;
}
}
</style>