C Casini — Guide Open app (production) Open app (Firebase)

Using the portal Distributor / client side

Casini is where you order from the manufacturer, track every shipment, and find all your paperwork — no email threads, no spreadsheets.

Step 0 — Sign in (30 seconds)

Open the app and either click “Continue with Google” (fastest — a distributor account is created for you automatically on first sign-in), or sign in with your company email and the shared team password CasiniDemo2026!.

Your first order, in five steps

  1. Browse the CataloguePrices shown are your negotiated prices — your discount is already applied. Type a quantity and click Add to cart.
  2. Open the CartAdjust quantities, and optionally tick “repeat every …” on a line to flag it as a recurring replenishment.
  3. Choose addressesPick a saved invoice + delivery address, or type new ones (tick “save to address book” to reuse them next time). Add an optional note for the team.
  4. Submit the orderIt enters the pipeline as Submitted. The shipping/packaging fee shows as Pending until the manufacturer prices it — that's normal.
  5. Track itWatch the status stepper on My orders (Submitted → Processing → In Transit → Delivered). Download invoices and certificates from Documents, and ask questions in the order's Messages tab — replies stay attached to that order.

🚚 “EXW” orders end at pickup

If your contract uses EXW, you arrange your own freight: the pipeline ends at Picked Up, and the manufacturer assigns you a dock/gate and pickup slot instead of a tracking number.

⚙️ Settings

Manage your address book, see your contract terms (discount, Incoterm, annual quota) and your live quota attainment on your dashboard.

↔️ Switching seats

“Switch seat →” at the bottom-left returns you to the sign-in screen, where you can log in as a different account.

Running the manufacturer side Admin

Sign in with a manufacturer account (e.g. klaus@aetheris-medtech.com) to get the admin dashboard.

The daily loop

  1. Check the DashboardRevenue vs network quota, open orders, awaiting payment, quota attainment per distributor.
  2. Price new ordersA Submitted order is blocked until you set its shipping/packaging price on the order page — set it, save, and the Advance button unlocks. This fee is never counted as revenue.
  3. Advance the pipelineSubmitted → Processing → In Transit → Delivered (EXW orders go to Ready for Pickup → Picked Up). Add tracking + carrier, or dock/slot for EXW pickups. Payment status is a dropdown on the right.
  4. Answer and attachReply in the order's Messages (distributors see an unread counter), and attach documents — invoices, packing slips, certificates — under Documents. Distributors can download them instantly.
  5. Manage the networkUnder Distributors, edit each partner's discount rate, annual quota, default Incoterm and active status. Under Catalogue, add or edit products.
⚠️ Reset demo data (Settings) wipes everything back to the sample dataset — every order, message and account change. Only use it to start a fresh demo.

Maintaining the website Maintainer

The app is a static vanilla-JS site (no framework, no build complexity) backed by Firebase. Repo: D:\ivan\portal. This guide lives in D:\ivan\guide.

Run it locally

cd D:\ivan\portal
npm install
npm run dev      → http://localhost:5173

Deploy it

npm run build                    # → dist/
firebase deploy --only hosting   # firebase host
npx vercel deploy --prod         # vercel host

How the pieces fit

PieceWhat / where
FrontendStatic site in src/, built to dist/. Hosted twice: casiniportal.com (Vercel, production) and casini-portal.web.app (Firebase). Both are safe to share.
DatabaseFirebase Realtime Database, project casini-portal, instance casini-portal-default-rtdb (europe-west1), path janux. Rules require a signed-in user (auth != null).
LoginReal Firebase Authentication — Google sign-in plus email/password. Every seeded team member has a real auth account (password CasiniDemo2026!). The super-admin account is admin@casini.local (private password — ask the owner).
Admin scriptsscripts/create-users.mjs (create auth accounts), scripts/reset-db.mjs (force-reset data), scripts/seed-rtdb.mjs (seed only if empty), scripts/auth-config.mjs (enable Google / add login domains).

Common tasks

Reset demo data

Easiest: log in as admin → Settings → Reset demo data. Scripted: node scripts/reset-db.mjs (signs in as the super-admin and overwrites with the clean dataset from src/data.js).

Add a team or distributor account

Add the person to src/data.js (companyUsers or distributorUsers), then create their login with node scripts/create-users.mjs. Or just let them Continue with Google — distributors get a seat automatically.

“Google sign-in is not enabled”

Run node scripts/auth-config.mjs (enables the Google provider), and node scripts/auth-config.mjs add-domain https://your-new-url after deploying to a new domain.

App shows “cannot reach the database”

The Realtime Database instance may be paused in the Google Cloud console (it has happened before). Re-enable it, or run node scripts/rtdb-reenable.mjs, then reload.

Security posture & known limits

✅ Done: real Firebase Authentication (no more fake browser sessions), database locked to signed-in users only (anonymous REST access returns 401), security headers on both hosts, XSS escaping, git version control.
⚠️ Known limits (fine for the pilot, fix before scaling): the dataset is a single document — every signed-in user can read all of it, and any two simultaneous writes can overwrite each other. Prices and pipeline gates are enforced in the browser, not on a server. Next steps when it becomes real: per-distributor data nodes + per-user rules, price/pipeline validation in Cloud Functions (or a move back to the Supabase original with Postgres RLS).
📌 Deploying a new domain? Google sign-in only works from authorized domains: node scripts/auth-config.mjs add-domain https://that-domain.