Merge: remove Billing-Referenz UI + add Notizen (description) field
This commit is contained in:
@@ -59,6 +59,12 @@ export function renderAktenDetail(): string {
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div className="akten-detail-description">
|
||||
<h3 data-i18n="projekte.detail.description.heading">Notizen</h3>
|
||||
<p id="akte-description-display" className="akten-detail-description-text" />
|
||||
<textarea id="akte-description-edit" className="akten-detail-description-input" rows={4} style="display:none" />
|
||||
</div>
|
||||
|
||||
<nav className="akten-tabs" id="akte-tabs">
|
||||
<a className="akten-tab" data-tab="verlauf" href="#" data-i18n="projekte.detail.tab.verlauf">Verlauf</a>
|
||||
<a className="akten-tab" data-tab="team" href="#" data-i18n="projekte.detail.tab.team">Team</a>
|
||||
|
||||
@@ -125,10 +125,6 @@ export function renderAktenNeu(): string {
|
||||
<input type="text" id="akte-country" maxLength={2} placeholder="DE" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="form-field">
|
||||
<label htmlFor="akte-billing" data-i18n="projekte.field.billing_reference">Billing-Referenz</label>
|
||||
<input type="text" id="akte-billing" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Patent-specific */}
|
||||
@@ -163,6 +159,11 @@ export function renderAktenNeu(): string {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="form-field">
|
||||
<label htmlFor="akte-description" data-i18n="projekte.field.description">Notizen</label>
|
||||
<textarea id="akte-description" rows={4} placeholder="Kurznotizen zum Projekt (optional)..." data-i18n-placeholder="projekte.field.description.placeholder" />
|
||||
</div>
|
||||
|
||||
<div className="form-field">
|
||||
<label htmlFor="akte-status" data-i18n="projekte.field.status">Status</label>
|
||||
<select id="akte-status">
|
||||
|
||||
@@ -460,6 +460,18 @@ function renderHeader() {
|
||||
(document.getElementById("akte-title-edit") as HTMLInputElement).value = akte.title;
|
||||
(document.getElementById("akte-ref-display") as HTMLElement).textContent = akte.reference || "";
|
||||
|
||||
const descDisplay = document.getElementById("akte-description-display") as HTMLElement;
|
||||
const descEdit = document.getElementById("akte-description-edit") as HTMLTextAreaElement;
|
||||
const description = (akte as Akte & { description?: string | null }).description ?? "";
|
||||
descDisplay.textContent = description;
|
||||
descEdit.value = description;
|
||||
const descWrap = document.querySelector<HTMLElement>(".akten-detail-description");
|
||||
if (descWrap) {
|
||||
// Hide the whole Notizen block when there is nothing to show AND we're
|
||||
// not in edit mode — toggled by initTitleEdit on edit/save.
|
||||
descWrap.dataset.empty = description ? "0" : "1";
|
||||
}
|
||||
|
||||
const typeChip = document.getElementById("akte-type-chip")!;
|
||||
typeChip.className = `akten-type-chip akten-type-${akte.type}`;
|
||||
typeChip.textContent = t(`projekte.type.${akte.type}`) || akte.type;
|
||||
@@ -681,12 +693,16 @@ function initTabs() {
|
||||
function initTitleEdit() {
|
||||
const display = document.getElementById("akte-title-display")!;
|
||||
const editInput = document.getElementById("akte-title-edit") as HTMLInputElement;
|
||||
const descDisplay = document.getElementById("akte-description-display") as HTMLElement;
|
||||
const descEdit = document.getElementById("akte-description-edit") as HTMLTextAreaElement;
|
||||
const editBtn = document.getElementById("akte-edit-btn") as HTMLButtonElement;
|
||||
const saveBtn = document.getElementById("akte-save-btn") as HTMLButtonElement;
|
||||
|
||||
editBtn.addEventListener("click", () => {
|
||||
display.style.display = "none";
|
||||
editInput.style.display = "";
|
||||
descDisplay.style.display = "none";
|
||||
descEdit.style.display = "";
|
||||
saveBtn.style.display = "";
|
||||
editBtn.style.display = "none";
|
||||
editInput.focus();
|
||||
@@ -696,16 +712,23 @@ function initTitleEdit() {
|
||||
saveBtn.addEventListener("click", async () => {
|
||||
if (!akte) return;
|
||||
const newTitle = editInput.value.trim();
|
||||
if (!newTitle || newTitle === akte.title) {
|
||||
const newDesc = descEdit.value.trim();
|
||||
const oldDesc = (akte as Akte & { description?: string | null }).description ?? "";
|
||||
const titleUnchanged = !newTitle || newTitle === akte.title;
|
||||
const descUnchanged = newDesc === oldDesc;
|
||||
if (titleUnchanged && descUnchanged) {
|
||||
cancelEdit();
|
||||
return;
|
||||
}
|
||||
saveBtn.disabled = true;
|
||||
try {
|
||||
const body: Record<string, unknown> = {};
|
||||
if (!titleUnchanged) body.title = newTitle;
|
||||
if (!descUnchanged) body.description = newDesc;
|
||||
const resp = await fetch(`/api/projekte/${akte.id}`, {
|
||||
method: "PATCH",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ title: newTitle }),
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
if (resp.ok) {
|
||||
akte = await resp.json();
|
||||
@@ -722,6 +745,8 @@ function initTitleEdit() {
|
||||
function cancelEdit() {
|
||||
display.style.display = "";
|
||||
editInput.style.display = "none";
|
||||
descDisplay.style.display = "";
|
||||
descEdit.style.display = "none";
|
||||
saveBtn.style.display = "none";
|
||||
editBtn.style.display = "";
|
||||
}
|
||||
|
||||
@@ -115,9 +115,10 @@ function submitForm() {
|
||||
if (ind) payload.industry = ind;
|
||||
const cty = ($("akte-country") as HTMLInputElement).value.trim();
|
||||
if (cty) payload.country = cty;
|
||||
const bill = ($("akte-billing") as HTMLInputElement).value.trim();
|
||||
if (bill) payload.billing_reference = bill;
|
||||
}
|
||||
|
||||
const desc = ($("akte-description") as HTMLTextAreaElement).value.trim();
|
||||
if (desc) payload.description = desc;
|
||||
if (type === "patent") {
|
||||
const pat = ($("akte-patent-number") as HTMLInputElement).value.trim();
|
||||
if (pat) payload.patent_number = pat;
|
||||
|
||||
@@ -772,7 +772,9 @@ const translations: Record<Lang, Record<string, string>> = {
|
||||
"projekte.field.netdocuments_url": "netDocuments-URL (optional)",
|
||||
"projekte.field.industry": "Branche",
|
||||
"projekte.field.country": "Land (ISO-2)",
|
||||
"projekte.field.billing_reference": "Billing-Referenz",
|
||||
"projekte.field.description": "Notizen",
|
||||
"projekte.field.description.placeholder": "Kurznotizen zum Projekt (optional)...",
|
||||
"projekte.detail.description.heading": "Notizen",
|
||||
"projekte.field.patent_number": "Patentnummer",
|
||||
"projekte.field.filing_date": "Anmeldetag",
|
||||
"projekte.field.grant_date": "Erteilungstag",
|
||||
@@ -1773,7 +1775,9 @@ const translations: Record<Lang, Record<string, string>> = {
|
||||
"projekte.field.netdocuments_url": "netDocuments URL (optional)",
|
||||
"projekte.field.industry": "Industry",
|
||||
"projekte.field.country": "Country (ISO-2)",
|
||||
"projekte.field.billing_reference": "Billing reference",
|
||||
"projekte.field.description": "Notes",
|
||||
"projekte.field.description.placeholder": "Short notes about the project (optional)...",
|
||||
"projekte.detail.description.heading": "Notes",
|
||||
"projekte.field.patent_number": "Patent number",
|
||||
"projekte.field.filing_date": "Filing date",
|
||||
"projekte.field.grant_date": "Grant date",
|
||||
|
||||
Reference in New Issue
Block a user