Compare commits
3 Commits
0.6.0
...
e345602dc2
| Author | SHA1 | Date | |
|---|---|---|---|
| e345602dc2 | |||
| 4aac21e3e9 | |||
| 7d069dc367 |
@@ -1,179 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="de">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>Erste Schritte — Rapport</title>
|
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=DM+Mono:ital,wght@0,400;0,500;1,400&family=Playfair+Display:ital,wght@0,400;0,700;1,400&display=swap" rel="stylesheet" />
|
|
||||||
<style>
|
|
||||||
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
||||||
|
|
||||||
:root {
|
|
||||||
--bg: #ebe7e1;
|
|
||||||
--surface: #fdfcfa;
|
|
||||||
--text: #1a1a18;
|
|
||||||
--text2: #4a4844;
|
|
||||||
--text4: #8c8880;
|
|
||||||
--border: #ddd8d0;
|
|
||||||
--accent: #b07848;
|
|
||||||
}
|
|
||||||
|
|
||||||
html { background: var(--bg); color: var(--text); font-family: 'DM Mono', monospace; font-size: 14px; line-height: 1.6; }
|
|
||||||
|
|
||||||
body { max-width: 720px; margin: 0 auto; padding: 64px 32px 120px; }
|
|
||||||
|
|
||||||
/* Header */
|
|
||||||
.site-header { margin-bottom: 64px; padding-bottom: 28px; border-bottom: 1px solid var(--border); display: flex; align-items: baseline; justify-content: space-between; }
|
|
||||||
.logo { font-size: 22px; letter-spacing: -0.02em; color: var(--text); text-decoration: none; }
|
|
||||||
.logo span { font-family: 'Playfair Display', serif; font-style: italic; font-weight: 400; font-size: 13px; color: var(--text4); margin-left: 12px; }
|
|
||||||
|
|
||||||
/* Page title */
|
|
||||||
.page-title { font-family: 'Playfair Display', serif; font-size: 42px; font-weight: 400; letter-spacing: -0.02em; line-height: 1.1; margin-bottom: 12px; }
|
|
||||||
.page-subtitle { font-size: 13px; color: var(--text4); margin-bottom: 56px; line-height: 1.7; max-width: 500px; }
|
|
||||||
|
|
||||||
/* Steps */
|
|
||||||
.steps { display: flex; flex-direction: column; gap: 0; }
|
|
||||||
|
|
||||||
.step { display: flex; gap: 32px; padding: 32px 0; border-bottom: 1px solid var(--border); }
|
|
||||||
.step:first-child { border-top: 1px solid var(--border); }
|
|
||||||
|
|
||||||
.step-number {
|
|
||||||
font-family: 'Playfair Display', serif;
|
|
||||||
font-size: 32px;
|
|
||||||
font-weight: 400;
|
|
||||||
color: var(--border);
|
|
||||||
line-height: 1;
|
|
||||||
flex-shrink: 0;
|
|
||||||
width: 40px;
|
|
||||||
padding-top: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.step-content { flex: 1; }
|
|
||||||
.step-title { font-size: 15px; font-weight: 500; margin-bottom: 8px; color: var(--text); letter-spacing: 0.01em; }
|
|
||||||
.step-desc { font-size: 12px; color: var(--text2); line-height: 1.8; }
|
|
||||||
|
|
||||||
.step-fields { margin-top: 14px; display: flex; flex-direction: column; gap: 6px; }
|
|
||||||
.step-field { display: flex; align-items: baseline; gap: 12px; font-size: 11px; }
|
|
||||||
.step-field .label { color: var(--text4); letter-spacing: 0.08em; text-transform: uppercase; flex-shrink: 0; width: 160px; }
|
|
||||||
.step-field .val { color: var(--text2); }
|
|
||||||
|
|
||||||
/* Info box */
|
|
||||||
.info-box { margin-top: 56px; padding: 24px 28px; background: var(--surface); border-radius: 10px; border: 1px solid var(--border); box-shadow: 0 1px 3px rgba(0,0,0,0.06), 0 4px 16px rgba(0,0,0,0.05); }
|
|
||||||
.info-box-title { font-size: 10px; letter-spacing: 0.12em; color: var(--text4); text-transform: uppercase; margin-bottom: 10px; }
|
|
||||||
.info-box p { font-size: 12px; color: var(--text2); line-height: 1.8; }
|
|
||||||
|
|
||||||
/* Concept tags */
|
|
||||||
.concepts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 48px; }
|
|
||||||
.concept { padding: 6px 14px; background: var(--surface); border: 1px solid var(--border); border-radius: 20px; font-size: 11px; color: var(--text2); }
|
|
||||||
|
|
||||||
/* Footer */
|
|
||||||
.site-footer { margin-top: 80px; padding-top: 24px; border-top: 1px solid var(--border); font-size: 11px; color: var(--text4); display: flex; justify-content: space-between; align-items: center; }
|
|
||||||
.site-footer a { color: var(--text4); text-decoration: none; border-bottom: 1px solid var(--border); }
|
|
||||||
.site-footer a:hover { color: var(--text2); }
|
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
|
||||||
body { padding: 40px 20px 80px; }
|
|
||||||
.page-title { font-size: 32px; }
|
|
||||||
.step { gap: 20px; }
|
|
||||||
.step-number { font-size: 24px; width: 28px; }
|
|
||||||
.site-header { flex-direction: column; gap: 8px; }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<header class="site-header">
|
|
||||||
<a href="/" class="logo">RAPPORT <span>Studio Administration</span></a>
|
|
||||||
<span style="font-size: 10px; letter-spacing: 0.1em; color: var(--text4);">ALPHA 0.3</span>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<h1 class="page-title">Erste Schritte</h1>
|
|
||||||
<p class="page-subtitle">Rapport ist eine lokale Studio-Administrationssoftware für Architekturbüros. Alle Daten bleiben auf deinem Gerät — kein Server, kein Login.</p>
|
|
||||||
|
|
||||||
<div class="steps">
|
|
||||||
|
|
||||||
<div class="step">
|
|
||||||
<div class="step-number">1</div>
|
|
||||||
<div class="step-content">
|
|
||||||
<div class="step-title">Einstellungen konfigurieren</div>
|
|
||||||
<div class="step-desc">Bevor du beginnst, trage die Stammdaten deines Studios ein. Diese erscheinen auf allen Dokumenten und Rechnungen.</div>
|
|
||||||
<div class="step-fields">
|
|
||||||
<div class="step-field"><span class="label">Studio-Name</span><span class="val">Erscheint in der Sidebar und auf Druckdokumenten</span></div>
|
|
||||||
<div class="step-field"><span class="label">IBAN</span><span class="val">Für den QR-Einzahlungsschein auf Rechnungen (QR-IBAN empfohlen)</span></div>
|
|
||||||
<div class="step-field"><span class="label">MwSt-Satz</span><span class="val">Standardmässig 8.1 %</span></div>
|
|
||||||
<div class="step-field"><span class="label">Stundensätze</span><span class="val">Pro Rolle, werden für Honorarberechnungen verwendet</span></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="step">
|
|
||||||
<div class="step-number">2</div>
|
|
||||||
<div class="step-content">
|
|
||||||
<div class="step-title">Ersten Kunden anlegen</div>
|
|
||||||
<div class="step-desc">Unter <strong>Personen</strong> kannst du Kunden und Kontakte verwalten. Kunden werden mit Projekten und Rechnungen verknüpft. Name und Adresse sind für Dokumente erforderlich.</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="step">
|
|
||||||
<div class="step-number">3</div>
|
|
||||||
<div class="step-content">
|
|
||||||
<div class="step-title">Mitarbeiter erfassen</div>
|
|
||||||
<div class="step-desc">Unter <strong>Mitarbeiter</strong> legst du dein Team an. Wichtig sind Pensum, Wochenstunden und Eintrittsdatum — diese fliessen in die Zeiterfassung und Lohnabrechnung ein.</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="step">
|
|
||||||
<div class="step-number">4</div>
|
|
||||||
<div class="step-content">
|
|
||||||
<div class="step-title">Erstes Projekt erstellen</div>
|
|
||||||
<div class="step-desc">Unter <strong>Projekte</strong> erfasst du dein Bauvorhaben. Vergib eine Projektnummer, wähle den Auftraggeber und setze den Status. Optional kannst du eine Offerte verknüpfen, um das Stundenbudget abzuleiten.</div>
|
|
||||||
<div class="step-fields">
|
|
||||||
<div class="step-field"><span class="label">SIA-Phasen</span><span class="val">Aktiviere nur die für das Projekt relevanten Phasen</span></div>
|
|
||||||
<div class="step-field"><span class="label">Abrechnungsart</span><span class="val">Stundenbasis oder Pauschal</span></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="step">
|
|
||||||
<div class="step-number">5</div>
|
|
||||||
<div class="step-content">
|
|
||||||
<div class="step-title">Zeit erfassen</div>
|
|
||||||
<div class="step-desc">Unter <strong>Zeiterfassung</strong> buchst du Stunden auf Projekte und Phasen. Die Wochenansicht erlaubt das visuelle Planen per Drag & Drop. Der Monatssaldo zeigt jederzeit Stand bis heute.</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="step">
|
|
||||||
<div class="step-number">6</div>
|
|
||||||
<div class="step-content">
|
|
||||||
<div class="step-title">Erste Rechnung stellen</div>
|
|
||||||
<div class="step-desc">Unter <strong>Rechnungen</strong> erstellst du Rechnungen mit Positionen, MwSt und QR-Einzahlungsschein. Rechnungen lassen sich als PDF drucken und mit einem Status versehen (Entwurf → Gesendet → Bezahlt).</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="info-box">
|
|
||||||
<div class="info-box-title">Datenspeicherung</div>
|
|
||||||
<p>Alle Daten werden ausschliesslich lokal im Browser gespeichert (<code>localStorage</code>). Es gibt keinen Server, keine Cloud, keine Synchronisation. Erstelle regelmässig ein Backup über <strong>Einstellungen → Datenbank exportieren</strong>.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="concepts">
|
|
||||||
<span class="concept">Lokal gespeichert</span>
|
|
||||||
<span class="concept">Kein Login erforderlich</span>
|
|
||||||
<span class="concept">SIA 102 Honorare</span>
|
|
||||||
<span class="concept">QR-Rechnung</span>
|
|
||||||
<span class="concept">Lohnabrechnung</span>
|
|
||||||
<span class="concept">PDF-Export</span>
|
|
||||||
<span class="concept">Zeiterfassung</span>
|
|
||||||
<span class="concept">AGPL-3.0</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<footer class="site-footer">
|
|
||||||
<span>Rapport Alpha 0.3 — <a href="https://www.gnu.org/licenses/agpl-3.0.html" target="_blank">AGPL-3.0</a></span>
|
|
||||||
<a href="https://rapport.gabrielevarano.ch/">rapport.gabrielevarano.ch</a>
|
|
||||||
</footer>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
Generated
+12
-12
@@ -75,18 +75,6 @@ version = "1.0.102"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
|
checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rapport"
|
|
||||||
version = "0.6.0"
|
|
||||||
dependencies = [
|
|
||||||
"log",
|
|
||||||
"serde",
|
|
||||||
"serde_json",
|
|
||||||
"tauri",
|
|
||||||
"tauri-build",
|
|
||||||
"tauri-plugin-log",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayvec"
|
name = "arrayvec"
|
||||||
version = "0.7.6"
|
version = "0.7.6"
|
||||||
@@ -2760,6 +2748,18 @@ dependencies = [
|
|||||||
"rand_core 0.5.1",
|
"rand_core 0.5.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rapport"
|
||||||
|
version = "0.6.0"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"tauri",
|
||||||
|
"tauri-build",
|
||||||
|
"tauri-plugin-log",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "raw-window-handle"
|
name = "raw-window-handle"
|
||||||
version = "0.6.2"
|
version = "0.6.2"
|
||||||
|
|||||||
@@ -32,6 +32,9 @@
|
|||||||
"icons/128x128@2x.png",
|
"icons/128x128@2x.png",
|
||||||
"icons/icon.icns",
|
"icons/icon.icns",
|
||||||
"icons/icon.ico"
|
"icons/icon.ico"
|
||||||
]
|
],
|
||||||
|
"macOS": {
|
||||||
|
"signingIdentity": "-"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-1
@@ -28,7 +28,20 @@ const Documents = lazy(() => import("./views/Documents.jsx"));
|
|||||||
const PrintView = lazy(() => import("./print/PrintComponents.jsx").then(m => ({ default: m.PrintView })));
|
const PrintView = lazy(() => import("./print/PrintComponents.jsx").then(m => ({ default: m.PrintView })));
|
||||||
|
|
||||||
function ViewFallback() {
|
function ViewFallback() {
|
||||||
return <div style={{ padding: 40, color: "var(--text4)", fontSize: 12, letterSpacing: "0.08em" }}>LADEN…</div>;
|
return (
|
||||||
|
<div style={{ display: "flex", justifyContent: "center", alignItems: "center", minHeight: "calc(100vh - 60px)" }}>
|
||||||
|
<style>{`
|
||||||
|
@keyframes vf-spin { to { transform: rotate(360deg); } }
|
||||||
|
.vf-spinner {
|
||||||
|
width: 40px; height: 40px; border-radius: 50%;
|
||||||
|
border: 2px solid rgba(0,0,0,0.08);
|
||||||
|
border-top-color: rgba(0,0,0,0.45);
|
||||||
|
animation: vf-spin 0.9s linear infinite;
|
||||||
|
}
|
||||||
|
`}</style>
|
||||||
|
<div className="vf-spinner" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
|
|||||||
@@ -323,14 +323,6 @@ export default function Settings({ data, update, currentUser, uiZoom, setUiZoom
|
|||||||
<div>
|
<div>
|
||||||
{ConfirmModalEl}
|
{ConfirmModalEl}
|
||||||
|
|
||||||
{tab !== "profil" && (
|
|
||||||
<div className="filter-bar" style={{ marginBottom: 20 }}>
|
|
||||||
{TABS.map(t => (
|
|
||||||
<button key={t.id} onClick={() => setTab(t.id)} className={`pill${tab === t.id ? " active" : ""}`}>{t.label}</button>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* ── Profil-Tab ── */}
|
{/* ── Profil-Tab ── */}
|
||||||
{tab === "profil" && <PersonalSettings data={data} update={update} currentUser={currentUser} uiZoom={uiZoom || 1} setUiZoom={setUiZoom || (() => {})} nav={
|
{tab === "profil" && <PersonalSettings data={data} update={update} currentUser={currentUser} uiZoom={uiZoom || 1} setUiZoom={setUiZoom || (() => {})} nav={
|
||||||
<div className="filter-bar" style={{ marginBottom: 20 }}>
|
<div className="filter-bar" style={{ marginBottom: 20 }}>
|
||||||
@@ -409,6 +401,12 @@ export default function Settings({ data, update, currentUser, uiZoom, setUiZoom
|
|||||||
: null
|
: null
|
||||||
} />
|
} />
|
||||||
|
|
||||||
|
<div className="filter-bar" style={{ marginBottom: 20 }}>
|
||||||
|
{TABS.map(t => (
|
||||||
|
<button key={t.id} onClick={() => setTab(t.id)} className={`pill${tab === t.id ? " active" : ""}`}>{t.label}</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* ── Tab: Studio ── */}
|
{/* ── Tab: Studio ── */}
|
||||||
{tab === "studio" && (
|
{tab === "studio" && (
|
||||||
<>
|
<>
|
||||||
|
|||||||
Reference in New Issue
Block a user