225 lines
6.1 KiB
Vue
225 lines
6.1 KiB
Vue
<template>
|
|
<MintelManagerLayout
|
|
title="Company Manager"
|
|
:item-title="selectedCompany?.name || 'Firma wählen'"
|
|
:is-empty="!selectedCompany"
|
|
empty-title="Firma auswählen"
|
|
empty-icon="business"
|
|
:notice="feedback"
|
|
@close-notice="feedback = null"
|
|
>
|
|
<template #navigation>
|
|
<v-list nav>
|
|
<v-list-item @click="openCreateDrawer" clickable>
|
|
<v-list-item-icon>
|
|
<v-icon name="add" color="var(--theme--primary)" />
|
|
</v-list-item-icon>
|
|
<v-list-item-content>
|
|
<v-text-overflow text="Neue Firma anlegen" />
|
|
</v-list-item-content>
|
|
</v-list-item>
|
|
|
|
<v-divider />
|
|
|
|
<v-list-item
|
|
v-for="company in companies"
|
|
:key="company.id"
|
|
:active="selectedCompany?.id === company.id"
|
|
class="nav-item"
|
|
clickable
|
|
@click="selectCompany(company)"
|
|
>
|
|
<v-list-item-icon>
|
|
<v-icon name="business" />
|
|
</v-list-item-icon>
|
|
<v-list-item-content>
|
|
<v-text-overflow :text="company.name" />
|
|
</v-list-item-content>
|
|
</v-list-item>
|
|
</v-list>
|
|
</template>
|
|
|
|
<template #subtitle>
|
|
<template v-if="selectedCompany">
|
|
{{ selectedCompany.domain || 'Keine Domain angegeben' }}
|
|
</template>
|
|
</template>
|
|
|
|
<template #actions>
|
|
<v-button secondary rounded icon v-tooltip.bottom="'Firma bearbeiten'" @click="openEditDrawer">
|
|
<v-icon name="edit" />
|
|
</v-button>
|
|
<v-button danger rounded icon v-tooltip.bottom="'Firma löschen'" @click="deleteCompany">
|
|
<v-icon name="delete" />
|
|
</v-button>
|
|
</template>
|
|
|
|
<template #empty-state>
|
|
Wähle eine Firma in der Navigation aus oder
|
|
<v-button x-small @click="openCreateDrawer">erstelle eine neue Firma</v-button>.
|
|
</template>
|
|
|
|
<div v-if="selectedCompany" class="details-grid">
|
|
<div class="detail-item full">
|
|
<span class="label">Notizen / Adresse</span>
|
|
<p class="value">{{ selectedCompany.notes || '---' }}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Create/Edit Drawer -->
|
|
<v-drawer
|
|
v-model="drawerActive"
|
|
:title="isEditing ? 'Firma bearbeiten' : 'Neue Firma anlegen'"
|
|
icon="business"
|
|
@cancel="drawerActive = false"
|
|
>
|
|
<template #default>
|
|
<div class="drawer-content">
|
|
<div class="form-section">
|
|
<div class="field">
|
|
<span class="label">Firmenname</span>
|
|
<v-input v-model="form.name" placeholder="z.B. Schmidt GmbH" autofocus />
|
|
</div>
|
|
<div class="field">
|
|
<span class="label">Domain / Website</span>
|
|
<v-input v-model="form.domain" placeholder="example.com" />
|
|
</div>
|
|
<div class="field">
|
|
<span class="label">Notizen / Adresse</span>
|
|
<v-textarea v-model="form.notes" placeholder="z.B. Branche, Adresse, etc." />
|
|
</div>
|
|
</div>
|
|
|
|
<div class="drawer-actions">
|
|
<v-button primary block :loading="saving" @click="saveCompany">
|
|
Firma speichern
|
|
</v-button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
</v-drawer>
|
|
</MintelManagerLayout>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, onMounted } from 'vue';
|
|
import { useApi } from '@directus/extensions-sdk';
|
|
import { useRoute } from 'vue-router';
|
|
import { MintelManagerLayout } from '@mintel/directus-extension-toolkit';
|
|
|
|
const api = useApi();
|
|
const route = useRoute();
|
|
const companies = ref([]);
|
|
const selectedCompany = ref(null);
|
|
const feedback = ref(null);
|
|
const saving = ref(false);
|
|
const drawerActive = ref(false);
|
|
const isEditing = ref(false);
|
|
|
|
const form = ref({
|
|
id: null,
|
|
name: '',
|
|
domain: '',
|
|
notes: ''
|
|
});
|
|
|
|
async function fetchData() {
|
|
try {
|
|
const resp = await api.get('/items/companies', {
|
|
params: { sort: 'name' }
|
|
});
|
|
companies.value = resp.data.data;
|
|
} catch (error) {
|
|
console.error('Failed to fetch companies:', error);
|
|
}
|
|
}
|
|
|
|
function selectCompany(company: any) {
|
|
selectedCompany.value = company;
|
|
}
|
|
|
|
function openCreateDrawer() {
|
|
isEditing.value = false;
|
|
form.value = {
|
|
id: null,
|
|
name: '',
|
|
domain: '',
|
|
notes: ''
|
|
};
|
|
drawerActive.value = true;
|
|
}
|
|
|
|
function openEditDrawer() {
|
|
isEditing.value = true;
|
|
form.value = {
|
|
id: selectedCompany.value.id,
|
|
name: selectedCompany.value.name,
|
|
domain: selectedCompany.value.domain,
|
|
notes: selectedCompany.value.notes
|
|
};
|
|
drawerActive.value = true;
|
|
}
|
|
|
|
async function saveCompany() {
|
|
if (!form.value.name) {
|
|
feedback.value = { type: 'danger', message: 'Firmenname ist erforderlich.' };
|
|
return;
|
|
}
|
|
|
|
saving.value = true;
|
|
try {
|
|
let updatedItem;
|
|
if (isEditing.value) {
|
|
const res = await api.patch(`/items/companies/${form.value.id}`, form.value);
|
|
updatedItem = res.data.data;
|
|
feedback.value = { type: 'success', message: 'Firma aktualisiert!' };
|
|
} else {
|
|
const res = await api.post('/items/companies', form.value);
|
|
updatedItem = res.data.data;
|
|
feedback.value = { type: 'success', message: 'Firma angelegt!' };
|
|
}
|
|
drawerActive.value = false;
|
|
await fetchData();
|
|
if (updatedItem) {
|
|
selectedCompany.value = companies.value.find(c => c.id === updatedItem.id) || updatedItem;
|
|
}
|
|
} catch (error) {
|
|
feedback.value = { type: 'danger', message: error.message };
|
|
} finally {
|
|
saving.value = false;
|
|
}
|
|
}
|
|
|
|
async function deleteCompany() {
|
|
if (!confirm('Soll diese Firma wirklich gelöscht werden?')) return;
|
|
|
|
try {
|
|
await api.delete(`/items/companies/${selectedCompany.value.id}`);
|
|
feedback.value = { type: 'success', message: 'Firma gelöscht.' };
|
|
selectedCompany.value = null;
|
|
await fetchData();
|
|
} catch (error) {
|
|
feedback.value = { type: 'danger', message: error.message };
|
|
}
|
|
}
|
|
|
|
onMounted(async () => {
|
|
await fetchData();
|
|
if (route.query.create === 'true') {
|
|
openCreateDrawer();
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<style scoped>
|
|
.details-grid { display: flex; flex-direction: column; gap: 24px; }
|
|
.detail-item { display: flex; flex-direction: column; gap: 8px; }
|
|
.detail-item.full { width: 100%; }
|
|
.label { font-size: 12px; font-weight: 700; text-transform: uppercase; color: var(--theme--foreground-subdued); letter-spacing: 0.5px; }
|
|
.value { font-size: 16px; font-weight: 500; }
|
|
.drawer-content { padding: 24px; display: flex; flex-direction: column; gap: 32px; }
|
|
.form-section { display: flex; flex-direction: column; gap: 20px; }
|
|
.field { display: flex; flex-direction: column; gap: 8px; }
|
|
.drawer-actions { margin-top: 24px; }
|
|
</style>
|