import {
Component ,
createEffect ,
createMemo ,
FlowComponent ,
onCleanup ,
onMount ,
JSX ,
useContext ,
splitProps ,
} from "solid-js" ;
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/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 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 ,
shuffle ,
} from "~/util" ;
import { capitalize } from "froebel" ;
import { markdownHelpUrl } from "./Markdown" ;
import AgileCalculator from "./AgileCalculator" ;
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" ;
const ExternalLink : FlowComponent <
JSX . AnchorHTMLAttributes < HTMLAnchorElement >
> = ( p ) = > {
const [ props , rest ] = splitProps ( p , [ "children" ] ) ;
return (
< a class = { externalLinkClass } { ...externalLink } { ...rest } >
{ props . children }
< ExternalLinkIcon / >
< / a >
) ;
} ;
const WelcomeModal : Component = ( props ) = > {
const [ localState , setLocalState , localStateMounted ] =
useContext ( LocalStoreContext ) ! ;
const [ AccordionItem ] = createAccordion ( ) ;
let subtitleEl : HTMLSpanElement = undefined ! ;
const isOpen = createMemo ( ( ) = > {
return localStateMounted ( ) && localState . showWelcome ;
} ) ;
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 != "u.resume is not a function" ) {
console . dir ( err ) ;
}
}
halted = false ;
}
} ) ;
onCleanup ( function ( ) {
typerInstance . kill ( ) ;
} ) ;
} ) ;
const ShareonLink : Component < { provider : string ; via? : string } > = (
props
) = > (
< a
class = { props . provider + " shadow" }
title = { capitalize ( props . provider ) }
data - via = { props . via }
aria - label = { ` Share on ${ capitalize ( props . provider ) } ` }
> < / a >
) ;
// I hope Randomness will guarantee a fair sequence <3
const thankYouRahelAndFredi = shuffle ( [
< >
Fredi Niklaus (
< a
class = { externalLinkClass }
href = "https://www.remedyit.ch/"
{ . . . externalLink }
>
RemedyIT < ExternalLinkIcon / >
< / a >
)
< / > ,
"Rahel Lutz" ,
] ) ;
thankYouRahelAndFredi . splice ( 1 , 0 , " und " ) ;
return (
< Modal open = { isOpen ( ) } >
< div class = "hidden lg:block" >
< ModalCloseButton onClick = { ( ) = > setLocalState ( "showWelcome" , false ) } / >
< / div >
< div class = "max-h-[60vh] overflow-y-auto px-2" >
< div class = "min-h-[60vh] flex items-center justify-center" >
< div >
< div class = "flex flex-col items-center justify-around" >
< div class = "mt-3 mb-3 text-6xl lg:text-8xl flex items-end lg:w-[370px] justify-between gap-2 lg:gap-0 font-bold tracking-tighter leading-none text-swiss-red fill-current" >
< AppIcon class = "w-auto h-[0.9em]" / >
< div > R ä ppli < / div >
< / div >
< div class = "flex flex-col items-stretch" >
< div class = "flex justify-center" >
< div class = "text-gray-800 text-sm lg:text-base tracking-widest mb-4 flex gap-1 flex-col items-center lg:flex-row" >
Der reibungslose Weg zur { " " }
< span class = "ignore-white-space" ref = { subtitleEl } > < / span >
< / div >
< / div >
< / div >
< div class = "flex justify-end lg:w-[410px] max-w-full" >
< a
href = "https://lufrai.org"
class = "text-lufrai-primary-darker hover:text-lufrai-primary transition-colors fill-current text-base flex items-center leading-tight gap-2 tracking-tighter font-bold border-b border-lufrai-primary-light border-opacity-20 pb-1"
{ . . . externalLink }
>
< span > made < / span >
< span > by < / span >
< LufraiLogo class = "w-auto h-[1.5em]" / >
< / a >
< / div >
< / div >
< div class = "mt-28 text-base flex flex-wrap text-center gap-7 items-center justify-center" >
< a
class = "link text-secondary-focus hover:text-secondary"
href = "#welcome-quickstart"
>
Einleitung
< / a >
< a
class = "link text-secondary-focus hover:text-secondary"
href = "#welcome-why-free"
>
Wieso ist R ä ppli < br / >
< strong > komplett kostenlos < / strong > ?
< / a >
< a
class = "link text-secondary-focus hover:text-secondary"
href = "#welcome-lufrai"
>
Was ist Lufrai ?
< / a >
< a
class = "link text-secondary-focus hover:text-secondary"
href = "#welcome-patron"
>
Das Projekt
< br / >
unterst ü tzen
< / a >
< a
class = "link text-secondary-focus hover:text-secondary flex items-center gap-2"
href = "#welcome-opensource"
>
Open Source
< / a >
< a
class = "link text-secondary-focus hover:text-secondary flex items-center gap-2"
href = "#welcome-thankyou"
>
Danksagungen
< / a >
< a
class = "link text-secondary-focus hover:text-secondary"
title = "Häufig gestellte Fragen"
href = "#welcome-faq"
>
FAQ
< / a >
< / div >
< div
class = "mt-16 flex flex-wrap gap-3 items-center justify-center"
id = "welcome-social"
>
< div class = "text-sm text-slate-600" > Teile es auf : < / div >
< div
class = "shareon flex flex-wrap items-center justify-center"
data - title = "Hast du schon von Räppli gehört? Es ist ein praktisches Web App, womit Schweizer QR Rechnungen inkl. Rechnungspositionen erstellt werden können und es ist komplett kostenlos! Probiere es aus unter:"
data - url = { getHost ( ) }
>
< ShareonLink provider = "mastodon" / >
< ShareonLink provider = "telegram" / >
< ShareonLink provider = "reddit" / >
< ShareonLink provider = "odnoklassniki" / >
< ShareonLink provider = "pinterest" / >
< ShareonLink provider = "pocket" / >
< ShareonLink provider = "viber" / >
< ShareonLink provider = "vkontakte" / >
< ShareonLink provider = "linkedin" / >
< ShareonLink provider = "twitter" via = "katy_wings" / >
< ShareonLink provider = "facebook" / >
< ShareonLink provider = "whatsapp" / >
< / div >
< / div >
< / div >
< / div >
< div class = "mt-20 prose text-opacity-100" >
< section >
< h2 id = "welcome-quickstart" > Einleitung < / h2 >
< p class = "text-xl font-light lead" > { description } < / p >
< p >
Du m ö chtest dich < strong > selbstst ä ndig machen < / strong > , gr ü ndest
gerade ein < strong > Startup < / strong > oder einen { " " }
< strong > Verein < / strong > und musst in der Lage sein { " " }
< strong > Rechnungen , Offerten und Auftragsbest ä tigungen < / strong > zu
verschicken ? Du m ö chtest dabei < strong > unabh ä ngig < / strong > { " " }
bleiben ? Dann bist du hier genau richtig !
< / p >
< p > Vorteile von R ä ppli : < / p >
< ul >
< li >
< ResultIcon class = "inline-block scale-150 mr-2" / > Die
praktische Vorschau zeigt dir sofort das Endergebnis .
< / li >
< li >
< PrivacyIcon class = "inline-block scale-150 mr-2" / >
Deine Daten bleiben { " " }
< a onClick = { onClickFocus } href = "#welcome-privacy" >
bei dir
< / a >
.
< / li >
< li >
< FreeIcon class = "inline-block scale-150 mr-2" / > R ä ppli ist und
bleibt < a href = "#welcome-why-free" > komplett kostenlos < / a > !
< / li >
< li >
< FreedomIcon class = "inline-block scale-150 mr-2" / > Der
Quellcode ist { " " }
< a href = "#welcome-opensource" > vollumf ä nglich ö ffentlich < / a > .
R ä ppli kann selbst gehostet werden !
< / li >
< li >
< AgileIcon class = "inline-block scale-150 mr-2" / > Du arbeitest { " " }
< a onClick = { onClickFocus } href = "#welcome-agile" >
agil
< / a >
? R ä ppli kann dir dabei helfen einen Preis zu kalkulieren !
< / li >
< / ul >
< / section >
< section class = "mt-16" >
< h2 id = "welcome-why-free" >
Wieso ist < span class = "text-swiss-red" > R ä ppli < / span > komplett { " " }
< span class = "text-swiss-red" > kostenlos < / span > ?
< / h2 >
< p class = "text-xl font-light lead" >
Weil moderne Rechnungsstellung f ü r alle Menschen m ö glich sein
sollte !
< / p >
< p >
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 .
< / p >
< p >
Eines der wesentlichen Ziele von { " " }
< a href = "#welcome-lufrai" > Lufrai < / a > ist , Menschen dabei zu
unterst ü tzen aus eigener Kraft unabh ä ngig zu werden und ihrem
eigenen Lebenssinn zu folgen . { " " }
< strong >
< i > Befreie deine Stimme ! < / i >
< / strong >
< / p >
< p >
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 . { " " }
< a href = "#welcome-opensource" > Erfahre mehr < / a >
< / p >
< p >
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 .
< / p >
< / section >
< section class = "mt-16" >
< h2 id = "welcome-lufrai" >
Was ist < span class = "text-lufrai-primary" > Lufrai < / span > ?
< / h2 >
< p >
Lufrai ist die Einzelfirma von { " " }
< a
class = { externalLinkClass }
href = "https://lufrai.org/katjalutz"
{ . . . externalLink }
>
Katja Lutz < ExternalLinkIcon / >
< / a >
. 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 .
< a
class = "btn btn-sm inline-flex ml-3 items-center gap-1"
href = "https://lufrai.org"
{ . . . externalLink }
>
Erfahre mehr < ExternalLinkIcon / >
< / a >
< / p >
< p > Grunds ä tze : < / p >
< ol class = "prose-sm" >
< li > Zuoberst steht der Mensch . < / li >
< li >
Selbstverantwortlich zu leben heisst , zu geben und anzunehmen .
< br / >
Miteinander zu leben heisst , zu vergeben .
< / li >
< li >
Erkenntnis kommt von Innen und Altruismus kann nicht erzwungen
werden .
< / li >
< li >
N ö tigung dr ä ngt den Horizont zusammen , Aufkl ä rung erweitert ihn .
< / li >
< li >
Gleichheit setzt voraus , sich auf Augenh ö he zu begegnen und
Privatsph ä re zu respektieren .
< / li >
< li >
Achtsam ist , wer global denkt , aber lokal handelt . < br / >
Gute Entscheidungen trifft , wer die Konsequenzen begreift .
< / li >
< li >
Der Technik die Entscheidung zu ü berlassen heisst , selbst zur
Maschine zu werden .
< / li >
< li >
Sch ö nheit ist nicht selbstverst ä ndlich , sie entspringt aus der
Bereitschaft zur Ver ä nderung .
< / li >
< li >
Anf ü hrer zeichnen sich nicht durch ihre Lautst ä rke und Forderung
aus , sondern durch Selbstlosigkeit und Transparenz .
< / li >
< li > Zensur betreibt , wer etwas verbergen will . < / li >
< / ol >
< / section >
< section class = "mt-16" >
< h2 id = "welcome-patron" > Das Projekt unterst ü tzen < / h2 >
< p class = "text-xl font-light lead" >
Danke dass du das Projekt und damit auch den Fortbestand von
Lufrai unterst ü tzen m ö chtest !
< / p >
< h3 > Teilen < / h3 >
< p >
< a href = "#welcome-social" > Teile < / a > 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 .
< / p >
< h3 > Spenden < / h3 >
< p >
R ä ppli 1.0 wurde mit einem Aufwand von fast 4 Wochen entwickelt , "
< a href = "#welcome-lufrai" > Lufrai - Katja Lutz < / a > " hat somit etwa
18 ' 000 CHF in die Verwirklichung von diesem Projekt investiert . { " " }
< strong >
Herzlichen Dank , dass du dich daran beteiligen m ö chtest !
< / strong >
< / p >
< a
href = "https://lufrai.org/spenden/"
class = { ` btn btn-sm btn-secondary bg-purple-600 border-purple-600 ${ externalLinkClass } ` }
{ . . . externalLink }
>
Kontoinformationen < ExternalLinkIcon / >
< / a >
< h3 > Mitwirkung / Feedback < / h3 >
< p >
F ü r Feedbacks , bitte beachte den entsprechenden { " " }
< a href = "#welcome-feedback" onClick = { onClickFocus } >
FAQ - Abschnitt
< / a >
.
< / p >
< p >
Du bist ein Web - Entwickler , verstehst Javascript / Typescript wie
deine Westentasche und m ö chtest R ä ppli verbessern ? Hurra ! Bitte
schaue dir den < a href = "#welcome-opensource" > Open Source < / a > { " " }
Abschnitt an .
< / p >
< / section >
< section class = "mt-16" >
< h2 id = "welcome-opensource" > Open Source < / h2 >
< p >
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 { " " }
< ExternalLink href = "https://git.lufrai.com/rappli/rappli/src/branch/master/LICENSE" >
MIT
< / ExternalLink >
.
< a
class = "btn btn-sm inline-flex ml-3 items-center gap-1"
href = "https://git.lufrai.com/rappli/rappli"
{ . . . externalLink }
>
Git - Repository
< ExternalLinkIcon / >
< / a >
< br / >
< strong >
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 .
< / strong >
< / p >
< p >
Eingesetzte Technologien ( < small > Nur um einige zu nennen < / small > ) :
< / p >
< ul >
< li >
< a
class = { externalLinkClass }
href = "https://www.solidjs.com/"
{ . . . externalLink }
>
Solid
< ExternalLinkIcon / >
< / a >
< / li >
< li >
< a
class = { externalLinkClass }
href = "https://tailwindcss.com/"
{ . . . externalLink }
>
Tailwind CSS
< ExternalLinkIcon / >
< / a >
< / li >
< li >
< a
class = { externalLinkClass }
href = "https://daisyui.com/"
{ . . . externalLink }
>
daisyUI
< ExternalLinkIcon / >
< / a >
< / li >
< li >
< a
class = { externalLinkClass }
href = "https://sortablejs.github.io/Sortable/"
{ . . . externalLink }
>
Sortable
< ExternalLinkIcon / >
< / a >
< / li >
< li >
< a
class = { externalLinkClass }
href = "https://remark.js.org/"
{ . . . externalLink }
>
remark
< ExternalLinkIcon / >
< / a >
< / li >
< / ul >
< / section >
< section class = "mt-16" >
< h2 id = "welcome-thankyou" > Danksagungen < / h2 >
< p >
An dieser Stelle m ö chte ich ( Katja ) mich bei der Community von { " " }
< a
class = { externalLinkClass }
href = "https://www.solidjs.com/"
{ . . . externalLink }
>
Solid < ExternalLinkIcon / >
< / a > { " " }
bedanken , nicht nur f ü r ihr verbl ü ffend effektives Open Source
Web - Framework , sondern auch f ü r ihre Offenheit , Anregungen und
cleveren Tipps !
< / p >
< p >
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 !
< / p >
< p >
Mein herzlicher Dank gilt zudem auch { " " }
< ExternalLink href = "https://www.kohei.dev/en-us" >
Kohei Asai
< / ExternalLink > { " " }
< small >
(
< ExternalLink href = "https://twitter.com/axross_" >
Twitter
< / ExternalLink >
)
< / small >
, welcher mir sehr grossz ü gig seine Rechte am Paketnamen "rappli"
auf { " " }
< ExternalLink href = "https://npmjs.com" > npmjs . com < / ExternalLink > { " " }
ü bertragen hat .
< / p >
< / section >
< section class = "mt-16" >
< h2 id = "welcome-faq" > H ä ufig gestellte Fragen < / h2 >
< div class = "text-black" >
< AccordionItem
id = "welcome-privacy"
label = { "1. Wo werden welche Daten gespeichert?" }
alignCenter = { false }
>
< ul >
< li >
Deine eingegebenen Daten werden an keine Server ü bermittelt .
< / li >
< li >
Einige deiner Daten , wie z . B . Bankverbindung , Logo und
Zahlungsbedingungen verbleiben im { " " }
< span
class = "text-title-border"
title = "Der sogennante localStorage"
>
Speicher
< / span > { " " }
von deinem Browser . So musst du sie nicht jedes Mal neu
erfassen , wenn du eine Rechnung schreiben willst .
< / li >
< li >
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 { " " }
< a
class = { externalLinkClass }
href = "https://t3n.de/news/tcp-ip-internet-grundlagen-755667/"
{ . . . externalLink }
>
hier
< ExternalLinkIcon / >
< / a > { " " }
wie das Internet funktioniert .
< / li >
< / ul >
< / AccordionItem >
< AccordionItem
label = "2. Ich habe vergessen zu speichern, was nun?!"
alignCenter = { false }
>
Deine Daten werden auf keinem Server gespeichert . Lerne aus dem
Malheur und speichere ab sofort regelm ä ssig { " " }
< HugIcon class = "inline" / > !
< / AccordionItem >
< AccordionItem label = "3. Werden meine Nutzungsdaten zu Marketingzwecken gesammelt?" >
< strong > Nein < / strong > , 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 .
< / AccordionItem >
< AccordionItem
id = "welcome-feedback"
label = {
< >
4 . Ich habe einen Anpassungswunsch !
< br / >
Kann die App bitte gratis angepasst werden ?
< / >
}
alignCenter = { false }
>
R ä ppli ist < a href = "#welcome-opensource" > Open Source < / a > und
wird grunds ä tzlich von < a href = "#welcome-lufrai" > Lufrai < / a > { " " }
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 { " " }
< a
href = "https://lufrai.org/impressum/"
class = { externalLinkClass }
{ . . . externalLink }
>
Kontakt < ExternalLinkIcon / >
< / a > { " " }
oder erstelle ein Issue auf dem { " " }
< a href = "#welcome-opensource" > Git - Repository < / a > .
< / AccordionItem >
< AccordionItem
id = "welcome-agile"
label = {
< div >
5 . Wie funktionieren < strong > Agile Positionen < / strong > ?
< / div >
}
alignCenter = { false }
>
< p class = "!mt-0 text-lg font-light lead" >
Agile Positionen k ö nnen dir dabei helfen , Arbeitsaufwand
( Zeit ) zu sch ä tzen .
< / p >
< p >
Der Preis von agilen Positionen wird aus Story Points , einem
Umrechnungssatz "Stunden pro Story Point" , dem Risiko Faktor
und dem Stundensatz ( "Einzelpreis" ) berechnet .
< / p >
< h3 > Was sind Story Points ? < / h3 >
< p >
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 ?
< / p >
< p >
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 .
< / p >
< a
href = "https://www.agile-academy.com/de/product-owner/was-sind-story-points/"
class = { externalLinkClass }
{ . . . externalLink }
>
Erfahre mehr ü ber Story Points
< ExternalLinkIcon / >
< / a >
< h3 > Was ist der Risiko Faktor ? < / h3 >
< p >
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 .
< br / >
< strong >
Der Risiko Faktor wird in den "Dokument" - Einstellungen
eingegeben und er entscheidet ü ber die Gewichtung der
minimalen und maximalen Story Points :
< / strong >
< / p >
< ul class = "mb-8" >
< li >
Risiko Faktor von < span class = "underline" > 0 % < / span > : Es
existiert kein Risiko , < strong > nur die minimalen < / strong > { " " }
Story Points werden beachtet !
< / li >
< li >
Risiko Faktor von < span class = "underline" > 70 % < / span > : { " " }
< strong > 30 % von den Minimalen < / strong > , und { " " }
< strong > 70 % von den maximalen < / strong > Story Points werden
beachtet .
< / li >
< li >
Risiko Faktor von < span class = "underline" > 100 % < / span > : Der
Worst - Case ist alternativlos , { " " }
< strong > nur die maximalen < / strong > Story Points werden
beachtet !
< / li >
< / ul >
< AgileCalculator / >
< / AccordionItem >
< AccordionItem
label = { "6. Welche Geräte werden unterstützt?" }
alignCenter = { false }
>
< p class = "!mt-0" >
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 !
< / p >
< / AccordionItem >
< AccordionItem
label = {
< div >
7 . K ö nnen Fliesstexte formatiert werden ?
< br / >
Was ist < strong > Markdown < / strong > ?
< / div >
}
alignCenter = { false }
>
< p class = "!mt-0 mb-1" >
Du kannst deinen Text formatieren , indem du ihn mit ganz
bestimmten Zeichen versiehst ! Welche Zeichen das sind , wird
durch den "Markdown" - Standard definiert .
< / p >
< p class = "mt-1" >
Erfahre { " " }
< a
href = { markdownHelpUrl }
class = { externalLinkClass }
{ . . . externalLink }
>
hier < ExternalLinkIcon / >
< / a > { " " }
wie Markdown im Detail funktioniert !
< / p >
< strong > Kurzbeispiel : < / strong >
< div class = "prose-sm" >
< div class = "grid grid-cols-2" >
< p > Dein Text : < / p >
< pre >
{ [ "- *Pizza*" , "- **Gemüse**" , "- ***Salat***" ] . join (
"\n"
) }
< / pre >
< p > Ausgabe : < / p >
< div class = "border border-slate-200" >
< ul >
< li >
< i > Pizza < / i >
< / li >
< li >
< strong > Gem ü se < / strong >
< / li >
< li >
< i >
< strong > Salat < / strong >
< / i >
< / li >
< / ul >
< / div >
< / div >
< / div >
< / AccordionItem >
< AccordionItem
id = "welcome-local-installation"
label = { < div > 8 . Kann R ä ppli lokal installiert werden ? < / div > }
alignCenter = { false }
>
< p class = "!mt-0" >
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 .
< / p >
< p class = "bg-slate-500/10 flex p-3 items-center gap-3 rounded" >
< WarningIcon class = "w-auto h-6 inline mr-1" / > { " " }
< strong >
F ü r die Installation sind grundlegende Kenntnisse im Umgang
mit der Kommandozeile empfohlen !
< / strong >
< / p >
< h3 > Voraussetzungen : < / h3 >
< ul >
< li >
Installiere { " " }
< a
class = { externalLinkClass }
href = "https://nodejs.org/en/"
{ . . . externalLink }
>
nodejs { ">" } = 18 < ExternalLinkIcon / >
< / a >
< / li >
< / ul >
< h3 > Installation R ä ppli < / h3 >
< p > F ü hre folgenden Befehl aus : < / p >
< pre > npm install - g rappli < / pre >
< h3 > R ä ppli starten < / h3 >
< p > F ü hre folgenden Befehl aus , um R ä ppli zu starten < / p >
< pre > rappli < / pre >
< p >
Sobald die Meldung "Listening on port 3000" erscheint , kannst
du dein lokales R ä ppli auf deinem Browser ü ber { " " }
< a href = "http://localhost:3000" { ...externalLink } >
http : //localhost:3000
< / a > { " " }
erreichen .
< / p >
< / AccordionItem >
< AccordionItem
label = {
< div >
9 . Wie pr ä zise wurden die SIX QR - Rechnung Vorgaben
umgesetzt ?
< / div >
}
alignCenter = { false }
>
< p class = "!mt-0" >
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 .
< / p >
< / AccordionItem >
< AccordionItem
label = { < div > 10 . Haftungsausschluss < / div > }
alignCenter = { false }
>
< p class = "!mt-0" >
R ä ppli ( { getDomain ( ) } ) verwendest du { " " }
< strong > eigenverantwortlich < / strong > . "Lufrai - Katja Lutz"
( Einzelfirma ) und "Katja Lutz" ( Mensch ) ü bernehmen keine
Haftung .
< / p >
< p >
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 { " " }
< a href = "#welcome-local-installation" onClick = { onClickFocus } >
installiere R ä ppli lokal
< / a >
.
< / p >
< / AccordionItem >
< / div >
< / section >
< / div >
< / div >
< div class = "mt-14 relative flex justify-center items-center gap-10" >
< a
href = "#welcome-patron"
class = "hidden lg:flex btn btn-sm btn-secondary bg-purple-600 border-purple-600 gap-2 transition-all shadow-lg hover:shadow-lg shadow-purple-300 hover:shadow-purple-500 hover:ring-2 ring-offset-2 ring-purple-500"
>
< DonationIcon / >
Spenden
< / a >
< div
class = "hidden lg:flex form-control flex-row items-center gap-2 tooltip tooltip-accent"
data - tip = "Füge das Lufrai Logo zu deinem Dokument hinzu."
>
< input
id = "welcome-modal-show-watermark"
checked = { localState . showLufraiWatermark }
class = "checkbox checkbox-lg checkbox-accent shadow-md"
type = "checkbox"
onClick = { ( evt ) = >
setLocalState ( "showLufraiWatermark" , evt . currentTarget . checked )
}
/ >
< label
for = "welcome-modal-show-watermark"
class = "btn btn-sm btn-accent gap-2 shadow-md"
>
< WatermarkIcon / >
F ü r Lufrai werben
< / label >
< / div >
< button
onClick = { ( ) = > setLocalState ( "showWelcome" , false ) }
class = "hidden lg:flex btn btn-xl btn-primary gap-2 transition-all shadow-lg hover:shadow-lg shadow-indigo-300 hover:shadow-indigo-500 hover:ring-2 ring-offset-2 ring-indigo-500"
>
< LaunchIcon / >
Loslegen
< / button >
< div
style = { { animation : "bounce 1.5s infinite;" } }
class = "animate-bounce w-full text-sm font-bold lg:hidden bg-red-300 ring-2 ring-offset-2 ring-error text-error-content rounded p-3 shadow-2xl flex items-center justify-center gap-3"
>
< WarningIcon / > Bitte verwende einen Laptop oder Computer mit einer
Mindestbreite von 1024 Pixel !
< / div >
< / div >
< a
href = "https://git.lufrai.com/rappli/rappli/src/branch/master/CHANGELOG.md#changelog"
class = "hover:underline absolute bottom-8 right-8 text-xs text-black opacity-60 flex gap-3"
{ . . . externalLink }
>
< span > Version : { __APP_VERSION__ } < / span >
< span > { getDisplayDate ( new Date ( __BUILD_TIME__ ) ) } < / span >
< / a >
< / Modal >
) ;
} ;
export default WelcomeModal ;