import { Component, createMemo, JSX, Show, FlowComponent, mergeProps, ParentComponent, createSignal, onMount, } from "solid-js"; import SwissInvoice, { InvoiceData } from "~/components/SwissInvoice"; import { Meta, Style, Title } from "solid-meta"; import Page from "~/components/Page"; import LufraiLogoWww from "~icons/custom/lufrai-logo-www"; import AppIcon from "~icons/custom/icon"; import { getLine1, getLine2, isStructuredAddress } from "~/components/Address"; import Positions, { calculatePositionsPrice, calculatePositionsTax, } from "~/components/Positions"; import SettingsOverlay from "~/components/Settings/Overlay"; import { createLocalStore, createStore, createUiStore, LocalStoreContext, printTypeTitles, PRINT_TYPE_CONFIRMATION, PRINT_TYPE_INVOICE, PRINT_TYPE_OFFER, StoreContext, UiStoreContext, } from "~/stores"; import Big from "big.js"; import { getDisplayDateFromUnix, getHost, roundToStep } from "~/util"; import WelcomeModal, { description } from "~/components/WelcomeModal"; import Markdown from "~/components/Markdown"; // TODO: This should be a direct import of "shareon/css", but "shareon/css" doesnt work yet because solid-start / vite do not properly detect that as css import "../shareon.css"; export default function Home() { const store = createStore(); const [state, setState] = store; const localStore = createLocalStore(); const [localState, setLocalState] = localStore; const uiStore = createUiStore(); const [uiState, setUiState] = uiStore; onMount(function () { !import.meta.env.SSR && import("shareon").then((m) => m.init()); }); const invoiceData = createMemo((): InvoiceData => { const amountBeforeTax = calculatePositionsPrice(state.positions, state); const tax = calculatePositionsTax(amountBeforeTax, localState); const totalAmount = new Big(amountBeforeTax).plus(tax).toNumber(); const totalAmountRounded = roundToStep(totalAmount, 0.05); const creditor = localState.creditor; return { iban: localState.iban || "", amount: totalAmountRounded, amountBeforeTax, tax, currency: "CHF", message: state.invoice.message, reference: state.invoice.reference, //generate("12345 12345 12345 12345 1"), creditor: { type: isStructuredAddress(creditor) ? "S" : "K", name: creditor.name, city: creditor.city, zip: creditor.zip || 8500, country: "CH", line1: creditor.line1, line2: creditor.line2, }, debtor: state.customer.debtorAddress.name ? { type: isStructuredAddress(state.customer.debtorAddress) ? "S" : "K", name: state.customer.debtorAddress.name, city: state.customer.debtorAddress.city, zip: state.customer.debtorAddress.zip, country: "CH", line1: state.customer.debtorAddress.line1, line2: state.customer.debtorAddress.line2, } : undefined, }; }); const InnerPadding: FlowComponent = (props) => (
{props.children}
); const PageHeader: Component = () => { const RightItem: ParentComponent< { label: string; value?: any } & JSX.HTMLAttributes > = (p) => { const props = mergeProps({ show: true }, p); return (
{props.label}
{props.children || props.value}
); }; const address = createMemo(() => { const value = (localState.useCustomAddress && localState.customAddress ? localState.customAddress : localState.creditor) || invoiceData().creditor; return value; }); const customerAddress = createMemo(() => { return state.useCustomerAlternativeAddress ? state.customer.alternativeAddress : state.customer.debtorAddress; }); const titleMemo = createMemo( () => (state.positions.length > 0 ? `(${state.positions.length}) ` : "") + "Räppli - " + (state.project.projectNumber.length > 0 ? `${state.project.projectNumber} - ` : "") + printTypeTitles[uiState.printType] ); const externalTitle = "Räppli - Web App für Schweizerische Rechnungen"; return (
{import.meta.env.SSR ? externalTitle : titleMemo()}

{externalTitle}

{address().name ? [address().name, getLine1(address()), getLine2(address())] .filter((x) => x != "") .join(" · ") : ""}
{customerAddress().name}
{getLine1(customerAddress())}
{getLine2(customerAddress())}

); }; const PrintPreview: Component = () => { const Title: FlowComponent = (props) => (
{props.children}
); const PositionsWithData = () => ( ); const Preface = () => ( ); const Conclusion = () => ( ); const LufraiWatermark = () => ( ); return ( <> Offerte Auftragsbestätigung Rechnung

Zahlungsbedingungen: {localState.paymentTerms}

); }; const [pulsingLogo, setPulsingLogo] = createSignal(false); onMount(function () { setPulsingLogo(true); setTimeout(function () { setPulsingLogo(false); }, 4000); }); return (
setLocalState("showWelcome", true)} classList={{ "animate-pulse": pulsingLogo() && !localState.showWelcome, "print:hidden hover:!opacity-100 fixed z-10 right-2 top-0 text-slate-600 m-4 transition-all duration-75 hover:text-swiss-red fill-current cursor-pointer hover:scale-110 text-6xl drop-shadow-md": true, }} >
); }