mirror of
https://github.com/Spythere/station-manager-2.0.git
synced 2026-05-03 05:28:13 +00:00
refactor: modal for updating vehicles; global & modal styles changes
This commit is contained in:
@@ -0,0 +1,273 @@
|
||||
<template>
|
||||
<div class="modal-bg" @click="() => (vehiclesStore.selectedVehicleId = -1)"></div>
|
||||
|
||||
<div class="modal">
|
||||
<div class="modal-content">
|
||||
<h1 class="modal-header">
|
||||
{{ mode == 'update' ? 'Edytuj' : 'Dodaj' }} pojazd
|
||||
|
||||
<button class="modal-exit" @click="closeModal">
|
||||
<LucideX :size="40" />
|
||||
</button>
|
||||
</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>
|
||||
<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>
|
||||
|
||||
<input type="checkbox" name="vehicle-hidden" id="vehicle-hidden" v-model="vehicleValues.hidden" />
|
||||
<label for="vehicle-hidden">Ukryty</label>
|
||||
</div>
|
||||
|
||||
<div></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">Nie zapisuj</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, PropType, reactive, ref, Ref, watch } from 'vue';
|
||||
import { useVehiclesStore } from '../../stores/vehicles.store';
|
||||
import { LucideX } from 'lucide-vue-next';
|
||||
import { IVehicle, RemoveVehicleGroupAPIResponse, UpdateVehicleAPIResponse } from '../../types/vehicles.types';
|
||||
import client from '../../common/http';
|
||||
import { AxiosError } from 'axios';
|
||||
|
||||
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,
|
||||
});
|
||||
|
||||
let currentChanges: Record<string, any> = reactive({});
|
||||
|
||||
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) {
|
||||
vehicleValues.name = currentVehicleRef.value.name || '';
|
||||
vehicleValues.cabinName = currentVehicleRef.value.cabinName || '';
|
||||
vehicleValues.type = currentVehicleRef.value.type || '';
|
||||
vehicleValues.vehicleGroupsId = currentVehicleRef.value.vehicleGroupsId || 0;
|
||||
vehicleValues.hidden = currentVehicleRef.value.hidden;
|
||||
vehicleValues.restrictions = {
|
||||
sponsorOnly: currentVehicleRef.value.restrictions?.sponsorOnly ?? null,
|
||||
teamOnly: currentVehicleRef.value.restrictions?.teamOnly ?? false,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
watch(
|
||||
vehicleValues,
|
||||
(val) => {
|
||||
Object.keys(val).forEach((k) => {
|
||||
const newValue = vehicleValues[k as keyof IVehicle];
|
||||
const currentValue = currentVehicleRef.value![k as keyof IVehicle];
|
||||
|
||||
if (newValue != currentValue) currentChanges[k] = newValue;
|
||||
else currentChanges[k] = undefined;
|
||||
});
|
||||
},
|
||||
{ deep: true },
|
||||
);
|
||||
|
||||
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;
|
||||
|
||||
alert('Zaktualizowano pojazd: ' + updatedData.name);
|
||||
} catch (error) {
|
||||
alert(handleAPIErrors(error));
|
||||
}
|
||||
|
||||
vehiclesStore.selectedVehicleId = -1;
|
||||
}
|
||||
|
||||
async function removeVehicle() {
|
||||
const vehicle = vehicleRef.value;
|
||||
|
||||
if (!vehicle) 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;
|
||||
}
|
||||
|
||||
.modal-actions {
|
||||
display: flex;
|
||||
gap: 0.5em;
|
||||
font-size: 1.1em;
|
||||
padding: 1em;
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user