feat: implement WelcomeModal component
parent
d5eff6095e
commit
0c0ef7fe99
@ -0,0 +1,325 @@
|
||||
import {
|
||||
Component,
|
||||
createEffect,
|
||||
createMemo,
|
||||
onCleanup,
|
||||
onMount,
|
||||
useContext,
|
||||
} from "solid-js";
|
||||
import LufraiLogo from "~icons/custom/lufrai-logo";
|
||||
import AppIcon from "~icons/custom/icon";
|
||||
import ExternalLinkIcon from "~icons/carbon/launch";
|
||||
import LaunchIcon from "~icons/carbon/edit";
|
||||
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 { shuffle } from "~/util";
|
||||
|
||||
const WelcomeModal: Component = (props) => {
|
||||
const [localState, setLocalState, localStateMounted] =
|
||||
useContext(LocalStoreContext)!;
|
||||
const [AcordionItem] = 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) {
|
||||
console.log(err);
|
||||
}
|
||||
halted = false;
|
||||
}
|
||||
});
|
||||
|
||||
onCleanup(function () {
|
||||
typerInstance.kill();
|
||||
});
|
||||
});
|
||||
|
||||
return (
|
||||
<Modal open={isOpen()}>
|
||||
<ModalCloseButton onClick={() => setLocalState("showWelcome", false)} />
|
||||
<div class="max-h-[50vh] overflow-y-auto">
|
||||
<div class="h-[50vh] flex items-center justify-center">
|
||||
<div>
|
||||
<div class="flex flex-col items-center">
|
||||
<div class="mb-3 text-8xl flex items-end justify-between w-[370px] font-bold tracking-tighter leading-none text-swiss-red fill-current">
|
||||
<AppIcon height="0.9em" />
|
||||
<div>Räppli</div>
|
||||
</div>
|
||||
<div class="flex flex-col items-stretch">
|
||||
<div class="flex justify-center">
|
||||
<div class="text-gray-800 tracking-widest mb-4 flex gap-1">
|
||||
Der reibungslose Weg zur{" "}
|
||||
<span class="ignore-white-space" ref={subtitleEl}></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex justify-end w-[410px]">
|
||||
<a
|
||||
href="https://lufrai.org"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
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"
|
||||
>
|
||||
<span>made</span>
|
||||
<span>by</span>
|
||||
<LufraiLogo class="w-auto h-[1.5em]" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-28 flex text-center gap-7 items-center justify-center">
|
||||
<a class="link link-secondary" href="#welcome-quickstart">
|
||||
Einleitung
|
||||
</a>
|
||||
<a class="link link-secondary" href="#welcome-why-free">
|
||||
Wieso ist Räppli <br />
|
||||
<strong>komplett kostenlos</strong>?
|
||||
</a>
|
||||
<a class="link link-secondary" href="#welcome-lufrai">
|
||||
Was ist Lufrai?
|
||||
</a>
|
||||
<a class="link link-secondary" href="#welcome-support">
|
||||
Das Projekt
|
||||
<br />
|
||||
unterstützen
|
||||
</a>
|
||||
<a
|
||||
class="link link-secondary"
|
||||
title="Häufig gestellte Fragen"
|
||||
href="#welcome-faq"
|
||||
>
|
||||
FAQ
|
||||
</a>
|
||||
<a
|
||||
class="link link-secondary flex items-center gap-2"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
href="https://git.lufrai.com/rappli/rappli"
|
||||
>
|
||||
Git-Repository
|
||||
<ExternalLinkIcon />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-20 prose max-w-none">
|
||||
<section>
|
||||
<h1 id="welcome-quickstart">Einleitung</h1>
|
||||
<p>
|
||||
Sit aute excepteur labore eu non eiusmod nulla irure irure
|
||||
officia. Veniam pariatur dolore fugiat mollit cillum. Et id
|
||||
occaecat occaecat non duis. Veniam excepteur do labore sit nulla
|
||||
veniam non ad nisi qui proident adipisicing esse adipisicing ea.
|
||||
Officia do esse magna dolore irure voluptate pariatur consequat
|
||||
esse voluptate. Incididunt incididunt mollit nostrud laborum
|
||||
cupidatat proident tempor reprehenderit officia exercitation
|
||||
labore. Commodo minim fugiat mollit commodo. Sit anim est aute.
|
||||
Ullamco non deserunt deserunt aliquip labore sunt esse Lorem aute
|
||||
in nisi mollit irure deserunt labore. Lorem veniam in consequat
|
||||
ipsum consequat sint consectetur ex anim magna.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="mt-16">
|
||||
<h1 id="welcome-why-free">
|
||||
Wieso ist <span class="text-swiss-red">Räppli</span> komplett{" "}
|
||||
<span class="text-swiss-red">kostenlos</span>?
|
||||
</h1>
|
||||
<p>
|
||||
Consectetur id magna labore commodo exercitation laboris est
|
||||
laboris consectetur irure minim. Officia anim tempor adipisicing
|
||||
irure labore tempor reprehenderit culpa consequat ea esse
|
||||
exercitation. Consectetur labore velit nulla excepteur eiusmod sit
|
||||
fugiat do proident. Ex non consectetur mollit dolor dolore Lorem
|
||||
ut et incididunt pariatur sunt deserunt tempor magna ullamco.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="mt-16">
|
||||
<h1 id="welcome-lufrai">
|
||||
Was ist <span class="text-lufrai-primary">Lufrai</span>?
|
||||
</h1>
|
||||
<p>
|
||||
Quis occaecat pariatur laborum do ad esse. Mollit excepteur duis
|
||||
nulla proident nostrud tempor ad ullamco. Amet id magna aute esse
|
||||
tempor incididunt pariatur veniam ipsum qui. Sunt laboris in
|
||||
laborum reprehenderit qui sint consectetur nostrud excepteur
|
||||
proident proident laboris qui dolor ea. Reprehenderit tempor elit
|
||||
consequat dolore quis ad voluptate consequat. Eiusmod ad quis
|
||||
dolore dolore ea ipsum commodo eu aliquip veniam. Consequat
|
||||
pariatur est do sint nisi duis enim tempor occaecat elit non.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="mt-16">
|
||||
<h1 id="welcome-support">Das Projekt unterstützen</h1>
|
||||
<p>
|
||||
Irure laboris quis consequat enim tempor dolor. Esse velit
|
||||
occaecat dolore aute cillum pariatur reprehenderit irure duis eu
|
||||
nulla pariatur fugiat consectetur ipsum. Commodo ad aliquip nulla
|
||||
non incididunt. Officia veniam cillum cillum. Velit ex aliquip
|
||||
mollit deserunt nostrud id amet voluptate ea duis cupidatat
|
||||
officia culpa consequat enim. Voluptate anim fugiat anim et elit
|
||||
aute cupidatat. Duis aliquip laboris adipisicing dolore elit
|
||||
voluptate proident occaecat excepteur culpa exercitation velit.
|
||||
Veniam esse quis voluptate aliquip culpa. Aute cupidatat sunt amet
|
||||
ad fugiat id elit. Officia proident ea deserunt quis anim elit
|
||||
cupidatat pariatur. Aliqua dolore ad eiusmod qui eu ea enim qui
|
||||
enim incididunt aute irure tempor fugiat sunt. Consequat magna
|
||||
culpa Lorem nostrud cillum eu cillum adipisicing eu aute duis
|
||||
excepteur. In anim mollit amet elit ex.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="mt-16">
|
||||
<h1 id="welcome-faq">Häufig gestellte Fragen</h1>
|
||||
<div class="text-black">
|
||||
<AcordionItem
|
||||
item={0}
|
||||
label={"Wo werden meine Daten gespeichert?"}
|
||||
>
|
||||
test
|
||||
</AcordionItem>
|
||||
|
||||
<AcordionItem label="Ich habe vergessen zu speichern!?">
|
||||
test
|
||||
</AcordionItem>
|
||||
|
||||
<AcordionItem
|
||||
label={
|
||||
<div class="text-center">
|
||||
Ich habe einen Anpassungswunsch!
|
||||
<br />
|
||||
Kann die App bitte gratis angepasst werden?
|
||||
</div>
|
||||
}
|
||||
>
|
||||
test
|
||||
</AcordionItem>
|
||||
|
||||
<AcordionItem label={"Welche Geräte werden unterstützt?"}>
|
||||
test
|
||||
</AcordionItem>
|
||||
|
||||
<AcordionItem label={"Wer hat's erfunden?"}>test</AcordionItem>
|
||||
|
||||
<AcordionItem label={'Was heisst "Open Source"?'}>
|
||||
test
|
||||
</AcordionItem>
|
||||
|
||||
<AcordionItem
|
||||
label={
|
||||
<div class="text-center">
|
||||
Können Fliesstexte formatiert werden?
|
||||
<br />
|
||||
Was ist <strong>Markdown</strong>?
|
||||
</div>
|
||||
}
|
||||
>
|
||||
test
|
||||
</AcordionItem>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-14 relative flex justify-center gap-10">
|
||||
<div
|
||||
class="form-control flex-row items-center gap-2"
|
||||
title="Unterstütze Lufrai mit einem Wasserzeichen im Dokument"
|
||||
>
|
||||
<input
|
||||
checked={localState.showLufraiWatermark}
|
||||
class="checkbox checkbox-lg checkbox-accent"
|
||||
type="checkbox"
|
||||
onClick={(evt) =>
|
||||
setLocalState("showLufraiWatermark", evt.currentTarget.checked)
|
||||
}
|
||||
/>
|
||||
<button
|
||||
onClick={() =>
|
||||
setLocalState(
|
||||
"showLufraiWatermark",
|
||||
!localState.showLufraiWatermark
|
||||
)
|
||||
}
|
||||
class="btn btn-sm btn-accent text-gap-2 shadow-2xl shadow-lufrai-primary-darker"
|
||||
>
|
||||
Lufrai Wasserzeichen
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setLocalState("showWelcome", false)}
|
||||
class="btn btn-xl btn-primary gap-2 shadow-2xl shadow-indigo-900"
|
||||
>
|
||||
<LaunchIcon />
|
||||
Loslegen
|
||||
</button>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
export default WelcomeModal;
|
Loading…
Reference in New Issue