Scouting: links die normalen Creator, rechts die Premium
Filipe: "ich will dass es da in der mitte eine trennung gibt. links sollen normale creator sein und rechts premium creator. es gibt bei tiktok naemlich diese zwei optionen von streamer ... auch dass wenn man die eintraegt soll man aussuchen koennen." Jede Stufe der Pipeline hat jetzt zwei Spalten mit einer Trennlinie dazwischen. Die Trennung sitzt IN der Stufe, nicht einmal ueber der ganzen Seite: Zwei komplette Pipelines nebeneinander haetten jede Stufenueberschrift verdoppelt und die beiden Seiten waeren nie auf gleicher Hoehe gewesen. GENAU ZWEI WERTE, kein "weiss nicht". Anders als bei `netzwerk`, wo "noch nicht gefragt" eine eigene gueltige Antwort ist: Dort wird eine fremde Tatsache festgehalten, hier eine eigene Absicht -- und deren Normalfall ist "normal". NULL wird als "normal" gelesen, der eine vorhandene Lead steht damit links, ohne dass ihm etwas unterstellt wird. DIE ART UEBERLEBT DIE UEBERGABE. Beim Creator-Onboarding wandert sie auf die Person und ist in der Personenverwaltung aenderbar. Ohne das endet die Angabe genau dort, wo sie zum ersten Mal vertraglich zaehlt. Die Schwelle misst den STUFENKASTEN (@container), nicht das Fenster -- der Fehler vom 06.09.2026 im selben Haus. Auf dem Handy liegen die Spalten untereinander, die senkrechte Linie faellt weg. ZWEI FUNDE BEIM BAUEN, beide von Hauswachen: * `pruef-fingermass` fand, dass meine neue Handy-Messung mit `setViewportSize` statt eigenem Kontext lief -- ohne `hasTouch` greift keine einzige Regel aus `@media (pointer: coarse)`. * Die Klassen hiessen zuerst `.spalte__*` -- die gehoeren `aufgaben.css`, und scouting.html laedt die VOR scouting.css. `margin-left: auto` aus dem Aufgabenbrett zog die Zahl 560 px von ihrem Wort weg, ohne dass eine Pruefung rot wurde. Jetzt `.art-spalte__*`, und der Abstand wird gemessen. pruef-scouting-felder: 28 -> 64 Pruefungen, gruen. Zwei Gegenproben gefahren (Trennung deaktiviert, Spaltenreihenfolge gedreht) -- beide schlugen an. Dazu gruen: haus-trennung, css-klassen, personen-liste, personen-kachel, hand-personen, schranke, formulare, lesbarkeit, agentur, deutsche-texte, tippziele, leerzustand, fingermass. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -55,6 +55,27 @@ export const NETZWERK = ["nein", "ja", "unbekannt"];
|
||||
export const NETZWERK_NAME = {
|
||||
nein: "frei", ja: "schon im Netzwerk", unbekannt: "noch nicht gefragt",
|
||||
};
|
||||
|
||||
/* NORMAL ODER PREMIUM -- die beiden Arten, die TikTok kennt (06.10.2026).
|
||||
|
||||
Filipe: "es gibt bei tiktok nämlich diese zwei optionen von streamer."
|
||||
|
||||
GENAU ZWEI, und absichtlich kein "weiss nicht". Die Begruendung steht
|
||||
bei der Spalte in workspace.js; kurz: Hier wird nicht eine fremde
|
||||
Tatsache festgehalten, sondern eine eigene Absicht -- und deren
|
||||
Normalfall ist "normal".
|
||||
|
||||
DIE REIHENFOLGE IST DIE DER SPALTEN auf der Seite: links normal,
|
||||
rechts premium. Die Oberflaeche liest sie von hier, sie fuehrt keine
|
||||
eigene Liste -- sonst stuende die Trennung an zwei Stellen und wuerde
|
||||
an einer davon geaendert. */
|
||||
export const ARTEN = ["normal", "premium"];
|
||||
export const ART_NAME = { normal: "Normal", premium: "Premium" };
|
||||
|
||||
/* NULL ist "normal". Diese Umrechnung steht an EINER Stelle, weil sonst
|
||||
jede Abfrage, jede Spaltenzuteilung und jede Zaehlung ihre eigene
|
||||
Meinung dazu haette, wo ein Lead ohne Eintrag hingehoert. */
|
||||
export const artVon = (wert) => (wert === "premium" ? "premium" : "normal");
|
||||
const NAME_MAX = 120;
|
||||
const TEXT_MAX = 3000;
|
||||
|
||||
@@ -120,6 +141,7 @@ const SPALTEN = `
|
||||
l.aktivitaet, l.potenzial, l.notizen, l.letzte_nachricht, l.naechster_followup,
|
||||
l.scout_id, l.erstellt, l.geaendert, l.uebergeben_am, l.creator_id,
|
||||
l.follower, l.land, l.woher, l.kontaktweg, l.live_zeiten, l.netzwerk, l.absage_grund,
|
||||
l.creator_art,
|
||||
ps.name AS scout_name, pc.name AS creator_name`;
|
||||
|
||||
const VERBUND = `
|
||||
@@ -143,7 +165,11 @@ scoutRouter.get("/workspace/api/leads", (req, res) => {
|
||||
andere nicht -- zuletzt bei der Rollenwahl am 10.09. */
|
||||
laender: LAENDER, land_name: LAND_NAME,
|
||||
netzwerk: NETZWERK, netzwerk_name: NETZWERK_NAME,
|
||||
arten: ARTEN, art_name: ART_NAME,
|
||||
heute,
|
||||
/* `creator_art` wird hier schon aufgeloest (NULL -> "normal"),
|
||||
damit die Oberflaeche nicht ihre eigene Regel dafuer braucht --
|
||||
sie waere die zweite und wuerde irgendwann die andere sagen. */
|
||||
leads: db().prepare(`
|
||||
SELECT ${SPALTEN} ${VERBUND}
|
||||
WHERE ${wo}
|
||||
@@ -153,7 +179,8 @@ scoutRouter.get("/workspace/api/leads", (req, res) => {
|
||||
WHEN 'uebergeben' THEN 4 ELSE 5 END,
|
||||
CASE l.prioritaet WHEN 'hoch' THEN 0 WHEN 'mittel' THEN 1 ELSE 2 END,
|
||||
CASE WHEN l.naechster_followup IS NULL THEN 1 ELSE 0 END,
|
||||
l.naechster_followup, l.id DESC`).all(...werte),
|
||||
l.naechster_followup, l.id DESC`).all(...werte)
|
||||
.map((l) => ({ ...l, creator_art: artVon(l.creator_art) })),
|
||||
});
|
||||
} catch (fehler) {
|
||||
console.error("[workspace] Leads lesen:", fehler?.message);
|
||||
@@ -216,6 +243,19 @@ function pruefe(körper, { neu }) {
|
||||
else if (!NETZWERK.includes(w)) fehler.push("Unbekannte Angabe zum Netzwerk.");
|
||||
else aus.netzwerk = w;
|
||||
}
|
||||
/* Normal oder Premium. Ein leerer Wert ist hier NICHT dasselbe wie bei
|
||||
Land und Netzwerk: Dort heisst leer "nicht angegeben" und wird als
|
||||
NULL gespeichert, hier gibt es keinen dritten Zustand -- leer faellt
|
||||
auf "normal" zurueck, so wie es die Spalte ohnehin liest. Ein
|
||||
erfundener Wert wird trotzdem abgelehnt und nicht stillschweigend
|
||||
zu "normal" gemacht: Wer "premiumm" schickt, hat sich vertippt und
|
||||
soll es erfahren, statt die Karte auf der falschen Seite zu finden. */
|
||||
if (körper.creator_art !== undefined) {
|
||||
const w = String(körper.creator_art ?? "").trim();
|
||||
if (!w) aus.creator_art = "normal";
|
||||
else if (!ARTEN.includes(w)) fehler.push("Unbekannte Creator-Art.");
|
||||
else aus.creator_art = w;
|
||||
}
|
||||
if (körper.follower !== undefined) {
|
||||
const roh = String(körper.follower ?? "").trim();
|
||||
if (!roh) aus.follower = null;
|
||||
@@ -270,8 +310,9 @@ scoutRouter.post("/workspace/api/leads", gleicheHerkunft, (req, res) => {
|
||||
INSERT INTO leads
|
||||
(name, plattform, handle, status, prioritaet, aktivitaet, potenzial,
|
||||
notizen, letzte_nachricht, naechster_followup, scout_id, erstellt, erstellt_von,
|
||||
follower, land, woher, kontaktweg, live_zeiten, netzwerk, absage_grund)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`).run(
|
||||
follower, land, woher, kontaktweg, live_zeiten, netzwerk, absage_grund,
|
||||
creator_art)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`).run(
|
||||
aus.name, aus.plattform ?? null, aus.handle ?? null,
|
||||
aus.status ?? "neu", aus.prioritaet ?? "mittel",
|
||||
aus.aktivitaet ?? null, aus.potenzial ?? null, aus.notizen ?? null,
|
||||
@@ -279,7 +320,7 @@ scoutRouter.post("/workspace/api/leads", gleicheHerkunft, (req, res) => {
|
||||
scoutId, jetzt(), req.person.id,
|
||||
aus.follower ?? null, aus.land ?? null, aus.woher ?? null,
|
||||
aus.kontaktweg ?? null, aus.live_zeiten ?? null, aus.netzwerk ?? null,
|
||||
aus.absage_grund ?? null);
|
||||
aus.absage_grund ?? null, aus.creator_art ?? "normal");
|
||||
|
||||
protokolliere("lead_angelegt", {
|
||||
personId: req.person.id, rolle: req.person.rolle, ip: echteIp(req),
|
||||
@@ -382,6 +423,17 @@ scoutRouter.post("/workspace/api/leads/:id/onboarding", gleicheHerkunft, (req, r
|
||||
db().prepare("UPDATE leads SET creator_id = ?, geaendert = ? WHERE id = ?")
|
||||
.run(neu.id, jetzt(), id);
|
||||
|
||||
/* DIE ART GEHT MIT (06.10.2026).
|
||||
|
||||
Sonst endet die Angabe genau in dem Moment, in dem sie zum ersten
|
||||
Mal vertraglich zaehlt: Der Scout haelt fest, dass jemand als
|
||||
Premium geholt werden soll, das Onboarding legt die Person an --
|
||||
und am Creator steht es nirgends mehr. Ab hier ist es eine Angabe
|
||||
an der Person und laeuft dem Lead nicht mehr hinterher; geaendert
|
||||
wird sie danach in der Personenverwaltung. */
|
||||
db().prepare("UPDATE personen SET creator_art = ? WHERE id = ?")
|
||||
.run(artVon(lead.creator_art), neu.id);
|
||||
|
||||
/* Die Angaben des Scouts wandern ins Creator-Profil -- sonst müsste
|
||||
das Management sie abtippen, obwohl sie längst da sind. */
|
||||
const handles = [lead.plattform, lead.handle].filter(Boolean).join(" · ") || null;
|
||||
|
||||
Reference in New Issue
Block a user