Files
RAPPORT/src/views/BackendChoice.jsx
T
karim edee7b9f28 0.8.2: Auto-Recovery für hängende 0.8.0-Installationen + UpdateNotifier vor Login
- Auto-Recovery in adapter.js: wenn Cloud-Modus gesetzt + lokale Daten
  vorhanden + keine Cloud-Session → Cloud-Konfiguration wird beim
  nächsten App-Start automatisch zurückgenommen. Marker rapport_080_recovery
  verhindert wiederholte Auslösung.
- UpdateNotifier wird in allen Pre-Login-Screens gerendert (BackendChoice,
  Setup, MigrationScreen, CloudSetup, Login) — so kann ein hängender
  Wizard sich via Auto-Update selbst befreien.
- Tauri-Builds ignorieren VITE_SUPABASE_URL aus dem Build. Desktop-User
  geben die Server-URL immer aktiv im Login ein, statt eine irrelevante
  Default-IP vorgesetzt zu bekommen.
- Anon-Key bleibt aus dem Build (kein Geheimnis, pro Cloud-Instanz fix).
- BackendChoice zeigt nur dann eine vorkonfigurierte URL, wenn nicht in Tauri.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 19:54:14 +02:00

117 lines
4.7 KiB
React

import React from "react";
// Erst-Screen einer frischen Rapport-Installation: «Lokal oder Cloud?».
// Wird angezeigt, solange `localStorage["rapport_backend_chosen"]` nicht
// gesetzt ist UND noch keine lokalen Daten existieren. Sobald der User
// gewählt hat, reloaded die App und der jeweilige Wizard übernimmt:
// Lokal → bestehender Setup.jsx
// Cloud → Login mit Init-Modus oder Login-Modus (je nach Studio-Vorhandensein)
// Tauri-User geben die Server-URL immer aktiv ein. Build-time-URL ist nur
// für Web-Deploy gedacht (z.B. app.rapport.kgva.ch → 127.0.0.1:54321 lokal).
const isTauri = typeof window !== "undefined" && !!window.__TAURI_INTERNALS__;
const envCloudUrl = isTauri ? "" : (import.meta.env.VITE_SUPABASE_URL || "");
export default function BackendChoice() {
const pick = (backend, cloudUrl = "") => {
localStorage.setItem("rapport_backend_chosen", "1");
localStorage.setItem("rapport_backend", backend);
if (backend === "cloud" && cloudUrl) {
localStorage.setItem("rapport_cloud_url", cloudUrl.replace(/\/+$/, ""));
}
window.location.reload();
};
return (
<div style={{
minHeight: "100vh", minWidth: "100vw",
background: "#ebe7e1",
display: "flex", alignItems: "center", justifyContent: "center",
fontFamily: "'DM Mono', 'Courier New', monospace",
position: "fixed", inset: 0, zIndex: 9999,
padding: 20,
}}>
<style>{`
@keyframes bc-fade-in {
from { opacity: 0; transform: translateY(16px); }
to { opacity: 1; transform: translateY(0); }
}
.bc-card { animation: bc-fade-in 0.5s cubic-bezier(0.22,1,0.36,1) both; }
.bc-option {
width: 100%;
background: #fdfcfa;
border: 1.5px solid #ddd8d0;
border-radius: 14px;
padding: 22px 24px;
cursor: pointer;
font-family: inherit;
text-align: left;
transition: all 0.18s;
margin-bottom: 12px;
}
.bc-option:hover {
border-color: #9a7858;
box-shadow: 0 4px 16px rgba(154,120,88,0.12);
transform: translateY(-1px);
}
.bc-title {
font-size: 14px; font-weight: 500; color: #1a1a18; margin-bottom: 4px;
letter-spacing: 0.02em;
}
.bc-desc {
font-size: 12px; color: #888; line-height: 1.5;
}
`}</style>
<div className="bc-card" style={{
background: "transparent",
width: "100%", maxWidth: 460,
}}>
<div style={{ textAlign: "center", marginBottom: 36 }}>
<div style={{ fontFamily: "Krungthep, 'Archivo Black', sans-serif", fontSize: 40, color: "#1a1a18", letterSpacing: "-0.02em", lineHeight: 1 }}>
RAPPORT
</div>
<div style={{ fontSize: 10, color: "#b0aca4", letterSpacing: "0.22em", marginTop: 10, fontWeight: 500 }}>
ERSTE EINRICHTUNG
</div>
<div style={{ width: 40, height: 1.5, background: "#ddd8d0", margin: "20px auto 0" }} />
</div>
<p style={{ fontSize: 13, color: "#666", marginBottom: 26, textAlign: "center", lineHeight: 1.6 }}>
Wie möchten Sie Rapport nutzen?
</p>
<button className="bc-option" onClick={() => pick("local")}>
<div className="bc-title">Lokal auf diesem Gerät</div>
<div className="bc-desc">
Daten liegen ausschliesslich in diesem Browser / dieser App. Kein Server nötig.
Ideal zum Ausprobieren oder als Solo-Setup.
</div>
</button>
{envCloudUrl ? (
<button className="bc-option" onClick={() => pick("cloud", envCloudUrl)}>
<div className="bc-title">Mit Cloud-Server verbinden</div>
<div className="bc-desc">
Daten liegen auf dem konfigurierten Server. Mehrere Geräte / Mitarbeiter
können gemeinsam arbeiten. Vorkonfiguriert: <code style={{ fontSize: 11, color: "#9a7858" }}>{(() => { try { return new URL(envCloudUrl).host; } catch { return envCloudUrl; } })()}</code>
</div>
</button>
) : (
<button className="bc-option" onClick={() => pick("cloud")}>
<div className="bc-title">Mit Cloud-Server verbinden</div>
<div className="bc-desc">
Daten liegen auf einem Supabase-Server (z.B. Mac Mini im Büro, Docker im LAN).
Die Server-Adresse geben Sie im nächsten Schritt ein.
</div>
</button>
)}
<div style={{ marginTop: 24, fontSize: 11, color: "#aaa", textAlign: "center", lineHeight: 1.6 }}>
Sie können später in den Einstellungen wechseln.
</div>
</div>
</div>
);
}