Überarbeitung landing und index
This commit is contained in:
@@ -186,6 +186,17 @@ function ledger_fetch_participant_summaries(PDO $pdo, int $tenantId, array $opti
|
|||||||
array_push($params, ...$emailNorms);
|
array_push($params, ...$emailNorms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (array_key_exists('user_ids', $options)) {
|
||||||
|
$userIds = is_array($options['user_ids'])
|
||||||
|
? ledger_normalize_ids($options['user_ids'])
|
||||||
|
: [];
|
||||||
|
if ($userIds === []) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
$where[] = 'p.user_id IN (' . implode(',', array_fill(0, count($userIds), '?')) . ')';
|
||||||
|
array_push($params, ...$userIds);
|
||||||
|
}
|
||||||
|
|
||||||
$sql = "
|
$sql = "
|
||||||
SELECT
|
SELECT
|
||||||
p.id AS participant_id,
|
p.id AS participant_id,
|
||||||
|
|||||||
+37
-8
@@ -71,11 +71,23 @@ body.public-page {
|
|||||||
padding: 4rem 6vw;
|
padding: 4rem 6vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Section intros (Titel + Unterzeile) sind ueberall zentriert, damit die
|
||||||
|
Seite nicht zwischen linksbuendigen und zentrierten Abschnitten springt.
|
||||||
|
Die Karteninhalte darunter bleiben davon unberuehrt links ausgerichtet. */
|
||||||
|
.public-section > header.major {
|
||||||
|
text-align: center;
|
||||||
|
max-width: 42rem;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.public-grid {
|
.public-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
gap: 1.25rem;
|
gap: 1.25rem;
|
||||||
max-width: 72rem;
|
max-width: 72rem;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.public-feature,
|
.public-feature,
|
||||||
@@ -84,6 +96,13 @@ body.public-page {
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
padding: 1.5rem;
|
padding: 1.5rem;
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
|
text-align: left;
|
||||||
|
transition: transform 0.15s ease, box-shadow 0.15s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.public-feature:hover {
|
||||||
|
transform: translateY(-0.2rem);
|
||||||
|
box-shadow: 0 0.75rem 1.75rem rgba(61, 68, 73, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.public-feature h3 {
|
.public-feature h3 {
|
||||||
@@ -94,6 +113,18 @@ body.public-page {
|
|||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.public-highlight {
|
||||||
|
background: #eef4ea;
|
||||||
|
}
|
||||||
|
|
||||||
|
.public-fineprint {
|
||||||
|
max-width: 72rem;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
color: #7f888f;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
.public-auth {
|
.public-auth {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background-image: url("../images/landing-hero.png");
|
background-image: url("../images/landing-hero.png");
|
||||||
@@ -171,6 +202,8 @@ body.public-page {
|
|||||||
|
|
||||||
.public-demo-frame {
|
.public-demo-frame {
|
||||||
max-width: 72rem;
|
max-width: 72rem;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
border: solid 1px rgba(210, 215, 217, 0.75);
|
border: solid 1px rgba(210, 215, 217, 0.75);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -188,6 +221,8 @@ body.public-page {
|
|||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
gap: 1.25rem;
|
gap: 1.25rem;
|
||||||
max-width: 72rem;
|
max-width: 72rem;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
margin-bottom: 1.5rem;
|
margin-bottom: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,14 +256,8 @@ body.public-page {
|
|||||||
margin: 0 0.5rem;
|
margin: 0 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.public-cta {
|
.public-cta ul.actions {
|
||||||
text-align: center;
|
justify-content: center;
|
||||||
}
|
|
||||||
|
|
||||||
.public-cta .major {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 980px) {
|
@media screen and (max-width: 980px) {
|
||||||
|
|||||||
@@ -38,12 +38,26 @@ if (!$hasAccess && checkKaffeelisteAccess($conn, $mailadress)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$participant = null;
|
$participant = null;
|
||||||
if ($hasAccess && $emailNorm !== '') {
|
if ($hasAccess) {
|
||||||
|
// Eingeloggte SaaS-Nutzer werden primaer ueber die feste user_id-
|
||||||
|
// Verknuepfung ihres Teilnehmers gefunden (bei Registrierung bzw.
|
||||||
|
// Zugangsvergabe gesetzt) - robuster als der E-Mail-Abgleich, der bei
|
||||||
|
// abweichender oder geleerter Teilnehmer-E-Mail ins Leere liefe. Der
|
||||||
|
// Legacy-/Dev-Pfad ohne SaaS-User faellt weiterhin auf die E-Mail zurueck.
|
||||||
|
$saasUserId = $saasUser !== null ? (int)$saasUser['user_id'] : 0;
|
||||||
|
if ($saasUserId > 0) {
|
||||||
|
$summaries = ledger_fetch_participant_summaries($pdo, $tenantId, [
|
||||||
|
'user_ids' => [$saasUserId],
|
||||||
|
]);
|
||||||
|
$participant = $summaries[0] ?? null;
|
||||||
|
}
|
||||||
|
if ($participant === null && $emailNorm !== '') {
|
||||||
$summaries = ledger_fetch_participant_summaries($pdo, $tenantId, [
|
$summaries = ledger_fetch_participant_summaries($pdo, $tenantId, [
|
||||||
'email_norms' => [$emailNorm],
|
'email_norms' => [$emailNorm],
|
||||||
]);
|
]);
|
||||||
$participant = $summaries[0] ?? null;
|
$participant = $summaries[0] ?? null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$settings = $hasAccess ? saas_fetch_tenant_settings($pdo, $tenantId) : null;
|
$settings = $hasAccess ? saas_fetch_tenant_settings($pdo, $tenantId) : null;
|
||||||
$entryMessage = null;
|
$entryMessage = null;
|
||||||
@@ -86,15 +100,8 @@ function dashboard_paypal_action(string $template, string $amount): string
|
|||||||
/**
|
/**
|
||||||
* @return array{ok: bool, message?: string, error?: string}
|
* @return array{ok: bool, message?: string, error?: string}
|
||||||
*/
|
*/
|
||||||
function dashboard_record_legacy_self_entry(PDO $pdo, array $participant, array $settings, mixed $marksValue): array
|
function dashboard_record_self_entry(PDO $pdo, array $participant, array $settings, mixed $marksValue, ?int $actorUserId): array
|
||||||
{
|
{
|
||||||
$legacyMitarbeiterId = $participant['legacy_mitarbeiter_id'] !== null
|
|
||||||
? (int)$participant['legacy_mitarbeiter_id']
|
|
||||||
: 0;
|
|
||||||
if ($legacyMitarbeiterId <= 0) {
|
|
||||||
return ['ok' => false, 'error' => 'Für diesen Teilnehmer ist die eigene Stricherfassung noch nicht verfügbar.'];
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((int)$settings['self_entry_enabled'] !== 1) {
|
if ((int)$settings['self_entry_enabled'] !== 1) {
|
||||||
return ['ok' => false, 'error' => 'Die eigene Stricherfassung ist aktuell deaktiviert.'];
|
return ['ok' => false, 'error' => 'Die eigene Stricherfassung ist aktuell deaktiviert.'];
|
||||||
}
|
}
|
||||||
@@ -109,11 +116,20 @@ function dashboard_record_legacy_self_entry(PDO $pdo, array $participant, array
|
|||||||
return ['ok' => false, 'error' => 'Der Preis pro Strich ist nicht gültig konfiguriert.'];
|
return ['ok' => false, 'error' => 'Der Preis pro Strich ist nicht gültig konfiguriert.'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$legacyMitarbeiterId = $participant['legacy_mitarbeiter_id'] !== null
|
||||||
|
? (int)$participant['legacy_mitarbeiter_id']
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ($legacyMitarbeiterId > 0) {
|
||||||
|
// Migrierter Default-Mandant: weiterhin in die Legacy-Tabelle
|
||||||
|
// schreiben, damit die noch-legacy Sammelseiten (stricheintragen.php)
|
||||||
|
// den Eintrag ebenfalls sehen; der Ledger-Eintrag entsteht per
|
||||||
|
// Spiegelung.
|
||||||
$bookedAt = date('Y-m-d H:i:s');
|
$bookedAt = date('Y-m-d H:i:s');
|
||||||
$cost = (($marks * $unitPriceCents) / 100);
|
$cost = (($marks * $unitPriceCents) / 100);
|
||||||
$unitPrice = ($unitPriceCents / 100);
|
$unitPrice = ($unitPriceCents / 100);
|
||||||
|
|
||||||
try {
|
|
||||||
$pdo->beginTransaction();
|
$pdo->beginTransaction();
|
||||||
$stmt = $pdo->prepare(
|
$stmt = $pdo->prepare(
|
||||||
'INSERT INTO kl_Kaffeeverbrauch
|
'INSERT INTO kl_Kaffeeverbrauch
|
||||||
@@ -128,6 +144,20 @@ function dashboard_record_legacy_self_entry(PDO $pdo, array $participant, array
|
|||||||
|
|
||||||
ledger_mirror_legacy_consumption($pdo, (int)$participant['tenant_id'], $legacyConsumptionId);
|
ledger_mirror_legacy_consumption($pdo, (int)$participant['tenant_id'], $legacyConsumptionId);
|
||||||
$pdo->commit();
|
$pdo->commit();
|
||||||
|
} else {
|
||||||
|
// SaaS-native Mandanten (alle ausser dem migrierten Default-
|
||||||
|
// Mandanten) haben keine Legacy-Schattentabelle - direkt ins
|
||||||
|
// Ledger buchen.
|
||||||
|
ledger_record_consumption(
|
||||||
|
$pdo,
|
||||||
|
(int)$participant['tenant_id'],
|
||||||
|
(int)$participant['participant_id'],
|
||||||
|
$marks,
|
||||||
|
$unitPriceCents,
|
||||||
|
'self_entry',
|
||||||
|
$actorUserId
|
||||||
|
);
|
||||||
|
}
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
if ($pdo->inTransaction()) {
|
if ($pdo->inTransaction()) {
|
||||||
$pdo->rollBack();
|
$pdo->rollBack();
|
||||||
@@ -174,7 +204,7 @@ function dashboard_render_consumption(array $entries): void
|
|||||||
|
|
||||||
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
||||||
if ($hasAccess && $participant !== null && $settings !== null) {
|
if ($hasAccess && $participant !== null && $settings !== null) {
|
||||||
$result = dashboard_record_legacy_self_entry($pdo, $participant, $settings, $_POST["anzahlStriche"] ?? null);
|
$result = dashboard_record_self_entry($pdo, $participant, $settings, $_POST["anzahlStriche"] ?? null, $saasUser['user_id'] ?? null);
|
||||||
if ($result['ok']) {
|
if ($result['ok']) {
|
||||||
$entryMessage = $result['message'] ?? null;
|
$entryMessage = $result['message'] ?? null;
|
||||||
$participant = ledger_fetch_participant_summary($pdo, $tenantId, (int)$participant['participant_id']);
|
$participant = ledger_fetch_participant_summary($pdo, $tenantId, (int)$participant['participant_id']);
|
||||||
@@ -213,8 +243,7 @@ if ($hasAccess && $participant !== null && $settings !== null) {
|
|||||||
$balanceCents = (int)$participant['balance_cents'];
|
$balanceCents = (int)$participant['balance_cents'];
|
||||||
$balance = dashboard_money($balanceCents);
|
$balance = dashboard_money($balanceCents);
|
||||||
$currentName = dashboard_current_name($saasUser, $participant, $conn, $mailadress);
|
$currentName = dashboard_current_name($saasUser, $participant, $conn, $mailadress);
|
||||||
$selfEntryEnabled = (int)$settings['self_entry_enabled'] === 1
|
$selfEntryEnabled = (int)$settings['self_entry_enabled'] === 1;
|
||||||
&& $participant['legacy_mitarbeiter_id'] !== null;
|
|
||||||
$paypalEnabled = (int)$settings['paypal_enabled'] === 1
|
$paypalEnabled = (int)$settings['paypal_enabled'] === 1
|
||||||
&& trim((string)$settings['paypal_url_template']) !== '';
|
&& trim((string)$settings['paypal_url_template']) !== '';
|
||||||
?>
|
?>
|
||||||
|
|||||||
+85
-18
@@ -5,7 +5,7 @@
|
|||||||
<title>Kaffeeliste – die digitale Kaffeekasse für Teams</title>
|
<title>Kaffeeliste – die digitale Kaffeekasse für Teams</title>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
|
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
|
||||||
<meta name="description" content="Kaffeeliste ist die digitale Kaffeekasse für Teams, Büros und Vereine: Striche erfassen, Guthaben im Blick behalten, bequem per PayPal ausgleichen." />
|
<meta name="description" content="Kaffeeliste automatisiert die Abrechnung eurer Kaffeekasse: Guthaben, Zahlungen und offene Beträge immer im Blick – ab 0 € im Monat, in Minuten startklar." />
|
||||||
<link rel="stylesheet" href="assets/css/main.css" />
|
<link rel="stylesheet" href="assets/css/main.css" />
|
||||||
<link rel="stylesheet" href="assets/css/public.css" />
|
<link rel="stylesheet" href="assets/css/public.css" />
|
||||||
</head>
|
</head>
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
</nav>
|
</nav>
|
||||||
<div class="public-hero-content">
|
<div class="public-hero-content">
|
||||||
<h1>Die Kaffeekasse, die von allein mitrechnet</h1>
|
<h1>Die Kaffeekasse, die von allein mitrechnet</h1>
|
||||||
<p>Schluss mit Strichlisten auf Papier und Kopfrechnen beim Kassensturz: Kaffeeliste hält für dein Team, Büro oder deinen Verein fest, wer wie viele Striche gemacht hat, wer bezahlt hat und wer gerade offen ist – jederzeit einsehbar, für jeden nachvollziehbar.</p>
|
<p>Die Striche macht ihr weiterhin ganz klassisch an der Maschine – auf der ausgedruckten Liste, wie eh und je. Den Rest übernimmt Kaffeeliste: Guthaben, Zahlungen und offene Beträge sind für alle jederzeit auf einen Blick sichtbar. Schluss mit Kopfrechnen, Excel-Tabellen und dem lästigen Kassensturz am Monatsende.</p>
|
||||||
<ul class="actions">
|
<ul class="actions">
|
||||||
<li><a href="<?php echo htmlspecialchars(app_primary_url('register.php'), ENT_QUOTES, 'UTF-8'); ?>" class="button primary big">Kostenlos einrichten</a></li>
|
<li><a href="<?php echo htmlspecialchars(app_primary_url('register.php'), ENT_QUOTES, 'UTF-8'); ?>" class="button primary big">Kostenlos einrichten</a></li>
|
||||||
<li><a href="<?php echo htmlspecialchars(app_primary_url('login.php'), ENT_QUOTES, 'UTF-8'); ?>" class="button big">Zur App</a></li>
|
<li><a href="<?php echo htmlspecialchars(app_primary_url('login.php'), ENT_QUOTES, 'UTF-8'); ?>" class="button big">Zur App</a></li>
|
||||||
@@ -32,6 +32,7 @@
|
|||||||
<section class="public-section">
|
<section class="public-section">
|
||||||
<header class="major">
|
<header class="major">
|
||||||
<h2>So funktioniert's</h2>
|
<h2>So funktioniert's</h2>
|
||||||
|
<p>Drei Schritte, kein Umlernen für dein Team nötig.</p>
|
||||||
</header>
|
</header>
|
||||||
<div class="public-grid public-steps">
|
<div class="public-grid public-steps">
|
||||||
<article class="public-feature">
|
<article class="public-feature">
|
||||||
@@ -42,12 +43,12 @@
|
|||||||
<article class="public-feature">
|
<article class="public-feature">
|
||||||
<span class="public-step-number">2</span>
|
<span class="public-step-number">2</span>
|
||||||
<h3>Strich setzen</h3>
|
<h3>Strich setzen</h3>
|
||||||
<p>Der Strich landet in der Kaffeeliste – entweder durch eine verantwortliche Person gesammelt oder, wenn gewünscht, direkt selbst im eigenen Dashboard.</p>
|
<p>Der Strich landet in der Kaffeeliste – gesammelt durch die zuständige Person oder, wenn gewünscht, in Sekunden selbst im eigenen Dashboard erfasst.</p>
|
||||||
</article>
|
</article>
|
||||||
<article class="public-feature">
|
<article class="public-feature">
|
||||||
<span class="public-step-number">3</span>
|
<span class="public-step-number">3</span>
|
||||||
<h3>Bei Bedarf bezahlen</h3>
|
<h3>Bei Bedarf bezahlen</h3>
|
||||||
<p>Der aktuelle Stand ist jederzeit sichtbar. Ausgleich bequem per PayPal, wenn dein Team das nutzt – ganz ohne Bargeld und Wechselgeld.</p>
|
<p>Der aktuelle Stand ist immer sichtbar. Ausgleich in einem Klick per PayPal, ganz ohne Bargeld und Wechselgeld-Suche.</p>
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
@@ -55,35 +56,97 @@
|
|||||||
<section class="public-section">
|
<section class="public-section">
|
||||||
<header class="major">
|
<header class="major">
|
||||||
<h2>Alles rund um die Kaffeekasse</h2>
|
<h2>Alles rund um die Kaffeekasse</h2>
|
||||||
|
<p>Kein Feature-Wildwuchs – nur, was ein Team wirklich braucht.</p>
|
||||||
</header>
|
</header>
|
||||||
<div class="public-grid">
|
<div class="public-grid">
|
||||||
<article class="public-feature">
|
<article class="public-feature">
|
||||||
<h3>Mitglieder & Rollen</h3>
|
<h3>Immer der richtige Zugriff</h3>
|
||||||
<p>Mitglieder anlegen, deaktivieren oder anonymisieren. Zugang mit passender Rolle (Admin, Kassenwart, Mitglied) gezielt vergeben oder wieder entziehen.</p>
|
<p>Neue Kolleg:innen sind in einer Minute angelegt, wer geht, ist genauso schnell wieder draußen. Rollen wie Admin oder Kassenwart vergebt ihr gezielt – zum Beispiel für die Praktikantin, die nur Striche einträgt, aber nichts an den Einstellungen ändern kann.</p>
|
||||||
</article>
|
</article>
|
||||||
<article class="public-feature">
|
<article class="public-feature">
|
||||||
<h3>Guthaben & Einzahlungen</h3>
|
<h3>Nie wieder „Wer hat schon bezahlt?"</h3>
|
||||||
<p>Striche, Einzahlungen und Korrekturen laufen über ein durchgängiges Journal – jede Buchung bleibt nachvollziehbar, auch nachträglich.</p>
|
<p>Jede Einzahlung, jeder Strich, jede Korrektur landet automatisch im gemeinsamen Kontobuch – nachvollziehbar bis zum ersten Tag. Praktisch beim Jahresabschluss: ein Klick, fertig.</p>
|
||||||
</article>
|
</article>
|
||||||
<article class="public-feature">
|
<article class="public-feature">
|
||||||
<h3>PayPal-Zahlung</h3>
|
<h3>Bezahlen in 10 Sekunden</h3>
|
||||||
<p>Offene Beträge lassen sich optional direkt per PayPal ausgleichen, inklusive automatischem Abgleich in der Liste.</p>
|
<p>Wer offen ist, bekommt einen fertigen PayPal-Link mit passendem Betrag. Kein Bargeld, kein Wechselgeld-Chaos in der Teeküche.</p>
|
||||||
</article>
|
</article>
|
||||||
<article class="public-feature">
|
<article class="public-feature">
|
||||||
<h3>CSV-Import & Export</h3>
|
<h3>Die Liste an der Wand bleibt</h3>
|
||||||
<p>Zahlungen aus einem PayPal-Export einlesen, mit Vorschau und Dublettenprüfung vor der Übernahme. Kaffeeliste als PDF für den Ausdruck exportieren.</p>
|
<p>Ausdrucken, aufhängen, fertig – mit eigenem Hinweistext als Wasserzeichen und automatisch passender Zeilengröße, egal ob 5 oder 150 Kolleg:innen mitmachen.</p>
|
||||||
</article>
|
</article>
|
||||||
<article class="public-feature">
|
<article class="public-feature">
|
||||||
<h3>Mandantenfähig</h3>
|
<h3>Alle informiert, ohne Rundmail-Chaos</h3>
|
||||||
<p>Jeder Kunde arbeitet in einem eigenen, streng getrennten Bereich mit eigenen Mitgliedern, Einstellungen und Buchungen.</p>
|
<p>Ein Hinweisbanner für „Die Maschine ist kaputt" oder eine Erinnerungsmail an alle mit offenem Betrag – in einer Minute verschickt statt einzeln nachgefragt.</p>
|
||||||
</article>
|
|
||||||
<article class="public-feature">
|
|
||||||
<h3>Hinweise & Info-Mails</h3>
|
|
||||||
<p>Aktuelle Hinweise für alle sichtbar einblenden, und bei Bedarf eine Info-Mail mit dem aktuellen Stand an alle Mitglieder verschicken.</p>
|
|
||||||
</article>
|
</article>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section class="public-section public-highlight">
|
||||||
|
<header class="major">
|
||||||
|
<h2>6 Gründe, warum Verwalter Kaffeeliste lieben</h2>
|
||||||
|
<p>Für Admin und Kassenwart macht das den größten Unterschied im Alltag.</p>
|
||||||
|
</header>
|
||||||
|
<div class="public-grid public-steps public-advantages">
|
||||||
|
<article class="public-feature">
|
||||||
|
<span class="public-step-number">1</span>
|
||||||
|
<h3>Kein Taschenrechner mehr</h3>
|
||||||
|
<p>Salden berechnen sich automatisch. Keine manuelle Addition von Strichen und Zahlungen am Monatsende.</p>
|
||||||
|
</article>
|
||||||
|
<article class="public-feature">
|
||||||
|
<span class="public-step-number">2</span>
|
||||||
|
<h3>Ein Klick statt Excel-Akrobatik</h3>
|
||||||
|
<p>Jahresabschluss, Mitgliederliste, Export – direkt aus der App statt mühsamer Tabellenpflege nebenbei.</p>
|
||||||
|
</article>
|
||||||
|
<article class="public-feature">
|
||||||
|
<span class="public-step-number">3</span>
|
||||||
|
<h3>Erinnerungen laufen von allein</h3>
|
||||||
|
<p>Eine Info-Mail an alle mit offenem Betrag, statt jede Person einzeln anzuschreiben oder anzusprechen.</p>
|
||||||
|
</article>
|
||||||
|
<article class="public-feature">
|
||||||
|
<span class="public-step-number">4</span>
|
||||||
|
<h3>Mitgliederverwaltung in Sekunden</h3>
|
||||||
|
<p>Neue Kolleg:innen anlegen, alte deaktivieren, Rollen vergeben – ohne Rückfragen, wer worauf Zugriff hat.</p>
|
||||||
|
</article>
|
||||||
|
<article class="public-feature">
|
||||||
|
<span class="public-step-number">5</span>
|
||||||
|
<h3>PayPal-Abgleich ohne Nachrechnen</h3>
|
||||||
|
<p>Eingehende Zahlungen ordnen sich automatisch dem richtigen Mitglied zu – kein Abgleich von Hand mehr.</p>
|
||||||
|
</article>
|
||||||
|
<article class="public-feature">
|
||||||
|
<span class="public-step-number">6</span>
|
||||||
|
<h3>Der Stand ist immer griffbereit</h3>
|
||||||
|
<p>Ob am Handy in der Teeküche oder am Rechner im Büro: Der Kassenstand ist nie veraltet oder in der falschen Datei.</p>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="public-section">
|
||||||
|
<header class="major">
|
||||||
|
<h2>Preise</h2>
|
||||||
|
<p>Ein Preis pro Team, gestaffelt nach aktiven Teilnehmern – keine Kosten pro Kopf, keine versteckten Gebühren.</p>
|
||||||
|
</header>
|
||||||
|
<div class="public-grid">
|
||||||
|
<article class="public-feature">
|
||||||
|
<h3>Bis 10 Teilnehmer</h3>
|
||||||
|
<p><strong>Kostenlos</strong></p>
|
||||||
|
</article>
|
||||||
|
<article class="public-feature">
|
||||||
|
<h3>Bis 25 Teilnehmer</h3>
|
||||||
|
<p><strong>3,99 € / Monat</strong></p>
|
||||||
|
</article>
|
||||||
|
<article class="public-feature">
|
||||||
|
<h3>Bis 50 Teilnehmer</h3>
|
||||||
|
<p><strong>7,99 € / Monat</strong></p>
|
||||||
|
</article>
|
||||||
|
<article class="public-feature">
|
||||||
|
<h3>Bis 150 Teilnehmer</h3>
|
||||||
|
<p><strong>12,99 € / Monat</strong></p>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
<p class="public-fineprint">Mehr als 150 Teilnehmer? <a href="<?php echo htmlspecialchars(app_primary_url('preise.php'), ENT_QUOTES, 'UTF-8'); ?>">Preis auf Anfrage</a>. Gemäß § 19 UStG wird keine Umsatzsteuer berechnet – die genannten Beträge sind die tatsächlich zu zahlenden Endpreise. Details unter <a href="<?php echo htmlspecialchars(app_primary_url('preise.php'), ENT_QUOTES, 'UTF-8'); ?>">Preise</a>.</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section class="public-section public-demo">
|
<section class="public-section public-demo">
|
||||||
<header class="major">
|
<header class="major">
|
||||||
<h2>So sieht's in der App aus</h2>
|
<h2>So sieht's in der App aus</h2>
|
||||||
@@ -103,6 +166,10 @@
|
|||||||
<h3>Wie schnell ist meine Kaffeeliste startklar?</h3>
|
<h3>Wie schnell ist meine Kaffeeliste startklar?</h3>
|
||||||
<p>Kundenkonto anlegen, Mitglieder eintragen, loslegen. Es ist keine Einrichtung durch uns nötig, und die bestehenden Abläufe rund um Striche und Einzahlungen bleiben dieselben.</p>
|
<p>Kundenkonto anlegen, Mitglieder eintragen, loslegen. Es ist keine Einrichtung durch uns nötig, und die bestehenden Abläufe rund um Striche und Einzahlungen bleiben dieselben.</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="public-panel">
|
||||||
|
<h3>Was kostet die Kaffeeliste?</h3>
|
||||||
|
<p>Bis 10 Teilnehmer kostenlos, danach gestaffelt nach Teamgröße ab 3,99 € im Monat – ohne Kosten pro Kopf. Details unter <a href="<?php echo htmlspecialchars(app_primary_url('preise.php'), ENT_QUOTES, 'UTF-8'); ?>">Preise</a>.</p>
|
||||||
|
</div>
|
||||||
<div class="public-panel">
|
<div class="public-panel">
|
||||||
<h3>Sind unsere Daten von denen anderer Kunden getrennt?</h3>
|
<h3>Sind unsere Daten von denen anderer Kunden getrennt?</h3>
|
||||||
<p>Ja. Jeder Kunde hat einen eigenen, isolierten Bereich für Mitglieder, Buchungen und Einstellungen. Diese Trennung ist fester Bestandteil der App und wird automatisiert geprüft.</p>
|
<p>Ja. Jeder Kunde hat einen eigenen, isolierten Bereich für Mitglieder, Buchungen und Einstellungen. Diese Trennung ist fester Bestandteil der App und wird automatisiert geprüft.</p>
|
||||||
|
|||||||
Reference in New Issue
Block a user