import { Component, createEffect, createMemo, FlowComponent, onCleanup, onMount, JSX, useContext, splitProps, createSignal, Show, For, untrack, createResource, } from "solid-js"; import { createStore } from "solid-js/store"; import LufraiLogo from "~icons/custom/lufrai-logo"; import AppIcon from "~icons/custom/icon"; import ExternalLinkIcon from "~icons/carbon/launch"; import WarningIcon from "~icons/carbon/warning-alt-filled"; import LaunchIcon from "~icons/carbon/edit"; import DonationIcon from "~icons/bxs/donate-heart"; import FavoriteIcon from "~icons/carbon/favorite"; import FavoriteHalfIcon from "~icons/carbon/favorite-half"; import FavoriteFilledIcon from "~icons/carbon/favorite-filled"; import WatermarkIcon from "~icons/carbon/bullhorn"; import FreedomIcon from "~icons/noto/butterfly"; import FreeIcon from "~icons/noto/seedling"; import PrivacyIcon from "~icons/noto/princess"; import AgileIcon from "~icons/noto/person-bouncing-ball"; import ResultIcon from "~icons/noto/chequered-flag"; import HugIcon from "~icons/noto/hugging-face"; import VideoIcon from "~icons/carbon/video-filled"; import CloseIcon from "~icons/carbon/close-outline"; import Modal, { ModalCloseButton } from "./Modal"; import { LocalStoreContext } from "~/stores"; import createAccordion from "./Accordion"; import typer from "typer-js"; import "typer-js/dist/typer.min.css"; import { externalLink, getDisplayDate, getDomain, getHost, onClickFocus, } from "~/util"; import { capitalize, clamp, shuffle } from "froebel"; import { markdownHelpUrl } from "./Markdown"; import AgileCalculator from "./AgileCalculator"; import server from "solid-start/server"; import { getLikes, increaseLikes } from "~/server/likes"; export const description = "Räppli ist eine freie Web App zur Erstellung von Schweizerischen Rechnungen inklusive QR-Code. Erfasse deine Rechnungspositionen und erhalte unmittelbar eine druckbare Rechnung."; const externalLinkClass = "inline-flex items-center gap-1"; import ConfettiExplosion from "solid-confetti-explosion"; // TODO: after solid-start update >= alpha.95, switch to lazy // const ConfettiExplosion = lazy(() => import("solid-confetti-explosion")); const ExternalLink: FlowComponent< JSX.AnchorHTMLAttributes > = (p) => { const [props, rest] = splitProps(p, ["children"]); return ( {props.children} ); }; const WelcomeModal: Component = (props) => { const [localState, setLocalState, localStateMounted] = useContext(LocalStoreContext)!; const [AccordionItem] = createAccordion(); let subtitleEl: HTMLSpanElement = undefined!; const isOpen = createMemo(() => { return localStateMounted() && localState.showWelcome; }); const [showTrailer, setShowTrailer] = createSignal(false); const increaseCount_ = server(increaseLikes); const [likes] = createResource(server(getLikes)); onMount(function () { let adjectives = [ "Schweizerischen", "anständigen", "umfassenden", "erfrischenden", "erfreulichen", "sauberen", "übersichtlichen", ]; let nouns = ["Rechnung", "Auftragsbestätigung", "Offerte"]; let combinations: [string, string][] = []; for (const adjective of adjectives) { for (const noun of nouns) { combinations.push([adjective, noun]); } } const firstCombination = combinations.splice(0, 1)[0]; combinations = shuffle(combinations); combinations.unshift(firstCombination!); let typerInstance = typer(subtitleEl, { min: 60, max: 160 }); let lastAdjective = ""; let lastNoun = ""; for (const [adjective, noun] of combinations) { const first = lastAdjective === ""; if (lastAdjective === adjective) { typerInstance.back(lastNoun.length, 80).continue(noun); } else { const method = first ? "line" : "continue"; typerInstance .back("all", 65) [method]( `${adjective} ${noun}`, first ? { min: 60, max: 70 } : undefined ); } typerInstance.pause(first ? 4181 : 6765); lastNoun = noun; lastAdjective = adjective; } typerInstance.back("all", 50).repeat(Infinity); let halted = false; createEffect(function () { if (!isOpen()) { halted = typerInstance.halt() === undefined; } else { try { // typer-js has some weird logic how it handles halt / resume. Essentially if halt wasn't executed before of resume, resume breaks completely halted && typerInstance.resume(); } catch (err) { if (!(err as TypeError).message.endsWith("is not a function")) { console.dir(err); } } halted = false; } }); onCleanup(function () { typerInstance.kill(); }); }); const ShareonLink: Component<{ provider: string; via?: string }> = ( props ) => ( ); // I hope Randomness will guarantee a fair sequence <3 const thankYouRahelAndFredi = shuffle([ <> Fredi Niklaus ( RemedyIT ) , "Rahel Lutz", ]); thankYouRahelAndFredi.splice(1, 0, " und "); const [likeCount, setLikeCount] = createSignal(0); const [confetti, setConfetti] = createStore([false, false, false]); const confettiDuration = 2000; createEffect(function () { if (likeCount() == 0) { return; } untrack(function () { for (const idx of confetti.keys()) { if (confetti[idx]) { continue; } setConfetti(idx, true); setTimeout( () => setConfetti(idx, false), (confettiDuration / 100) * 80 ); break; } }); }); return (
Räppli
Der reibungslose Weg zur{" "}
{() => (
)}
Teile es auf:

Einleitung

{description}

Du möchtest dich selbstständig machen, gründest gerade ein Startup oder einen{" "} Verein und musst in der Lage sein{" "} Rechnungen, Offerten und Auftragsbestätigungen zu verschicken? Du möchtest dabei unabhängig{" "} bleiben? Dann bist du hier genau richtig!

Vorteile von Räppli:

  • Die praktische Vorschau zeigt dir sofort das Endergebnis.
  • Deine Daten bleiben{" "} bei dir .
  • Räppli ist und bleibt komplett kostenlos!
  • Der Quellcode ist{" "} vollumfänglich öffentlich. Räppli kann selbst gehostet werden!
  • Du arbeitest{" "} agil ? Räppli kann dir dabei helfen einen Preis zu kalkulieren!

Wieso ist Räppli komplett{" "} kostenlos?

Weil moderne Rechnungsstellung für alle Menschen möglich sein sollte!

Jeder Selbstständige kommt wohl irgendwann an den Punkt, dass er eine Rechnung schreiben muss. Doch eine moderne Rechnung zu schreiben, die heutige Erwartungen erfüllt, ist gar nicht so einfach und braucht viel Zeit. So werden viele Selbstständige zum Einsatz von komplexer und oftmals teurer "ERP"-Software oder zu Outsourcing gedrängt. Menschen die sich mit wenig Startkapital selbstständig machen wollen, stehen vor einer schwierigen Wahl.

Eines der wesentlichen Ziele von{" "} Lufrai ist, Menschen dabei zu unterstützen aus eigener Kraft unabhängig zu werden und ihrem eigenen Lebenssinn zu folgen.{" "} Befreie deine Stimme!

Räppli soll ein Beweis dafür darstellen, dass Selbstlosigkeit auch ohne teure, zentralisierte, staatliche Lösungen möglich ist. Der gesamte Quellcode von Räppli steht offen verfügbar.{" "} Erfahre mehr

Zu guter Letzt ist Räppli auch eine Referenzarbeit. Sie soll zeigen was ich (Katja) als Web-Entwicklerin drauf habe. Denn im mündlichen Gespräch verkaufe ich meine Fähigkeiten leider wie eine absolute Niete und wirke mit einer Grösse von 1.9 Metern etwas abschreckend. Verkauf ist nicht meine Stärke.

Was ist Lufrai?

Lufrai ist die Einzelfirma von{" "} Katja Lutz . Sie setzt sich als Web-Entwicklerin, Künstlerin und Aktivistin für eine unabhängige, freie Schweiz ein und unterstützt ihre souveränen Mitmenschen, das Steuer selbst in die Hand zu nehmen. Erfahre mehr

Grundsätze:

  1. Zuoberst steht der Mensch.
  2. Selbstverantwortlich zu leben heisst, zu geben und anzunehmen.
    Miteinander zu leben heisst, zu vergeben.
  3. Erkenntnis kommt von Innen und Altruismus kann nicht erzwungen werden.
  4. Nötigung drängt den Horizont zusammen, Aufklärung erweitert ihn.
  5. Gleichheit setzt voraus, sich auf Augenhöhe zu begegnen und Privatsphäre zu respektieren.
  6. Achtsam ist, wer global denkt, aber lokal handelt.
    Gute Entscheidungen trifft, wer die Konsequenzen begreift.
  7. Der Technik die Entscheidung zu überlassen heisst, selbst zur Maschine zu werden.
  8. Schönheit ist nicht selbstverständlich, sie entspringt aus der Bereitschaft zur Veränderung.
  9. Anführer zeichnen sich nicht durch ihre Lautstärke und Forderung aus, sondern durch Selbstlosigkeit und Transparenz.
  10. Zensur betreibt, wer etwas verbergen will.

Das Projekt unterstützen

Danke dass du das Projekt und damit auch den Fortbestand von Lufrai unterstützen möchtest!

Teilen

Teile Räppi unter deinen Freunden und Bekannten was das Zeug hält! Lufrai investiert kein Geld in teures Marketing, aus der Überzeugung, dass es auf unserer Welt bereits genug davon gibt.

Spenden

Räppli 1.0 wurde mit einem Aufwand von fast 4 Wochen entwickelt, " Lufrai - Katja Lutz" hat somit etwa 18'000 CHF in die Verwirklichung von diesem Projekt investiert.{" "} Herzlichen Dank, dass du dich daran beteiligen möchtest!

Kontoinformationen

Mitwirkung / Feedback

Für Feedbacks, bitte beachte den entsprechenden{" "} FAQ-Abschnitt .

Du bist ein Web-Entwickler, verstehst Javascript / Typescript wie deine Westentasche und möchtest Räppli verbessern? Hurra! Bitte schaue dir den Open Source{" "} Abschnitt an.

Open Source

Du hast richtig gehört, Räppli ist Open Source! Jeder kann Räppli kopieren, verteilen und erweitern. Du brauchst also keine Angst zu haben, dass du irgendwann keine Rechnungen mehr schreiben darfst. Lizenziert ist Räppli mit{" "} MIT . Git-Repository
Falls du dich dort zur Mitwirkung registrieren möchtest: Bitte schreibe mir nach deiner Registrierung ein kurzes Mail mit deiner Motivation an "contact(at)lufrai.org", damit ich dich freischalten kann.

Eingesetzte Technologien (Nur um einige zu nennen):

Danksagungen

An dieser Stelle möchte ich (Katja) mich bei der Community von{" "} Solid {" "} bedanken, nicht nur für ihr verblüffend effektives Open Source Web-Framework, sondern auch für ihre Offenheit, Anregungen und cleveren Tipps!

Ausserdem möchte ich mich insbesondere bei {thankYouRahelAndFredi}{" "} herzlichst bedanken, welche mir stets bei der Umsetzung meiner kurligen Projekte unterstützend zur Seite standen und mich immer inspirierten, einen Schritt weiterzugehen!

Mein herzlicher Dank gilt zudem auch{" "} Kohei Asai {" "} ( Twitter ) , welcher mir sehr grosszügig seine Rechte am Paketnamen "rappli" auf{" "} npmjs.com{" "} übertragen hat.

Häufig gestellte Fragen

  • Deine eingegebenen Daten werden an keine Server übermittelt.
  • Einige deiner Daten, wie z.B. Bankverbindung, Logo und Zahlungsbedingungen verbleiben im{" "} Speicher {" "} von deinem Browser. So musst du sie nicht jedes Mal neu erfassen, wenn du eine Rechnung schreiben willst.
  • Damit das Internet und somit auch Räppli überhaupt funktionieren, müssen jedoch unweigerlich einige Daten übertragen werden, wie z.B. deine IP-Adresse. Erfahre{" "} hier {" "} wie das Internet funktioniert.
Deine Daten werden auf keinem Server gespeichert. Lerne aus dem Malheur und speichere ab sofort regelmässig{" "} ! Nein, vorausgesetzt du verwendest das offizielle Räppli über rappli.ch und keine modizifierte Version. Lufrai legt Wert auf deine Privatsphäre. Es werden keine Nutzungsdaten an Google, Facebook oder ähnliche Riesen übermittelt. 4. Ich habe einen Anpassungswunsch!
Kann die App bitte gratis angepasst werden? } alignCenter={false} > Räppli ist Open Source und wird grundsätzlich von Lufrai{" "} weiterentwickelt. Für eine optimale Weiterentwicklung ist dein Feedback sehr wichtig und ich (Katja) bin für dein Feedback und deine Ideen dankbar! Jedoch besteht keine Garantie dafür, dass jedes Feedback beantwortet / umgesetzt werden kann, die Entwicklung ist aufwändig und kein Wunschkonzert. Kontaktiere Lufrai auf{" "} Kontakt {" "} oder erstelle ein Issue auf dem{" "} Git-Repository.
5. Wie funktionieren Agile Positionen?
} alignCenter={false} >

Agile Positionen können dir dabei helfen, Arbeitsaufwand (Zeit) zu schätzen.

Der Preis von agilen Positionen wird aus Story Points, einem Umrechnungssatz "Stunden pro Story Point", dem Risiko Faktor und dem Stundensatz ("Einzelpreis") berechnet.

Was sind Story Points?

Story Points sind relative Punktzahlen. Weise all deinen Positionen Story Points zu, die im Verhältnis zueinander stimmen. Vergleiche dazu deine Positionen und überlege dir, welche davon schwieriger sind und welche einfacher. Wie viel schwieriger ist eine Position (Arbeitsaufwand) im Vergleich zu einer anderen?

Nachdem du die Story Points zugewiesen hast, kannst du dir überlegen, wie viel Stunden ein einzelner Story Point wert ist, trage diesen in den "Dokument"-Einstellungen unter "Stunden pro Story Point" ein.

Erfahre mehr über Story Points

Was ist der Risiko Faktor?

Aufwandschätzungen sind eine riskante Angelegenheit. Räppli erlaubt dir deshalb für den geschätzten, optimalen Fall "Story Points Minimum" und für den schlimmsten Fall "Story Points Maximum" anzugeben.
Der Risiko Faktor wird in den "Dokument"-Einstellungen eingegeben und er entscheidet über die Gewichtung der minimalen und maximalen Story Points:

  • Risiko Faktor von 0%: Es existiert kein Risiko, nur die minimalen{" "} Story Points werden beachtet!
  • Risiko Faktor von 70%:{" "} 30% von den Minimalen, und{" "} 70% von den maximalen Story Points werden beachtet.
  • Risiko Faktor von 100%: Der Worst-Case ist alternativlos,{" "} nur die maximalen Story Points werden beachtet!

Räppli wurde für Geräte mit grösseren Bildschirmen wie z.B. Laptops und Computer programmiert. Die besten Druckergebnisse werden erfahrungsgemäss mit dem Browser "Mozilla Firefox" erreicht, jedoch sind auch "Google Chrome" basierte Browser geeignet. Verwende einen aktuellen Browser!

7. Können Fliesstexte formatiert werden?
Was ist Markdown?
} alignCenter={false} >

Du kannst deinen Text formatieren, indem du ihn mit ganz bestimmten Zeichen versiehst! Welche Zeichen das sind, wird durch den "Markdown"-Standard definiert.

Erfahre{" "} hier {" "} wie Markdown im Detail funktioniert!

Kurzbeispiel:

Dein Text:

                      {["- *Pizza*", "- **Gemüse**", "- ***Salat***"].join(
                        "\n"
                      )}
                    

Ausgabe:

  • Pizza
  • Gemüse
  • Salat
8. Kann Räppli lokal installiert werden?
} alignCenter={false} >

Räppli kann lokal installiert werden, jedoch ist es für den Betrieb auf Servern optimiert. Das heisst: auch wenn du Räppli installiert hast, musst du deinen Webbrowser nutzen, um Räppli zu öffnen.

{" "} Für die Installation sind grundlegende Kenntnisse im Umgang mit der Kommandozeile empfohlen!

Voraussetzungen:

Installation Räppli

Führe folgenden Befehl aus:

npm install -g rappli

Räppli starten

Führe folgenden Befehl aus, um Räppli zu starten

rappli

Sobald die Meldung "Listening on port 3000" erscheint, kannst du dein lokales Räppli auf deinem Browser über{" "} http://localhost:3000 {" "} erreichen.

9. Wie präzise wurden die SIX QR-Rechnung Vorgaben umgesetzt? } alignCenter={false} >

Es handelt sich bewusst nicht um eine Pixel-genaue Umsetzung der Vorgaben von SIX. Das Design der QR-Rechnung orientiert sich am Grundsatz des pragmatischen Perfektionismus. Das heisst: es wurden die Möglichkeiten des Design Frameworks "Tailwind CSS" genutzt, um die Vorgaben von SIX möglichst genau umzusetzen, aber da dabei nicht die unerschöpflichen Mittel der Schweizer Regierung zur Verfügung standen, wurde das Rad nicht komplett neu erfunden.

10. Haftungsausschluss} alignCenter={false} >

Räppli ({getDomain()}) verwendest du{" "} eigenverantwortlich. "Lufrai - Katja Lutz" (Einzelfirma) und "Katja Lutz" (Mensch) übernehmen keine Haftung.

Es besteht kein Anspruch auf die Verfügbarkeit von{" "} {getDomain()}. Falls du 100% sicher sein willst, dass du Räppli auch in aussergewöhnlichen Zeiten verwenden kannst, besorge dir den Quellcode jetzt und{" "} installiere Räppli lokal .

Spenden
Loslegen
Version: {__APP_VERSION__} {getDisplayDate(new Date(__BUILD_TIME__))}
); }; export default WelcomeModal;