147 lines
6.5 KiB
JavaScript
147 lines
6.5 KiB
JavaScript
Vue.component('warehouse-project-modal', {
|
|
props: {
|
|
id: { type: [String, Number], required: true },
|
|
},
|
|
data() {
|
|
return {
|
|
window: window,
|
|
loading: false,
|
|
allUsers: [],
|
|
project: {
|
|
title: '',
|
|
description: '',
|
|
startDate: null,
|
|
endDate: null,
|
|
storageLocation: '',
|
|
externalTeam: '',
|
|
internalTeam: [], // Array of user IDs
|
|
status: 'new',
|
|
financials: 0.00
|
|
},
|
|
statusOptions: [
|
|
{ text: 'Neu', value: 'new' },
|
|
{ text: 'In Bearbeitung', value: 'wip' },
|
|
{ text: 'Abgeschlossen', value: 'finished' },
|
|
{ text: 'Storniert', value: 'cancelled' }
|
|
]
|
|
};
|
|
},
|
|
//language=Vue
|
|
template: `
|
|
<tt-modal :show="true"
|
|
:delete="false"
|
|
:title="id === 'create' ? 'Projekt erstellen' : 'Projekt bearbeiten'"
|
|
@update:show="$emit('close')"
|
|
@submit="submit"
|
|
:save-loading="loading"
|
|
>
|
|
<div style="width: 99%">
|
|
<tt-input v-model="project.title" label="Bezeichnung *" sm row required/>
|
|
<div class="row">
|
|
<div class="col-md-6">
|
|
<tt-input v-model="project.startDate" label="Startdatum *" type="date" sm row required/>
|
|
</div>
|
|
<div class="col-md-6">
|
|
<tt-input v-model="project.endDate" label="Enddatum *" type="date" sm row required/>
|
|
</div>
|
|
</div>
|
|
|
|
<tt-input v-model="project.storageLocation" label="Lagerort" sm row/>
|
|
|
|
<div class="form-group row">
|
|
<label class="col-sm-3 col-form-label col-form-label-sm">Status *</label>
|
|
<div class="col-sm-9">
|
|
<select class="form-control form-control-sm" v-model="project.status" required>
|
|
<option v-for="opt in statusOptions" :key="opt.value" :value="opt.value">{{ opt.text }}</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Internal Team Select (Create Only or simplified list) -->
|
|
<div class="form-group row" v-if="id === 'create'">
|
|
<label class="col-sm-3 col-form-label col-form-label-sm">Internes Team</label>
|
|
<div class="col-sm-9">
|
|
<select class="form-control form-control-sm" v-model="project.internalTeam" multiple style="height: 100px;">
|
|
<option v-for="u in allUsers" :key="u.id" :value="u.id">{{ u.name }}</option>
|
|
</select>
|
|
<small class="text-muted">Strg+Klick für Mehrfachauswahl</small>
|
|
</div>
|
|
</div>
|
|
|
|
<tt-textarea v-model="project.externalTeam" label="Externes Team" sm row placeholder="Namen, Firmen, Kontakte..."/>
|
|
<tt-textarea v-model="project.description" label="Beschreibung" sm row rows="4"/>
|
|
|
|
<div v-if="id !== 'create'" class="form-group row">
|
|
<label class="col-sm-3 col-form-label col-form-label-sm">Finanzen</label>
|
|
<div class="col-sm-9">
|
|
<input type="text" class="form-control form-control-sm" :value="formatPrice(project.financials)" disabled>
|
|
<small class="text-muted">Wird automatisch berechnet.</small>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</tt-modal>
|
|
`,
|
|
async mounted() {
|
|
this.fetchUsers();
|
|
if (this.id !== 'create') {
|
|
this.loading = true;
|
|
try {
|
|
const { data } = await axios.get(`${window.TT_CONFIG["BASE_PATH"]}/WarehouseProject/getById`, { params: { id: this.id } });
|
|
if (data) {
|
|
this.project = { ...this.project, ...data };
|
|
// Ensure dates are in YYYY-MM-DD format for input type="date"
|
|
if (this.project.startDate) this.project.startDate = this.formatDateForInput(this.project.startDate);
|
|
if (this.project.endDate) this.project.endDate = this.formatDateForInput(this.project.endDate);
|
|
}
|
|
} catch (e) {
|
|
console.error(e);
|
|
window.notify('error', 'Projekt konnte nicht geladen werden.');
|
|
} finally {
|
|
this.loading = false;
|
|
}
|
|
}
|
|
},
|
|
methods: {
|
|
async fetchUsers() {
|
|
try {
|
|
const res = await axios.get(`${window.TT_CONFIG["BASE_PATH"]}/WarehouseProject/getUsers`);
|
|
this.allUsers = res.data;
|
|
} catch(e) { console.error(e); }
|
|
},
|
|
formatDateForInput(timestamp) {
|
|
if (!timestamp) return null;
|
|
return new Date(timestamp * 1000).toISOString().split('T')[0];
|
|
},
|
|
formatPrice(val) {
|
|
return new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(val || 0);
|
|
},
|
|
async submit() {
|
|
if (!this.project.title || !this.project.startDate || !this.project.endDate) {
|
|
return window.notify('error', 'Bitte füllen Sie alle Pflichtfelder aus (*).');
|
|
}
|
|
|
|
this.loading = true;
|
|
try {
|
|
const payload = { ...this.project };
|
|
if (payload.startDate) payload.startDate = Math.floor(new Date(payload.startDate).getTime() / 1000);
|
|
if (payload.endDate) payload.endDate = Math.floor(new Date(payload.endDate).getTime() / 1000);
|
|
|
|
const url = `${window.TT_CONFIG["BASE_PATH"]}/WarehouseProject/${this.id === 'create' ? 'create' : 'update'}`;
|
|
const response = await axios.post(url, payload);
|
|
|
|
if (response.data.success) {
|
|
this.$emit('close');
|
|
window.notify('success', response.data.message || 'Gespeichert.');
|
|
} else {
|
|
window.notify('error', response.data.message || 'Fehler beim Speichern.');
|
|
}
|
|
} catch (e) {
|
|
console.error(e);
|
|
window.notify('error', 'Ein Systemfehler ist aufgetreten.');
|
|
} finally {
|
|
this.loading = false;
|
|
}
|
|
}
|
|
}
|
|
});
|