Files
rezervovator/.claude/rules/frontend.md
T
2026-10-09 18:18:35 +02:00

3.1 KiB

paths
paths
src/pages/**
src/components/**
src/locales/**
src/app.rs
src/validator.rs
style/**

Frontend rules

Components

  • Leptos 0.6 API only. Components are #[component] functions returning impl IntoView, one page or dialog per file in src/pages/; reusable building blocks go to src/components/. Register new files in the respective mod.rs (pub mod only if used from app.rs).
  • This code runs on the server (SSR) and in the browser (hydration). Browser-only APIs (window(), web_sys) must not run during SSR — keep them in event handlers/effects or behind #[cfg(not(feature = "ssr"))]. Markup must render the same on both sides or hydration breaks.
  • A new admin page needs a <Route path="admin/..."/> in src/app.rs wrapped in <AdminPortal>, and a menu entry in src/components/admin_portal.rs. Paths starting with /admin are login-protected by the middleware; data access is still guarded by perm_check! in the server fn.

Data loading and forms

  • Load data with create_blocking_resource / create_resource calling the server fn, rendered inside <Transition fallback=...> with {trl("Loading...")}. Use a dialog's opener.visible() as the resource source so lists reload after the dialog closes (see src/pages/users.rs).
  • Handle all three outcomes of a server call: Err(e), Ok(ApiResponse::Error(msg)), Ok(ApiResponse::Data(d)).
  • Edit/create dialogs: DialogOpener::new() in the parent, create_server_action::<ServerFnStruct>() in the dialog, wrapped in <DataForm opener=.. action=.. title="..">. It supplies the modal, Save/Close buttons, client validation and server error display. Confirmations use <QuestionDialog>.
  • Form field names follow the server fn argument: name="company[name]". Pass the id as a hidden input. Fill inputs with prop:value={move || signal.get().field}.
  • DataForm/ModalDialog take title as an untranslated English key (&'static str); they translate it themselves.

Translations

  • Every user-visible string goes through trl("English text"); never hard-code Czech (or any text) in a view. The English text is the key and the fallback.
  • When you add or change a key, add the Czech translation to the cs map in src/locales/catalogues.rs. This includes validation messages and ApiResponse::Error strings from the backend.
  • trl() returns a closure — use it directly as {trl("...")} or attribute value; call it (trl("...")()) when a String is needed.
  • Dates shown to users go through loc_date(), weekday names through show_day().

Styling

  • UI is the Bootstrap-based admin template in assets/vendor/ plus Boxicons (<i class="bx bx-...">). Reuse its classes (card, table, btn btn-primary, form-control, row/col) before writing CSS.
  • Custom styles go to style/main.scss. Never edit assets/vendor/.
  • The public page banner style is assets/data/banner.css, rewritten at runtime by the appearance upload (/*bg-img*/ marker) — keep that marker / the background-image: url('...') form intact.
  • Stylesheets and meta tags are declared in src/components/header.rs.