@ -10,13 +10,20 @@ import {
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/carbon/favorite-filled" ;
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" ;
@ -38,14 +45,18 @@ import {
getHost ,
onClickFocus ,
} from "~/util" ;
import { capitalize , shuffle } from "froebel" ;
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 < HTMLAnchorElement >
@ -68,6 +79,8 @@ const WelcomeModal: Component = (props) => {
return localStateMounted ( ) && localState . showWelcome ;
} ) ;
const [ showTrailer , setShowTrailer ] = createSignal ( false ) ;
const increaseCount_ = server ( increaseLikes ) ;
const [ likes ] = createResource ( server ( getLikes ) ) ;
onMount ( function ( ) {
let adjectives = [
@ -168,6 +181,29 @@ const WelcomeModal: Component = (props) => {
"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 (
< Modal open = { isOpen ( ) } >
@ -953,10 +989,10 @@ const WelcomeModal: Component = (props) => {
< / section >
< / div >
< / div >
< div class = "mt-8 xl:mt-14 relative flex justify-center items-center gap- 10">
< div class = "mt-8 xl:mt-14 relative flex justify-center items-center gap- 2 sm:gap-5 xl: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"
class = " 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
@ -982,24 +1018,66 @@ const WelcomeModal: Component = (props) => {
F ü r Lufrai werben
< / label >
< / div >
< div
class = "static md:relative lg:hidden tooltip tooltip-error"
data - tip = " Bitte verwende einen Laptop oder Computer mit einer
Mindestbreite von 1024 Pixeln ! "
>
< div class = "btn hover:!bg-white hover:!text-black/50 btn-outline flex gap-2 transition-all shadow-indigo-300 hover:shadow-red-300 hover:ring-2 ring-offset-2 ring-red-400" >
< WarningIcon / > Loslegen
< / div >
< / div >
< button
class = "btn relative border-red-600 bg-red-500 hover:bg-red-600 hover:border-pink-700 hover:ring-2 ring-offset-2 ring-pink-500 shadow-red-300 shadow-lg lg:shadow-md lg:shadow-red-300 hover:shadow-red-400 tooltip tooltip-error stroke-1 stroke-white"
onClick = { ( ) = > {
setLikeCount ( likeCount ( ) + 1 ) ;
increaseCount_ ( ) ;
} }
data - tip = { ( likes ( ) || 0 ) + likeCount ( ) }
>
< div
class = "flex justify-center transition-transform"
style = { {
transform : ` scale( ${ clamp ( 0.9 , 0.9 + likeCount ( ) / 12 , 1.3 ) } ) ` ,
} }
>
< Show when = { likeCount ( ) === 0 } >
< FavoriteIcon / >
< / Show >
< Show when = { likeCount ( ) === 1 } >
< FavoriteHalfIcon / >
< / Show >
< Show when = { likeCount ( ) > 1 } >
< FavoriteFilledIcon / >
< / Show >
< / div >
< span aria - disabled = "true" class = "text-xs text-orange-200 font-black" >
{ Intl . NumberFormat ( "en-US" , {
notation : "compact" ,
maximumFractionDigits : 1 ,
} ) . format ( ( likes ( ) || 0 ) + likeCount ( ) ) }
< / span >
< For each = { confetti } >
{ ( v ) = > (
< Show when = { v } >
< ConfettiExplosion
stageHeight = { 1500 }
duration = { confettiDuration }
force = { 1 }
shouldDestroyAfterDone = { true }
/ >
< / Show >
) }
< / For >
< / button >
< 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"
class = "hidden lg:flex btn btn- lg btn-primary gap-2 transition-all shadow-lg shadow-indigo-300 hover:shadow-indigo-500 hover:ring-2 ring-offset-2 ring-indigo-500"
>
< LaunchIcon / >
Loslegen
< / button >
< div
style = { { animation : ! showTrailer ( ) ? "bounce 1.5s infinite;" : "" } }
classList = { {
"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" :
true ,
"animate-bounce" : ! showTrailer ( ) ,
} }
>
< WarningIcon / > Bitte verwende einen Laptop oder Computer mit einer
Mindestbreite von 1024 Pixeln !
< / div >
< / div >
< a
href = "https://git.lufrai.com/rappli/rappli/src/branch/master/CHANGELOG.md#changelog"