180 lines
5.8 KiB
TypeScript
180 lines
5.8 KiB
TypeScript
import { PERMS } from "@/lib/permission-slugs";
|
|
import {
|
|
anyCapability,
|
|
type CanonicalHousekeepingHref,
|
|
type HousekeepingRouteDefinition,
|
|
} from "../../foundation/contracts";
|
|
import { HOTEL_ASSET_QUERY_OWNERSHIP } from "./queries/assets";
|
|
|
|
export const HOTEL_ROUTE_GROUPS = ["rooms", "navigation", "radio"] as const;
|
|
export type HotelRouteGroup = (typeof HOTEL_ROUTE_GROUPS)[number];
|
|
|
|
export const HOTEL_PRIMARY_ROUTE_IDS = [
|
|
"hotel.rooms",
|
|
"hotel.room-detail",
|
|
"hotel.room-furni",
|
|
"hotel.navigation",
|
|
"hotel.radio.overview",
|
|
"hotel.radio.settings",
|
|
"hotel.radio.monitoring",
|
|
"hotel.radio.moderation",
|
|
"hotel.radio.autodj",
|
|
"hotel.radio.history",
|
|
"hotel.radio.points",
|
|
"hotel.radio.ranks",
|
|
"hotel.radio.api-keys",
|
|
"hotel.radio.banners",
|
|
"hotel.radio.embed",
|
|
] as const;
|
|
export type HotelPrimaryRouteId = (typeof HOTEL_PRIMARY_ROUTE_IDS)[number];
|
|
|
|
export const HOTEL_STUDIO_ROUTE_IDS = [
|
|
"hotel.studio.audit",
|
|
"hotel.studio.badges",
|
|
"hotel.studio.clone",
|
|
"hotel.studio.clothing",
|
|
"hotel.studio.effects",
|
|
"hotel.studio.furni",
|
|
"hotel.studio.maintenance",
|
|
"hotel.studio.pets",
|
|
"hotel.studio.repair-icons",
|
|
"hotel.studio.sync",
|
|
"hotel.studio.upload",
|
|
] as const;
|
|
export type HotelStudioRouteId = (typeof HOTEL_STUDIO_ROUTE_IDS)[number];
|
|
export type HotelRouteId = HotelPrimaryRouteId | HotelStudioRouteId;
|
|
|
|
export const HOTEL_STUDIO_OPERATION_BY_ROUTE = Object.freeze({
|
|
"hotel.studio.badges": "badge",
|
|
"hotel.studio.clone": "clone",
|
|
"hotel.studio.clothing": "clothing",
|
|
"hotel.studio.effects": "effect",
|
|
"hotel.studio.furni": "furni",
|
|
"hotel.studio.maintenance": "maintenance",
|
|
"hotel.studio.pets": "pet",
|
|
"hotel.studio.repair-icons": "repair-icons",
|
|
"hotel.studio.sync": "sync",
|
|
"hotel.studio.upload": "upload",
|
|
} as const);
|
|
|
|
function route<const Id extends HotelPrimaryRouteId>(
|
|
id: Id,
|
|
href: CanonicalHousekeepingHref,
|
|
permissions: readonly string[],
|
|
): HousekeepingRouteDefinition & { readonly id: Id } {
|
|
return routeDefinition(id, href, permissions);
|
|
}
|
|
|
|
export const HOTEL_PRIMARY_ROUTES = [
|
|
route("hotel.rooms", "/ase-next/hotel/rooms", [PERMS.ROOMS_VIEW]),
|
|
route("hotel.room-detail", "/ase-next/hotel/rooms/:id", [
|
|
PERMS.ROOMS_VIEW,
|
|
PERMS.ROOMS_EDIT,
|
|
]),
|
|
route("hotel.room-furni", "/ase-next/hotel/rooms/:id/furni", [
|
|
PERMS.ROOMS_VIEW,
|
|
PERMS.ROOMS_EDIT,
|
|
]),
|
|
route("hotel.navigation", "/ase-next/hotel/navigation", [PERMS.PAGES_VIEW]),
|
|
...(
|
|
[
|
|
["hotel.radio.overview", "/ase-next/hotel/radio/overview"],
|
|
["hotel.radio.settings", "/ase-next/hotel/radio/settings"],
|
|
["hotel.radio.monitoring", "/ase-next/hotel/radio/monitoring"],
|
|
["hotel.radio.moderation", "/ase-next/hotel/radio/moderation"],
|
|
["hotel.radio.autodj", "/ase-next/hotel/radio/autodj"],
|
|
["hotel.radio.history", "/ase-next/hotel/radio/history"],
|
|
["hotel.radio.points", "/ase-next/hotel/radio/points"],
|
|
["hotel.radio.ranks", "/ase-next/hotel/radio/ranks"],
|
|
["hotel.radio.api-keys", "/ase-next/hotel/radio/api-keys"],
|
|
["hotel.radio.banners", "/ase-next/hotel/radio/banners"],
|
|
["hotel.radio.embed", "/ase-next/hotel/radio/embed"],
|
|
] as const
|
|
).map(([id, href]) => route(id, href, [PERMS.RADIO_VIEW])),
|
|
] as const satisfies readonly HousekeepingRouteDefinition[];
|
|
|
|
function studioRoute<const Id extends HotelStudioRouteId>(
|
|
id: Id,
|
|
href: CanonicalHousekeepingHref,
|
|
): HousekeepingRouteDefinition & { readonly id: Id } {
|
|
return routeDefinition(
|
|
id,
|
|
href,
|
|
id === "hotel.studio.maintenance"
|
|
? [PERMS.CATALOG_EDIT]
|
|
: [PERMS.ASSETS_IMPORT],
|
|
);
|
|
}
|
|
|
|
function routeDefinition<const Id extends HotelRouteId>(
|
|
id: Id,
|
|
href: CanonicalHousekeepingHref,
|
|
permissions: readonly string[],
|
|
): HousekeepingRouteDefinition & { readonly id: Id } {
|
|
return {
|
|
id,
|
|
href,
|
|
labelKey: `pages.housekeeping.routes.${id}`,
|
|
capability: anyCapability(...permissions),
|
|
};
|
|
}
|
|
|
|
export const HOTEL_STUDIO_ROUTES = [
|
|
studioRoute("hotel.studio.audit", "/ase-next/hotel/studio/audit"),
|
|
studioRoute("hotel.studio.badges", "/ase-next/hotel/studio/badges"),
|
|
studioRoute("hotel.studio.clone", "/ase-next/hotel/studio/clone"),
|
|
studioRoute("hotel.studio.clothing", "/ase-next/hotel/studio/clothing"),
|
|
studioRoute("hotel.studio.effects", "/ase-next/hotel/studio/effects"),
|
|
studioRoute("hotel.studio.furni", "/ase-next/hotel/studio/furni"),
|
|
studioRoute("hotel.studio.maintenance", "/ase-next/hotel/studio/maintenance"),
|
|
studioRoute("hotel.studio.pets", "/ase-next/hotel/studio/pets"),
|
|
studioRoute(
|
|
"hotel.studio.repair-icons",
|
|
"/ase-next/hotel/studio/repair-icons",
|
|
),
|
|
studioRoute("hotel.studio.sync", "/ase-next/hotel/studio/sync"),
|
|
studioRoute("hotel.studio.upload", "/ase-next/hotel/studio/upload"),
|
|
] as const satisfies readonly HousekeepingRouteDefinition[];
|
|
|
|
export const HOTEL_ROUTE_IDS = [
|
|
...HOTEL_PRIMARY_ROUTE_IDS,
|
|
...HOTEL_STUDIO_ROUTE_IDS,
|
|
] as const;
|
|
export const HOTEL_ROUTES = [
|
|
...HOTEL_PRIMARY_ROUTES,
|
|
...HOTEL_STUDIO_ROUTES,
|
|
] as const satisfies readonly HousekeepingRouteDefinition[];
|
|
|
|
const ROUTE_BY_ID = new Map(
|
|
HOTEL_ROUTES.map((definition) => [definition.id, definition]),
|
|
);
|
|
|
|
export function hotelRouteById(id: HotelRouteId): HousekeepingRouteDefinition {
|
|
const definition = ROUTE_BY_ID.get(id);
|
|
if (!definition) throw new Error(`unknown Hotel route: ${id}`);
|
|
return definition;
|
|
}
|
|
|
|
export function hotelStudioOperationKind(id: HotelStudioRouteId) {
|
|
if (id === "hotel.studio.audit") return null;
|
|
return HOTEL_STUDIO_OPERATION_BY_ROUTE[id];
|
|
}
|
|
|
|
export function hotelRouteGroup(id: HotelPrimaryRouteId): HotelRouteGroup {
|
|
if (id === "hotel.navigation") return "navigation";
|
|
return id.startsWith("hotel.radio.") ? "radio" : "rooms";
|
|
}
|
|
|
|
export const HOTEL_ASSET_CANONICAL_ROUTES = Object.freeze([
|
|
Object.freeze({
|
|
legacyPath: "/admin/badges",
|
|
routeId: HOTEL_ASSET_QUERY_OWNERSHIP.badges,
|
|
href: "/ase-next/economy/rewards/badges",
|
|
}),
|
|
Object.freeze({
|
|
legacyPath: "/admin/sounds",
|
|
routeId: HOTEL_ASSET_QUERY_OWNERSHIP.sounds,
|
|
href: "/ase-next/economy/rewards/sounds",
|
|
}),
|
|
] as const);
|