Merge kn/meine-pilot (Pilot-Feedback 17.10.)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
commit
d7724afc02
8 files changed
+630
-41
No files matched your search
@@ -40,30 +40,39 @@ function aboEndeText(f) {
|
||||
return tag ? `Dein Abo ist beendet. Deine Daten bleiben bis ${tag} gespeichert.` : 'Dein Abo ist beendet.'
|
||||
}
|
||||
|
||||
/** Pille und Zeile einer Funktion an einer Website (nur für Websites, bei denen istInMeine gilt). */
|
||||
const KURZINFO_MAX = 80 // wie der Server (kurzinfo.js): länger ist kein Detail mehr, sondern ein Fehler
|
||||
|
||||
/** Kurzinfo einer aktiven Funktion aus der Antwort des Servers: nur ein nicht leerer, kurzer Text; sonst '' (die Zeile zeigt dann „Aktiv“). */
|
||||
function kurzinfoVon(quelle) {
|
||||
const text = typeof quelle?.kurzinfo === 'string' ? quelle.kurzinfo.trim() : ''
|
||||
return text !== '' && text.length <= KURZINFO_MAX ? text : ''
|
||||
}
|
||||
|
||||
/**
|
||||
* Pille und Detailzeile einer Funktion an einer Website (nur für Websites, bei denen istInMeine gilt). Läuft die Funktion, gibt es keine
|
||||
* Pille: die Detailzeile ist die Kurzinfo des Servers („3 Termine heute · nächster 10:30“) oder „Aktiv“. Alles andere trägt eine Pille.
|
||||
*/
|
||||
function statusVon(eintrag, projekt) {
|
||||
if (eintrag.key === 'analyse') {
|
||||
const a = projekt.analyse
|
||||
if (a.state === 'active') return { pille: { text: 'Aktiv', ton: 'gruen' }, status: 'Läuft auf deiner Website' }
|
||||
if (a.state === 'active') return { pille: null, status: kurzinfoVon(a) || 'Aktiv' }
|
||||
return { pille: { text: 'Gesperrt', ton: 'grau' }, status: a.disabledReason === 'abo_ende' ? aboEndeText(a) : 'Schreib uns im Chat' }
|
||||
}
|
||||
const f = projekt.features[eintrag.key]
|
||||
switch (f.state) {
|
||||
case 'setup':
|
||||
return { pille: { text: 'In Einrichtung', ton: 'blau' }, status: f.ticketWoid ? `Einrichtung läuft · Ticket #${f.ticketWoid}` : 'Einrichtung läuft' }
|
||||
return { pille: { text: 'In Einrichtung', ton: 'blau' }, status: 'Wir richten sie gerade ein' }
|
||||
case 'ordered':
|
||||
return { pille: { text: 'Zahlung offen', ton: 'orange' }, status: 'Wir warten auf deine Zahlung' }
|
||||
case 'active': {
|
||||
const seit = datumDe(f.activatedAt)
|
||||
return { pille: { text: 'Aktiv', ton: 'gruen' }, status: seit ? `Aktiv seit ${seit}` : 'Läuft auf deiner Website' }
|
||||
}
|
||||
case 'active':
|
||||
return { pille: null, status: kurzinfoVon(f) || 'Aktiv' }
|
||||
case 'disabled':
|
||||
return { pille: { text: 'Abgeschaltet', ton: 'grau' }, status: f.disabledReason === 'abo_ende' ? aboEndeText(f) : 'Schreib uns im Chat, wenn du die Funktion wieder möchtest.' }
|
||||
return { pille: { text: 'Abgeschaltet', ton: 'grau' }, status: f.disabledReason === 'abo_ende' ? aboEndeText(f) : 'Im Chat wieder anfragen' }
|
||||
default: {
|
||||
if (eintrag.ablauf === 'fragebogen') return { pille: { text: 'Entwurf', ton: 'grau' }, status: 'Fragebogen fortsetzen' }
|
||||
const anfrage = anfrageStatusVon(projekt, eintrag.key)
|
||||
if (anfrage === 'angenommen') return { pille: { text: 'Angenommen', ton: 'blau' }, status: 'Jetzt einschalten' }
|
||||
if (anfrage === 'abgelehnt') return { pille: { text: 'Abgelehnt', ton: 'rot' }, status: 'Schreib uns im Chat' }
|
||||
if (anfrage === 'abgelehnt') return { pille: { text: 'Abgelehnt', ton: 'rot' }, status: 'Anfrage abgelehnt · Im Chat nachfragen' }
|
||||
return { pille: { text: 'Angefragt', ton: 'violett' }, status: 'Wir prüfen deine Anfrage' }
|
||||
}
|
||||
}
|
||||
@@ -71,8 +80,9 @@ function statusVon(eintrag, projekt) {
|
||||
|
||||
/**
|
||||
* Die Zeilen von „Meine“: je Funktion und Website eine, in Katalogreihenfolge, dann Websitereihenfolge. Funktionen mit
|
||||
* verfuegbar !== true fehlen (C9). zeile2 ist bei mehreren Websites der Websitename, sonst die Statuszeile.
|
||||
* @returns {Array<{ key: string, name: string, projectId: string, projektName: string, zustand: string, anfrageStatus: string, pille: { text: string, ton: string }, status: string, zeile2: string }>}
|
||||
* verfuegbar !== true fehlen (C9). pille ist null, solange die Funktion läuft; status ist die Detailzeile (Kurzinfo oder Zustandstext),
|
||||
* zeile2 ist bei mehreren Websites „Websitename · status“, sonst der Status allein.
|
||||
* @returns {Array<{ key: string, name: string, projectId: string, projektName: string, zustand: string, anfrageStatus: string, pille: { text: string, ton: string }|null, status: string, zeile2: string }>}
|
||||
*/
|
||||
export function meineZeilen(daten) {
|
||||
const seiten = websites(daten)
|
||||
@@ -82,16 +92,17 @@ export function meineZeilen(daten) {
|
||||
for (const projekt of seiten) {
|
||||
if (!istInMeine(eintrag, projekt)) continue
|
||||
const { pille, status } = statusVon(eintrag, projekt)
|
||||
const projektName = String(projekt.projectName ?? '')
|
||||
zeilen.push({
|
||||
key: eintrag.key,
|
||||
name: String(eintrag.name ?? ''),
|
||||
projectId: projekt.projectId,
|
||||
projektName: String(projekt.projectName ?? ''),
|
||||
projektName,
|
||||
zustand: String(zustandVon(projekt, eintrag.key) ?? ''),
|
||||
anfrageStatus: eintrag.key === 'analyse' ? '' : anfrageStatusVon(projekt, eintrag.key),
|
||||
pille,
|
||||
status,
|
||||
zeile2: mehrere ? String(projekt.projectName ?? '') : status,
|
||||
zeile2: mehrere && projektName !== '' ? `${projektName} · ${status}` : status,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -260,7 +271,7 @@ export async function zeigeFunktionen(wurzel, { route, me, nav } = {}, abh = {})
|
||||
},
|
||||
},
|
||||
h('span', { class: 'kn-fn-text' }, h('span', { class: 'kn-fn-name' }, z.name), h('span', { class: 'kn-fn-zeile2' }, z.zeile2)),
|
||||
pille(z.pille)))))
|
||||
h('span', { class: 'kn-fn-rechts' }, z.pille ? pille(z.pille) : null, h('span', { class: 'kn-fn-pfeil', 'aria-hidden': 'true' }, '›'))))))
|
||||
}
|
||||
|
||||
function eintragKarte({ eintrag, kandidaten }) {
|
||||
|
||||
@@ -50,7 +50,10 @@
|
||||
.kn-fn-zeile-knopf:hover .kn-fn-name { color: var(--kn-accent, #111); text-decoration: underline; text-decoration-color: var(--kn-line-strong, #d8dde3); text-underline-offset: 3px; }
|
||||
.kn-fn-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
|
||||
.kn-fn-name { font-weight: 600; color: var(--kn-text, #1a1f36); overflow-wrap: anywhere; }
|
||||
.kn-fn-zeile2 { font-size: 13px; line-height: 20px; color: var(--kn-text-2, #5e6678); overflow-wrap: anywhere; }
|
||||
.kn-fn-zeile2 { font-size: 13px; line-height: 20px; color: var(--kn-text-2, #5e6678); overflow-wrap: anywhere; font-variant-numeric: tabular-nums; }
|
||||
/* rechts: die Pille (nur wenn die Funktion nicht läuft) und der Pfeil, der die Zeile als antippbar zeigt */
|
||||
.kn-fn-rechts { display: flex; align-items: center; flex: none; gap: 12px; }
|
||||
.kn-fn-pfeil { font-size: 20px; line-height: 20px; color: var(--kn-text-2, #5e6678); }
|
||||
|
||||
/* ------------------------------------------------------------------------------------------ Entdecken --- */
|
||||
.kn-fn-eintrag { display: flex; flex-direction: column; gap: 16px; padding: 24px 0; border-top: 1px solid var(--kn-line, #ebeef1); }
|
||||
|
||||
Reference in new issue
Block a user