book-free.openapps.xyz

Source

This app’s code and revision history are public. Download a copy or explore the files below.

Public
The app’s code and revision history are public.
Owned app · rev f8f1b3a80195
Run it yourself
Take the whole tree and run it on your own machine. The download needs no account. Cloning needs a sign-in.
Download .zip
bounded clone 7385a6c1c47153b1728160ff
A copy you download is not bounded. The guarantees this app runs under - declared egress, proven invariants, writes that fail closed - live in the runtime serving this page, not in the files. What you get is auditable source you can read and run, with no runtime guarantees attached.
← All files
src/main.tsx
// Book's entry. "/" keeps the static landing and mounts the page maker and "Your pages" into it.
// "/<handle>" is a public booking page, "/e/<handle>" its owner's dashboard ("#k=<key>" claims it),
// and "/b/<handle>/<bookingId>" one booking ("#c=<key>" opens it on any device).
import { createRoot } from "react-dom/client";
import { usePath } from "./lib/router";
import { Toaster } from "./ui";
import { PageForm } from "./PageForm";
import { YourPages } from "./Home";
import { BookingPage } from "./BookingPage";
import { Dashboard } from "./Dashboard";
import { Manage } from "./Manage";
import { handleProblem } from "../functions/lib/book";
import "./styles.css";

function route(path: string): JSX.Element | null {
  const edit = path.match(/^\/e\/([A-Za-z0-9-]{3,32})\/?$/);
  if (edit) return <Dashboard key={edit[1].toLowerCase()} handle={edit[1].toLowerCase()} />;
  const booking = path.match(/^\/b\/([A-Za-z0-9-]{3,32})\/([A-Za-z0-9]{8,32})\/?$/);
  if (booking) return <Manage key={booking[2]} handle={booking[1].toLowerCase()} bookingId={booking[2]} />;
  const page = path.match(/^\/([A-Za-z0-9-]{3,32})\/?$/);
  if (page && !handleProblem(page[1].toLowerCase())) return <BookingPage key={page[1].toLowerCase()} handle={page[1].toLowerCase()} />;
  return null;
}

function App() {
  const view = route(usePath());
  document.body.classList.toggle("app-mode", Boolean(view));
  return (
    <>
      {view}
      <Toaster />
    </>
  );
}

createRoot(document.getElementById("app")!).render(<App />);
const createSlot = document.getElementById("create");
if (createSlot) createRoot(createSlot).render(<PageForm mode="create" />);
const pagesSlot = document.getElementById("your-pages");
if (pagesSlot) createRoot(pagesSlot).render(<YourPages />);

Change history

Add favicon.ico and link tag
f8f1b3a801 · 2 hours ago
Quality pass: guest reschedule, days off, calendar feed, API docs
c827e5d073 · 5 hours ago
Bounded source sync
68e67b4092 · 1 day ago
Bounded source sync
ab2e006f9b · 1 day ago
Bounded source sync
bb10824b54 · 1 day ago
Bounded source sync
d22f765fb7 · 1 day ago
Bounded source sync
30b4b06513 · 1 day ago
Bounded source sync
c3d297477a · 1 day ago
Bounded source sync
7b18317417 · 1 day ago