<template>
<div>
<h1>Report Template Editor: {{ template.name }}</h1>
<div v-if="isLoading" class="loading-state">Loading template data...</div>
<table class="template-table" v-if="!isLoading && template.lines">
<thead>
<tr>
<th style="width: 30%;">Line Name</th>
<th style="width: 15%;">Line Key</th>
<th style="width: 15%;">Account Spec</th>
<th style="width: 20%;">Formula</th>
<th style="width: 20%;">Display Style</th>
</tr>
</thead>
<tbody>
<tr v-for="line in template.lines" :key="line.line_id">
<!-- Indented Line Name -->
<td :style="{ paddingLeft: line.level * 25 + 10 + 'px' }">
<InlineTextEditor
:value="line.line_name"
@update="newValue => onCellUpdate(line.line_id, 'line_name', newValue)"
/>
</td>
<!-- Line Key Editor -->
<td>
<InlineTextEditor
:value="line.line_key"
@update="newValue => onCellUpdate(line.line_id, 'line_key', newValue)"
/>
</td>
<!-- Account Spec Editor -->
<td>
<InlineTextEditor
:value="line.account_spec"
@update="newValue => onCellUpdate(line.line_id, 'account_spec', newValue)"
/>
</td>
<!-- Formula Editor -->
<td>
<FormulaEditorDialog
:value="line.formula"
:available-line-keys="availableLineKeys"
@update="newValue => onCellUpdate(line.line_id, 'formula', newValue)"
/>
</td>
<!-- Style Selector -->
<td>
<StyleSelector
:value="line.display_style"
@update="newValue => onCellUpdate(line.line_id, 'display_style', newValue)"
/>
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import axios from 'axios';
import InlineTextEditor from '@/components/editors/InlineTextEditor.vue';
import StyleSelector from '@/components/editors/StyleSelector.vue';
import FormulaEditorDialog from '@/components/editors/FormulaEditorDialog.vue';
export default {
components: { InlineTextEditor, StyleSelector, FormulaEditorDialog },
props: {
// The template ID is expected to be passed via the router, e.g., /templates/:templateId/edit
templateId: {
type: String,
required: true
}
},
data() {
return {
template: {},
isLoading: false,
};
},
computed: {
availableLineKeys() {
if (!this.template.lines) return [];
return this.template.lines
.map(line => line.line_key)
.filter(Boolean); // Filter out null/empty/undefined keys
},
},
methods: {
async fetchTemplate() {
this.isLoading = true;
try {
// NOTE: Replace with your actual API endpoint to fetch a single template by its ID
const response = await axios.get(`/api/report-templates/${this.templateId}`);
this.template = response.data;
} catch (error) {
console.error("Failed to fetch template", error);
// Handle error (e.g., show notification to user)
} finally {
this.isLoading = false;
}
},
async onCellUpdate(lineId, fieldName, value) {
const payload = {
template_id: this.template._id,
line_id: lineId,
fieldname: fieldName,
value: value,
};
try {
await axios.post('/api/report-templates/lines/update', payload);
// Optimistic UI Update: Update the local data immediately for a responsive feel
const line = this.template.lines.find(l => l.line_id === lineId);
if (line) {
// Convert array from StyleSelector back to string for local state consistency
const finalValue = Array.isArray(value) ? value.join(' ') : value;
this.$set(line, fieldName, finalValue);
}
// Optionally show a success toast/notification
console.log("Update successful for", payload);
} catch (error) {
console.error("Failed to update line:", error);
// Optionally show an error toast/notification and revert the local change if needed
}
},
},
created() {
this.fetchTemplate();
},
};
</script>
<style scoped>
.template-table { width: 100%; border-collapse: collapse; table-layout: fixed; }
.template-table th, .template-table td { border: 1px solid #ddd; padding: 4px 8px; text-align: left; vertical-align: top; }
.template-table th { background-color: #f2f2f2; font-weight: bold; }
.loading-state { padding: 20px; text-align: center; color: #666; }
</style>