Anfrage mit einem Klick zu Kunde und Projektraum machen
Der wichtigste Handgriff im ganzen Bereich -- und der Weg, den man bei
JEDEM echten Kunden geht. Bisher haette man Name, E-Mail, Paket und
Wunschtermin von Hand in die Kundenmaske abgetippt: vier Gelegenheiten
fuer einen Tippfehler, und einer davon ist spaeter nicht mehr
korrigierbar, weil die E-Mail gleichzeitig der Anmeldename ist.
Jetzt steht in der Anfrage-Detailansicht eine Uebernahme mit Vorschau
(Kunde, E-Mail, Projekttitel, Sprache) und einem optionalen Preisfeld,
das die 30 % Anzahlung beim Tippen mitrechnet. Ein Klick legt an:
* den Kundenzugang, freigeschaltet, in der Sprache der Anfrage
* das Projekt, verknuepft mit der Anfrage, mit Wunschtermin und
"Briefing-Termin vereinbaren" als erstem sichtbaren Schritt
* die Anfrage wechselt automatisch auf "angenommen"
Danach springt die Ansicht auf "Kunden" und zeigt sofort den
Einladungslink -- den einzigen Weg, wie der Kunde an sein Passwort kommt.
Die beiden Schritte laufen bewusst nacheinander, nicht parallel: das
Projekt braucht die Kunden-Kennung. Schlaegt der zweite fehl, existiert
der Kunde trotzdem schon. Genau das sagt die Fehlermeldung dann auch
ausdruecklich -- sonst versucht man es blind noch einmal und scheitert an
der doppelten E-Mail-Adresse, ohne zu verstehen warum.
Ist aus einer Anfrage bereits ein Kunde geworden, erscheint statt der
Uebernahme ein Hinweis darauf. Zweimal denselben Kunden anzulegen soll
gar nicht erst angeboten werden.
Dabei denselben Anfuehrungszeichen-Fehler wie schon einmal gemacht und
behoben: das gerade " in „Kunden" beendet die JavaScript-Zeichenkette.
Typografisch richtig ist ohnehin das schliessende " -- beides in einem Zug.
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -231,6 +231,30 @@
|
||||
.vw-leer-gross h3 { margin-bottom: .3em; }
|
||||
.vw-leer-gross p { max-width: 46ch; margin-left: auto; margin-right: auto; }
|
||||
|
||||
|
||||
/* ---------- Übernahme: Anfrage wird Kunde ----------
|
||||
Der wichtigste Handgriff im ganzen Bereich. Bisher hätte man den
|
||||
Namen, die E-Mail, das Paket und den Budgetrahmen von Hand in die
|
||||
Kundenmaske abgetippt — vier Gelegenheiten für einen Tippfehler, und
|
||||
einer davon (die E-Mail) ist später nicht mehr korrigierbar, weil sie
|
||||
der Anmeldename ist. */
|
||||
.vw-uebernahme {
|
||||
border-radius: var(--wd-r);
|
||||
padding: 1.1rem 1.2rem;
|
||||
background: linear-gradient(180deg, rgba(127,208,232,.09), rgba(9,15,26,.6));
|
||||
border: 1px solid var(--wd-rand-stark);
|
||||
}
|
||||
.vw-uebernahme h4 { margin: 0 0 .3rem; font-size: 1rem; color: var(--wd-text); }
|
||||
.vw-uebernahme p { margin: 0 0 .8rem; font-size: .9rem; color: var(--wd-text-mid); }
|
||||
.vw-uebernahme-vorschau {
|
||||
display: grid; grid-template-columns: auto 1fr; gap: .25rem .8rem;
|
||||
font-size: .88rem; margin-bottom: .9rem;
|
||||
padding: .7rem .9rem; border-radius: 10px;
|
||||
background: rgba(5,7,11,.5); border: 1px solid var(--wd-rand);
|
||||
}
|
||||
.vw-uebernahme-vorschau dt { color: var(--wd-text-soft); }
|
||||
.vw-uebernahme-vorschau dd { margin: 0; color: var(--wd-text); overflow-wrap: anywhere; }
|
||||
|
||||
.vw-leer-hinweis { text-align: center; padding: 3rem 1rem; color: var(--wd-text-soft); }
|
||||
.vw-laedt { text-align: center; padding: 2.5rem 1rem; color: var(--wd-text-soft); }
|
||||
</style>
|
||||
@@ -793,6 +817,27 @@
|
||||
'<button type="button" class="wd-btn wd-btn--zweit wd-btn--klein" id="vw-notiz-speichern">Notiz speichern</button>' +
|
||||
"</div>" +
|
||||
|
||||
(a.kunde_id
|
||||
? '<div class="vw-abschnitt"><h3>Kunde</h3>' +
|
||||
'<p class="wd-klein wd-leise">Aus dieser Anfrage wurde bereits ein Kundenzugang erstellt. Du findest ihn oben unter „Kunden“.</p></div>'
|
||||
: '<div class="vw-abschnitt"><h3>Weiter geht es</h3>' +
|
||||
'<div class="vw-uebernahme">' +
|
||||
"<h4>Anfrage übernehmen</h4>" +
|
||||
"<p>Legt in einem Schritt den Kundenzugang UND das Projekt an — mit den Angaben aus dieser Anfrage. Du bekommst danach sofort den Einladungslink.</p>" +
|
||||
'<dl class="vw-uebernahme-vorschau">' +
|
||||
"<dt>Kunde</dt><dd>" + s(a.name) + "</dd>" +
|
||||
"<dt>E-Mail</dt><dd>" + s(a.email) + "</dd>" +
|
||||
"<dt>Projekt</dt><dd>" + s(PAKET_TEXT[a.paket] || a.paket) + " für " + s(a.name) + "</dd>" +
|
||||
"<dt>Sprache</dt><dd>" + s((a.sprache || "de").toUpperCase()) + "</dd>" +
|
||||
"</dl>" +
|
||||
'<div class="wd-feld" style="margin-bottom:.8rem">' +
|
||||
'<label for="vw-ue-preis">Gesamtpreis in Euro <span class="wd-leise">optional, später änderbar</span></label>' +
|
||||
'<input type="number" id="vw-ue-preis" min="0" step="1" inputmode="numeric" placeholder="z. B. 1500" />' +
|
||||
'<span class="wd-feld-hilfe" id="vw-ue-anzahlung">Die 30 % Anzahlung wird daraus berechnet.</span>' +
|
||||
"</div>" +
|
||||
'<button type="button" class="wd-btn wd-btn--haupt" id="vw-uebernehmen">Kunde und Projekt anlegen</button>' +
|
||||
"</div></div>") +
|
||||
|
||||
'<div class="vw-abschnitt"><h3>Aufräumen</h3>' +
|
||||
'<p class="wd-klein wd-leise">Archivieren löscht nichts — die Anfrage bleibt vollständig erhalten und lässt sich jederzeit zurückholen.</p>' +
|
||||
'<button type="button" class="wd-btn wd-btn--still wd-btn--klein" id="vw-archivieren">' +
|
||||
@@ -831,6 +876,67 @@
|
||||
}
|
||||
});
|
||||
|
||||
var preisFeld = blatt.querySelector("#vw-ue-preis");
|
||||
if (preisFeld) {
|
||||
preisFeld.addEventListener("input", function () {
|
||||
var wert = Number(preisFeld.value);
|
||||
blatt.querySelector("#vw-ue-anzahlung").textContent =
|
||||
Number.isFinite(wert) && wert > 0
|
||||
? "30 % Anzahlung: " + (Math.round(wert * 100 * 0.3) / 100).toFixed(2).replace(".", ",") + " €"
|
||||
: "Die 30 % Anzahlung wird daraus berechnet.";
|
||||
});
|
||||
}
|
||||
|
||||
var ueKnopf = blatt.querySelector("#vw-uebernehmen");
|
||||
if (ueKnopf) {
|
||||
ueKnopf.addEventListener("click", async function (e) {
|
||||
window.WD.knopfSperren(e.target, true, "Wird angelegt…");
|
||||
try {
|
||||
/* Zwei Schritte, bewusst nacheinander und nicht parallel: das
|
||||
Projekt braucht die Kunden-Kennung. Schlaegt der zweite
|
||||
fehl, existiert der Kunde trotzdem schon -- deshalb sagt die
|
||||
Fehlermeldung unten ausdruecklich, dass er angelegt wurde,
|
||||
damit niemand es blind noch einmal versucht und dann an der
|
||||
doppelten E-Mail scheitert. */
|
||||
var kunde = await api("/webdesign/admin/kunden", {
|
||||
method: "POST",
|
||||
body: {
|
||||
name: a.name, email: a.email, telefon: a.telefon || "",
|
||||
sprache: a.sprache || "de", freischalten: true,
|
||||
},
|
||||
});
|
||||
|
||||
var preis = Number(preisFeld && preisFeld.value);
|
||||
try {
|
||||
await api("/webdesign/admin/projekte", {
|
||||
method: "POST",
|
||||
body: {
|
||||
kundeId: kunde.id,
|
||||
anfrageId: a.id,
|
||||
titel: (PAKET_TEXT[a.paket] || a.paket) + " für " + a.name,
|
||||
paket: a.paket === "unklar" ? "website" : a.paket,
|
||||
preisEuro: Number.isFinite(preis) && preis > 0 ? preis : undefined,
|
||||
richttermin: a.termin || "",
|
||||
naechsterSchritt: "Briefing-Termin vereinbaren",
|
||||
},
|
||||
});
|
||||
} catch (projektFehler) {
|
||||
window.WD.meldung(meldung,
|
||||
"Der Kundenzugang wurde angelegt, das Projekt aber nicht: " +
|
||||
projektFehler.message + " Du kannst das Projekt unter „Kunden“ nachtragen.", "fehler");
|
||||
}
|
||||
|
||||
schliesseDetail();
|
||||
aktiverTab = "kunden";
|
||||
document.querySelector('[data-tab="kunden"]').click();
|
||||
zeigeLink(kunde.einladungsLink);
|
||||
} catch (fehler) {
|
||||
window.WD.knopfSperren(e.target, false);
|
||||
window.WD.meldung(meldung, fehler.message, "fehler");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
blatt.querySelector("#vw-archivieren").addEventListener("click", async function (e) {
|
||||
window.WD.knopfSperren(e.target, true, "…");
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user