162 lines
6.8 KiB
JavaScript
162 lines
6.8 KiB
JavaScript
Vue.component('warehouse-project-modal', {
|
|
props: {
|
|
id: { type: [String, Number], required: true },
|
|
mode: { type: String, default: 'edit' }
|
|
},
|
|
template: `
|
|
<tt-modal :show="true"
|
|
@submit="submit"
|
|
:delete="id !== 'create'"
|
|
:title="id === 'create' ? 'Projekt erstellen' : \`Projekt #\${id} bearbeiten\`"
|
|
@update:show="$emit('close')">
|
|
<div style="width: 99%">
|
|
<h4 class="text-center">Projektübersicht</h4>
|
|
<tt-input label="Projektnummer" v-model="project.projectNumber" sm row disabled />
|
|
<tt-textarea label="Um was handelt es sich?" v-model="project.description" sm row/>
|
|
|
|
<hr>
|
|
<h4 class="text-center">Zeitraum</h4>
|
|
<div style="display: grid; grid-gap: 10px; grid-template-columns: 1fr 1fr;">
|
|
<tt-date-picker label="Startdatum" v-model="project.startDate" sm/>
|
|
<tt-date-picker label="Enddatum" v-model="project.endDate" sm/>
|
|
</div>
|
|
|
|
<hr>
|
|
<h4 class="text-center">Beteiligte Personen</h4>
|
|
<tt-select label="Personen (XINON MT)"
|
|
:options="participantsOptions"
|
|
v-model="project.participants"
|
|
sm row />
|
|
<tt-textarea label="Freitext für weitere Personen" v-model="project.additionalParticipants" sm row/>
|
|
|
|
<hr>
|
|
<h4 class="text-center">Projektübersicht</h4>
|
|
<tt-input label="Gesamtsumme des Projekts (€)" v-model.number="project.totalSum" sm row type="number"/>
|
|
<tt-positions-manager
|
|
ref="positionsManager"
|
|
v-model="project.positions"
|
|
:config="positionsConfig"
|
|
@updateField-article="fetchArticleData"
|
|
/>
|
|
|
|
<hr>
|
|
<h4 class="text-center">Lagerort</h4>
|
|
<tt-input label="Lagerort für dieses Projekt" v-model="project.storageLocation" sm row/>
|
|
|
|
<hr>
|
|
<tt-textarea label="Notizen" v-model="project.notes" sm row/>
|
|
</div>
|
|
</tt-modal>
|
|
`,
|
|
data() {
|
|
return {
|
|
window: window,
|
|
participantsOptions: [
|
|
{ value: 1, text: 'Person A' },
|
|
{ value: 2, text: 'Person B' },
|
|
{ value: 3, text: 'Person C' }
|
|
// Add more participants as needed
|
|
],
|
|
positionsConfig: {
|
|
fields: {
|
|
article: {
|
|
type: 'autocomplete',
|
|
label: 'Artikel',
|
|
apiUrl: '/WarehouseArticle/autoComplete',
|
|
customFieldReference: 'WarehouseArticle',
|
|
},
|
|
hoursRequired: { type: 'input', label: 'Benötigte Stunden', inputType: 'number' },
|
|
amountRequired: { type: 'input', label: 'Benötigte Menge', inputType: 'number' },
|
|
description: { type: 'textarea', label: 'Beschreibung' }
|
|
},
|
|
validateForm(formData) {
|
|
const requiredFields = ['article', 'hoursRequired', 'amountRequired'];
|
|
for (const field of requiredFields) {
|
|
if (!formData[field]) {
|
|
window.notify('error', `Bitte füllen Sie ${this.positionsConfig.fields[field].label} aus`);
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
},
|
|
project: {
|
|
projectNumber: '',
|
|
description: '',
|
|
startDate: null,
|
|
endDate: null,
|
|
participants: [],
|
|
additionalParticipants: '',
|
|
totalSum: 0,
|
|
positions: [],
|
|
storageLocation: '',
|
|
notes: ''
|
|
}
|
|
};
|
|
},
|
|
async mounted() {
|
|
if (this.id !== 'create') {
|
|
const response = await axios.get(`${window.TT_CONFIG["BASE_PATH"]}/WarehouseProject/getById`, { params: { id: this.id } });
|
|
this.project = response.data;
|
|
} else {
|
|
this.project.projectNumber = await this.generateProjectNumber();
|
|
}
|
|
},
|
|
methods: {
|
|
async submit() {
|
|
if (!this.project.description) return window.notify('error', 'Bitte geben Sie eine Beschreibung ein.');
|
|
|
|
const url = this.id === 'create'
|
|
? `${window.TT_CONFIG["BASE_PATH"]}/WarehouseProject/create`
|
|
: `${window.TT_CONFIG["BASE_PATH"]}/WarehouseProject/update`;
|
|
|
|
const response = await axios.post(url, this.project);
|
|
|
|
if (response.data.success) {
|
|
window.notify('success', response.data.message ?? 'Projekt erfolgreich gespeichert');
|
|
this.$emit('close');
|
|
} else {
|
|
window.notify('error', response.data.errors ? Object.values(response.data.errors).join('<br>') : response.data.message || 'Ein Fehler ist aufgetreten');
|
|
}
|
|
},
|
|
async fetchArticleData(article) {
|
|
if (typeof article === 'number') {
|
|
const response = await axios.get(`${window.TT_CONFIG["BASE_PATH"]}/WarehouseArticle/getById`, { params: { id: article } });
|
|
this.$refs.positionsManager.updateField('description', response.data.description);
|
|
}
|
|
},
|
|
async generateProjectNumber() {
|
|
const currentCount = await axios.get(`${window.TT_CONFIG["BASE_PATH"]}/WarehouseProject/count`);
|
|
return `PRJ-${new Date().getFullYear()}-${String(currentCount.data + 1).padStart(4, '0')}`;
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
Vue.component('warehouse-project', {
|
|
template: `
|
|
<tt-card>
|
|
<warehouse-project-modal v-if="projectModalId" :id="projectModalId" @close="projectModalId = null;$refs.table.$refs.table.refreshTable()"/>
|
|
<button @click="projectModalId = 'create'" class="btn btn-primary">Angebot erstellen</button>
|
|
<tt-table-crud emit-edit @edit="projectModalId = $event.id" ref="table">
|
|
<template v-slot:expandedRow="{ row }">
|
|
<div>
|
|
<h5>Notizen</h5>
|
|
<p>{{ row.notes }}</p>
|
|
<h5>Verlauf</h5>
|
|
<ul>
|
|
<li v-for="entry in row.journal">{{ entry.date }} - {{ entry.description }}</li>
|
|
</ul>
|
|
</div>
|
|
</template>
|
|
</tt-table-crud>
|
|
</tt-card>
|
|
`,
|
|
data() {
|
|
return {
|
|
window: window,
|
|
projectModalId: null,
|
|
}
|
|
},
|
|
});
|