A site is a physical location in your operation — a floor, a building, a BPO campus. In TeleQuick it is a row in the dim_site dimension table, managed from Admin → Sites and backed end-to-end by the adminSites.* tRPC procedures (list, create, update, remove). Sites exist so that other screens have a stable thing to group and filter by. The Sites screen states the consumers directly: the wallboard, the adherence calendars, and the Agent directory all filter by site.

The site record

Every site row carries these fields: country and region are trimmed on save, and a blank value is stored as null rather than an empty string. code and name are trimmed before validation, so a whitespace-only value is rejected with Code is required / Name is required even though the browser’s required attribute would have accepted it.

Code

The code is the short handle for the site — MNL-1, AUS-3. The form upper-cases every keystroke, so codes are always stored in upper case, and it caps the field at 40 characters. In the list, the code renders as a chip in the leftmost column, and it is the value the deactivation dialog uses to identify the site (Deactivate site MNL-1?). Treat it as the human-readable key you will see quoted back to you elsewhere in the console, and keep it short enough to fit in a table cell.

Timezone

Timezone is a single IANA zone name per site, chosen from a combobox rather than typed. The option list comes from the browser itself, via Intl.supportedValuesOf('timeZone'), so it is the full IANA set the runtime ships. If the runtime does not expose that helper, the form falls back to a short curated list: UTC, America/New_York, America/Los_Angeles, America/Mexico_City, America/Sao_Paulo, Europe/London, Europe/Paris, Europe/Berlin, Asia/Kolkata, Asia/Singapore, Asia/Manila, Asia/Tokyo, Australia/Sydney. A new site starts at UTC. Set it to the real local zone of the floor before anyone starts scheduling against the site — the value is stored verbatim on the row and shown in the list in monospace.

Country and region

Both fields are optional, and both exist as reporting groupings rather than as behaviour switches.
  • Country is constrained to two characters and upper-cased, i.e. an ISO 3166-1 alpha-2 code such as PH or US. Keeping to the ISO code rather than a spelled-out name means sites from different teams group together cleanly.
  • Region is free text up to 40 characters — APAC, EMEA, LATAM. Because it is free text, consistency is on you: APAC and apac are two different groupings.
Both are also matched by the list’s search box, so a well-populated country and region make sites findable without knowing the code.

Creating and editing a site

New site opens a 520px drawer with an empty form. Clicking any row in the table opens the same drawer pre-filled for that site. The differences between the two modes: Both mutations are scoped to the organisation currently selected in the tenant switcher; orgId comes from the active org and is sent on every call, including list. On success, the screen invalidates the adminSites.list cache and closes the drawer, so the table reflects the change immediately. On failure the error message is rendered inline at the top of the form and raised as an error toast (Create failed / Save failed); the drawer stays open with your input intact.

Searching and paging the list

The filter bar has two controls:
  • Search — a single box that matches against code, name, country and region. It is passed through as search on adminSites.list, and is omitted entirely when blank. Typing resets you to page 1.
  • Include inactive — a checkbox mapped to includeInactive. Unticked (the default) the list shows active sites only; tick it to see deactivated sites alongside them. Toggling it also resets to page 1.
The list is paged at 50 rows per request (perPage), and the pager is sized from the total the procedure returns. That same total drives the count in the page header (12 sites). Previous results stay on screen while the next page loads, so paging does not flash an empty table. When nothing matches, the screen distinguishes the two empty cases: with a search term it says nothing matched and offers no action; with no search term it offers a Create first site button.

Deactivation is a soft delete

There is no hard delete. The Deactivate button in the edit drawer calls adminSites.remove({ orgId, id }), which sets active = false on the row. The confirmation dialog spells out why:
Sites are soft-deleted (active=false) so reports keep joining cleanly. You can re-activate later.
What changes when you deactivate:
  • The row’s status chip flips from Active to Inactive.
  • The site drops out of the default list view — you need Include inactive ticked to see it again.
What does not change:
  • The row is still there. Its id, code, name, timezone, country, region and tags are untouched, so anything that joins to dim_site by id still resolves.
To bring a site back, tick Include inactive, open the site, tick Active in the edit form and save. Re-activation is an ordinary update — no special procedure, and nothing is recreated.

Tagging sites

The rightmost column of the table is a tag cell. Tags on this screen use the resource kind dim_site and are scoped to the active org. Tags for the whole visible page are resolved in a single call when the page loads, keyed by site id; the cell itself only writes. Editing tags in a row does not open the site drawer — the cell stops the click from propagating — and after a change the screen refreshes the tag state for the page. Because tags live alongside the row rather than on it, they survive deactivation.