@ttt-productions/ttt-core 0.79.8 → 0.79.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants/admin-labels.d.ts +53 -0
- package/dist/constants/admin-labels.d.ts.map +1 -1
- package/dist/constants/admin-labels.js +47 -0
- package/dist/constants/admin-labels.js.map +1 -1
- package/dist/constants/business-content.d.ts +57 -1
- package/dist/constants/business-content.d.ts.map +1 -1
- package/dist/constants/business-content.js +36 -1
- package/dist/constants/business-content.js.map +1 -1
- package/dist/constants/options.d.ts +15 -13
- package/dist/constants/options.d.ts.map +1 -1
- package/dist/constants/options.js +16 -13
- package/dist/constants/options.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { UserAccountStatus } from '../doc-schemas/user.js';
|
|
2
2
|
import type { FeedbackType } from './business-admin.js';
|
|
3
|
+
import type { ClearableTextFieldName } from './business-content.js';
|
|
4
|
+
import { HALL_CONTENT_TEXT_FIELDS } from './business-content.js';
|
|
5
|
+
import type { HallContentTextSurface } from '../doc-schemas/content.js';
|
|
3
6
|
import type { ReportDisposition } from '../doc-schemas/safety/foundation.js';
|
|
4
7
|
import type { BroadcastAudienceSelector } from '../schemas/notification.js';
|
|
5
8
|
import type { DeadLetterCollection } from '../schemas/admin.js';
|
|
@@ -13,6 +16,56 @@ export declare const BROADCAST_AUDIENCE_KIND_LABELS: Record<BroadcastAudienceSel
|
|
|
13
16
|
* UI copy uses the SHORT settled terms (Trade → "Trades", Craft → "Craft Tags", Genre →
|
|
14
17
|
* "<Kind> Genres"), never the compound code identifiers (ARCH-107). */
|
|
15
18
|
export declare const FEEDBACK_TYPE_LABELS: Record<FeedbackType, string>;
|
|
19
|
+
/**
|
|
20
|
+
* Human labels for the raw clearable/changeable TEXT-FIELD names the moderation text-clear
|
|
21
|
+
* remedy and the published "Update details" change-request flow work in. The backend stores and
|
|
22
|
+
* validates the raw doc field names (`workingTitle`, `description`, `content`); these are the
|
|
23
|
+
* only display strings for them — rendered by the member-facing "text removed by moderation"
|
|
24
|
+
* banners, every admin clear-text field picker, the change-request dialog, and the admin
|
|
25
|
+
* change-request work view. Keyed by the derived ClearableTextFieldName union, so a new
|
|
26
|
+
* clearable field fails the build here until it has a label (ARCH-102).
|
|
27
|
+
*
|
|
28
|
+
* The `working*` pair belongs to the Work shell and the Realm doc; the labels stay the plain
|
|
29
|
+
* short terms (ARCH-107 — the code identifier carries `working`, the UI never shows it).
|
|
30
|
+
*/
|
|
31
|
+
export declare const CLEARABLE_TEXT_FIELD_LABELS: Record<ClearableTextFieldName, string>;
|
|
32
|
+
/**
|
|
33
|
+
* Per-surface label overrides for the field labels above: `[surface][field] → label`. Only a
|
|
34
|
+
* surface that genuinely names a field differently appears here; everything else resolves to the
|
|
35
|
+
* base map. Each surface's override keys are restricted to the fields THAT surface exposes
|
|
36
|
+
* (indexed off `HALL_CONTENT_TEXT_FIELDS`), so an override for a field the surface does not have
|
|
37
|
+
* is a compile error — as is an override for a surface outside `HallContentTextSurface`.
|
|
38
|
+
*/
|
|
39
|
+
export type ClearableTextFieldLabelOverrides = {
|
|
40
|
+
[S in HallContentTextSurface]?: {
|
|
41
|
+
[F in (typeof HALL_CONTENT_TEXT_FIELDS)[S][number]]?: string;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* A Realm's identity field is called **Name** on every Realm surface (DJ ruling 2026-07-29,
|
|
46
|
+
* settling a four-surface Name/Title conflict: the creation flow said "Realm Name", the inline
|
|
47
|
+
* edit form "Working Title", the moderation-cleared banner "Title", and the request-update
|
|
48
|
+
* dialog "Name"). The `workingTitle` doc field is shared with the Work shell, where it IS a
|
|
49
|
+
* Title — so the difference is per-surface, not per-field, and lives here rather than flattening
|
|
50
|
+
* one of the two settled terms.
|
|
51
|
+
*/
|
|
52
|
+
export declare const CLEARABLE_TEXT_FIELD_LABEL_OVERRIDES: {
|
|
53
|
+
readonly workRealm: {
|
|
54
|
+
readonly workingTitle: "Name";
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* The display label for one raw clearable text-field name: the surface's override when it has
|
|
59
|
+
* one, otherwise the base label, otherwise the raw name. This is the ONE accessor every surface
|
|
60
|
+
* calls — pass the surface whenever the caller knows it (a Realm surface must, or it renders
|
|
61
|
+
* "Title" for a Name); omit it only for a genuinely surface-agnostic caller.
|
|
62
|
+
*
|
|
63
|
+
* Both parameters tolerate a plain `string` because callers read field names off stored documents
|
|
64
|
+
* (`moderationClearedFields`) and callable payloads, and the surface may be the `workProject`
|
|
65
|
+
* shell — which is a clearable surface but not a `HallContentTextSurface`, so it simply has no
|
|
66
|
+
* overrides and falls through to the base map.
|
|
67
|
+
*/
|
|
68
|
+
export declare function clearableTextFieldLabel(field: string, surface?: string): string;
|
|
16
69
|
/** Human labels for the dead-letter replay ledgers (Ops Repairs dead-letter table). */
|
|
17
70
|
export declare const DEAD_LETTER_COLLECTION_LABELS: Record<DeadLetterCollection, string>;
|
|
18
71
|
/** Operator-settable report dispositions with their console copy. 'undetermined' is the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin-labels.d.ts","sourceRoot":"","sources":["../../src/constants/admin-labels.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAC5E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAEhE,sEAAsE;AACtE,eAAO,MAAM,0BAA0B,EAAE,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAIxE,CAAC;AAEF,kEAAkE;AAClE,eAAO,MAAM,8BAA8B,EAAE,MAAM,CAAC,yBAAyB,CAAC,MAAM,CAAC,EAAE,MAAM,CAM5F,CAAC;AAEF;;;;uEAIuE;AACvE,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAM7D,CAAC;AAEF,uFAAuF;AACvF,eAAO,MAAM,6BAA6B,EAAE,MAAM,CAAC,oBAAoB,EAAE,MAAM,CAc9E,CAAC;AAEF;4EAC4E;AAC5E,eAAO,MAAM,0BAA0B,EAAE,SAAS;IAChD,KAAK,EAAE,OAAO,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAC;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB,EAiBA,CAAC;AAEF,gGAAgG;AAChG,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;0BAI0B;AAC1B,eAAO,MAAM,0BAA0B,EAAE,SAAS,sBAAsB,EAW9D,CAAC;AAEX,2FAA2F;AAC3F,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAElF;AASD,eAAO,MAAM,kCAAkC,oBAAoB,CAAC;AACpE,eAAO,MAAM,+BAA+B,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"admin-labels.d.ts","sourceRoot":"","sources":["../../src/constants/admin-labels.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAGpE,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACxE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAC;AAC5E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAEhE,sEAAsE;AACtE,eAAO,MAAM,0BAA0B,EAAE,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAIxE,CAAC;AAEF,kEAAkE;AAClE,eAAO,MAAM,8BAA8B,EAAE,MAAM,CAAC,yBAAyB,CAAC,MAAM,CAAC,EAAE,MAAM,CAM5F,CAAC;AAEF;;;;uEAIuE;AACvE,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAM7D,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,2BAA2B,EAAE,MAAM,CAAC,sBAAsB,EAAE,MAAM,CAM9E,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,gCAAgC,GAAG;KAC5C,CAAC,IAAI,sBAAsB,CAAC,CAAC,EAAE;SAC7B,CAAC,IAAI,CAAC,OAAO,wBAAwB,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM;KAC7D;CACF,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,oCAAoC;;;;CAEI,CAAC;AAEtD;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAS/E;AAED,uFAAuF;AACvF,eAAO,MAAM,6BAA6B,EAAE,MAAM,CAAC,oBAAoB,EAAE,MAAM,CAc9E,CAAC;AAEF;4EAC4E;AAC5E,eAAO,MAAM,0BAA0B,EAAE,SAAS;IAChD,KAAK,EAAE,OAAO,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAC;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB,EAiBA,CAAC;AAEF,gGAAgG;AAChG,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;0BAI0B;AAC1B,eAAO,MAAM,0BAA0B,EAAE,SAAS,sBAAsB,EAW9D,CAAC;AAEX,2FAA2F;AAC3F,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAElF;AASD,eAAO,MAAM,kCAAkC,oBAAoB,CAAC;AACpE,eAAO,MAAM,+BAA+B,oBAAoB,CAAC"}
|
|
@@ -35,6 +35,53 @@ export const FEEDBACK_TYPE_LABELS = {
|
|
|
35
35
|
tunesWorkGenreSuggestions: 'Tunes Genres',
|
|
36
36
|
televisionWorkGenreSuggestions: 'Television Genres',
|
|
37
37
|
};
|
|
38
|
+
/**
|
|
39
|
+
* Human labels for the raw clearable/changeable TEXT-FIELD names the moderation text-clear
|
|
40
|
+
* remedy and the published "Update details" change-request flow work in. The backend stores and
|
|
41
|
+
* validates the raw doc field names (`workingTitle`, `description`, `content`); these are the
|
|
42
|
+
* only display strings for them — rendered by the member-facing "text removed by moderation"
|
|
43
|
+
* banners, every admin clear-text field picker, the change-request dialog, and the admin
|
|
44
|
+
* change-request work view. Keyed by the derived ClearableTextFieldName union, so a new
|
|
45
|
+
* clearable field fails the build here until it has a label (ARCH-102).
|
|
46
|
+
*
|
|
47
|
+
* The `working*` pair belongs to the Work shell and the Realm doc; the labels stay the plain
|
|
48
|
+
* short terms (ARCH-107 — the code identifier carries `working`, the UI never shows it).
|
|
49
|
+
*/
|
|
50
|
+
export const CLEARABLE_TEXT_FIELD_LABELS = {
|
|
51
|
+
workingTitle: 'Title',
|
|
52
|
+
workingDescription: 'Description',
|
|
53
|
+
title: 'Title',
|
|
54
|
+
description: 'Description',
|
|
55
|
+
content: 'Content',
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* A Realm's identity field is called **Name** on every Realm surface (DJ ruling 2026-07-29,
|
|
59
|
+
* settling a four-surface Name/Title conflict: the creation flow said "Realm Name", the inline
|
|
60
|
+
* edit form "Working Title", the moderation-cleared banner "Title", and the request-update
|
|
61
|
+
* dialog "Name"). The `workingTitle` doc field is shared with the Work shell, where it IS a
|
|
62
|
+
* Title — so the difference is per-surface, not per-field, and lives here rather than flattening
|
|
63
|
+
* one of the two settled terms.
|
|
64
|
+
*/
|
|
65
|
+
export const CLEARABLE_TEXT_FIELD_LABEL_OVERRIDES = {
|
|
66
|
+
workRealm: { workingTitle: 'Name' },
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* The display label for one raw clearable text-field name: the surface's override when it has
|
|
70
|
+
* one, otherwise the base label, otherwise the raw name. This is the ONE accessor every surface
|
|
71
|
+
* calls — pass the surface whenever the caller knows it (a Realm surface must, or it renders
|
|
72
|
+
* "Title" for a Name); omit it only for a genuinely surface-agnostic caller.
|
|
73
|
+
*
|
|
74
|
+
* Both parameters tolerate a plain `string` because callers read field names off stored documents
|
|
75
|
+
* (`moderationClearedFields`) and callable payloads, and the surface may be the `workProject`
|
|
76
|
+
* shell — which is a clearable surface but not a `HallContentTextSurface`, so it simply has no
|
|
77
|
+
* overrides and falls through to the base map.
|
|
78
|
+
*/
|
|
79
|
+
export function clearableTextFieldLabel(field, surface) {
|
|
80
|
+
const overrides = surface
|
|
81
|
+
? CLEARABLE_TEXT_FIELD_LABEL_OVERRIDES[surface]
|
|
82
|
+
: undefined;
|
|
83
|
+
return (overrides?.[field] ?? CLEARABLE_TEXT_FIELD_LABELS[field] ?? field);
|
|
84
|
+
}
|
|
38
85
|
/** Human labels for the dead-letter replay ledgers (Ops Repairs dead-letter table). */
|
|
39
86
|
export const DEAD_LETTER_COLLECTION_LABELS = {
|
|
40
87
|
chatSyncEvents: 'Chat sync event',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admin-labels.js","sourceRoot":"","sources":["../../src/constants/admin-labels.ts"],"names":[],"mappings":"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","sourcesContent":["// ============================================================================\n// ADMIN-SURFACE DISPLAY LABELS — the ONE home for business display copy keyed\n// by canonical ttt-core enums (ARCH-102, extended 2026-07-13). Consolidated from\n// the former component-local maps in ttt-prod (admin-user-management-view,\n// admin-announcements-view, guided-resolution-flow). Any client (web, phone,\n// TV, admin app) renders the same labels by importing these.\n//\n// A few entries here are copy for ADMIN-MANAGED content that a PUBLIC surface also\n// renders (the rules-page group titles at the bottom of this file). The organizing\n// principle is one declaration, not one consumer.\n// ============================================================================\n\nimport type { UserAccountStatus } from '../doc-schemas/user.js';\nimport type { FeedbackType } from './business-admin.js';\nimport type { ReportDisposition } from '../doc-schemas/safety/foundation.js';\nimport type { BroadcastAudienceSelector } from '../schemas/notification.js';\nimport type { DeadLetterCollection } from '../schemas/admin.js';\n\n/** Moderation status labels (user-management view, status badges). */\nexport const USER_ACCOUNT_STATUS_LABELS: Record<UserAccountStatus, string> = {\n active: 'Active',\n suspended: 'Suspended',\n banned: 'Banned',\n};\n\n/** Broadcast audience selector labels (announcement composer). */\nexport const BROADCAST_AUDIENCE_KIND_LABELS: Record<BroadcastAudienceSelector['kind'], string> = {\n allActiveUsers: 'All active users',\n allArtisans: 'All artisan creators',\n explicitUids: 'Specific users (paste uids)',\n workMembers: \"A Work's guild members\",\n realmMembers: \"A Realm's members\",\n};\n\n/** Human labels for the canonical feedback types — the admin feedback-suggestions views and\n * the user-facing feedback-submission surface render these instead of restating copy. Keyed\n * by FeedbackType, so a new FEEDBACK_TYPES member fails the build until its label exists.\n * UI copy uses the SHORT settled terms (Trade → \"Trades\", Craft → \"Craft Tags\", Genre →\n * \"<Kind> Genres\"), never the compound code identifiers (ARCH-107). */\nexport const FEEDBACK_TYPE_LABELS: Record<FeedbackType, string> = {\n tradeProfessionSuggestions: 'Trades',\n craftSkillTagSuggestions: 'Craft Tags',\n talesWorkGenreSuggestions: 'Tales Genres',\n tunesWorkGenreSuggestions: 'Tunes Genres',\n televisionWorkGenreSuggestions: 'Television Genres',\n};\n\n/** Human labels for the dead-letter replay ledgers (Ops Repairs dead-letter table). */\nexport const DEAD_LETTER_COLLECTION_LABELS: Record<DeadLetterCollection, string> = {\n chatSyncEvents: 'Chat sync event',\n chatAdminActionCommands: 'Chat moderation command',\n notificationDeliveries: 'Notification delivery',\n chatMessageOutbox: 'Chat message publish',\n squareAnnouncementJobs: 'Square announcement',\n chatSyncFanoutJobs: 'Chat access fanout',\n mediaAssets: 'Media authority sync',\n quarantineSagaJobs: 'Quarantine saga',\n nciiRemovalJobs: 'NCII removal',\n safetyEvidenceJobs: 'Safety evidence job',\n accountActionCommands: 'Account safety action',\n activeReportGroups: 'Report edge sync',\n hallSubItemEdgeSync: 'Hall sub-item edge sync',\n};\n\n/** Operator-settable report dispositions with their console copy. 'undetermined' is the\n * initial state, never a settable target, so it carries no option entry. */\nexport const REPORT_DISPOSITION_OPTIONS: readonly {\n value: Exclude<ReportDisposition, 'undetermined'>;\n label: string;\n description: string;\n}[] = [\n {\n value: 'reportRequired',\n label: 'Report required (NCMEC)',\n description:\n 'Apparent CSAM — a report is legally required. Establishes actual knowledge + arms the clock.',\n },\n {\n value: 'notRequired',\n label: 'No report required',\n description: 'No reporting obligation ever arose. Disallowed once there is a validated match.',\n },\n {\n value: 'correctedNoApparentViolation',\n label: 'False positive — correct it',\n description: 'There was a triggering signal but on review it is a false positive.',\n },\n];\n\n/** One user-facing reason option (shown to the affected user for any user-affecting action). */\nexport interface UserFacingReasonOption {\n code: string;\n label: string;\n description: string;\n}\n\n/** User-facing reason picklist for the guided case-resolution flow — the affected user sees the\n * label for any user-affecting action. Canonical home (ARCH-102): the codes ARE this list's own\n * enumeration, so every client (web, phone, TV, admin app) renders the same options + labels by\n * importing from here. Final user-/legal-facing wording is subject to lawyer review; these are\n * functional defaults. */\nexport const USER_FACING_REASON_OPTIONS: readonly UserFacingReasonOption[] = [\n { code: 'harassment', label: 'Harassment or bullying', description: 'Targeted abuse, threats, or sustained harassment of a person.' },\n { code: 'hate', label: 'Hate speech', description: 'Attacks on people based on a protected characteristic.' },\n { code: 'adult-content', label: 'Explicit / adult content', description: 'Sexual or graphic content not allowed on the platform.' },\n { code: 'violence', label: 'Violence or threats', description: 'Threats of violence, or content glorifying or inciting it.' },\n { code: 'spam', label: 'Spam or scam', description: 'Unsolicited bulk content, deceptive links, or fraud.' },\n { code: 'impersonation', label: 'Impersonation', description: 'Pretending to be another person, brand, or entity.' },\n { code: 'ip', label: 'Intellectual property', description: 'Use of someone else’s work without the right to do so.' },\n { code: 'nonconsensual', label: 'Nonconsensual intimate imagery', description: 'Intimate or sexual imagery shared without the subject’s consent.' },\n { code: 'safety', label: 'Safety violation', description: 'A serious safety violation handled under our safety policies.' },\n { code: 'other', label: 'Other (explain)', description: 'A policy violation not covered above — describe it in the detail box.' },\n] as const;\n\n/** The user-facing label for a reason code (undefined when the code is unknown/absent). */\nexport function userFacingReasonLabel(code: string | undefined): string | undefined {\n return USER_FACING_REASON_OPTIONS.find((o) => o.code === code)?.label;\n}\n\n// --- Rules-surface group titles ---\n// The two rule-GROUP headings for the platform rules content (`Rule.group`\n// 'workProjectType' / 'hallWingType' — see schemas/admin.ts). BOTH the admin rules editor\n// and the public rules page render these, so they are declared once here instead of being\n// restated as literals on each surface (ENG-002). Copy uses the short settled terms Work /\n// Hall / Wing (ARCH-107).\n\nexport const WORK_PROJECT_TYPE_RULE_GROUP_TITLE = 'Work Type Rules';\nexport const HALL_WING_TYPE_RULE_GROUP_TITLE = 'Hall Wing Rules';\n"]}
|
|
1
|
+
{"version":3,"file":"admin-labels.js","sourceRoot":"","sources":["../../src/constants/admin-labels.ts"],"names":[],"mappings":"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","sourcesContent":["// ============================================================================\n// ADMIN-SURFACE DISPLAY LABELS — the ONE home for business display copy keyed\n// by canonical ttt-core enums (ARCH-102, extended 2026-07-13). Consolidated from\n// the former component-local maps in ttt-prod (admin-user-management-view,\n// admin-announcements-view, guided-resolution-flow). Any client (web, phone,\n// TV, admin app) renders the same labels by importing these.\n//\n// A few entries here are copy for ADMIN-MANAGED content that a PUBLIC surface also\n// renders (the rules-page group titles at the bottom of this file). The organizing\n// principle is one declaration, not one consumer.\n// ============================================================================\n\nimport type { UserAccountStatus } from '../doc-schemas/user.js';\nimport type { FeedbackType } from './business-admin.js';\nimport type { ClearableTextFieldName } from './business-content.js';\n// Value import: the per-surface override type below indexes this map to restrict each surface's\n// override keys to the fields that surface actually exposes.\nimport { HALL_CONTENT_TEXT_FIELDS } from './business-content.js';\nimport type { HallContentTextSurface } from '../doc-schemas/content.js';\nimport type { ReportDisposition } from '../doc-schemas/safety/foundation.js';\nimport type { BroadcastAudienceSelector } from '../schemas/notification.js';\nimport type { DeadLetterCollection } from '../schemas/admin.js';\n\n/** Moderation status labels (user-management view, status badges). */\nexport const USER_ACCOUNT_STATUS_LABELS: Record<UserAccountStatus, string> = {\n active: 'Active',\n suspended: 'Suspended',\n banned: 'Banned',\n};\n\n/** Broadcast audience selector labels (announcement composer). */\nexport const BROADCAST_AUDIENCE_KIND_LABELS: Record<BroadcastAudienceSelector['kind'], string> = {\n allActiveUsers: 'All active users',\n allArtisans: 'All artisan creators',\n explicitUids: 'Specific users (paste uids)',\n workMembers: \"A Work's guild members\",\n realmMembers: \"A Realm's members\",\n};\n\n/** Human labels for the canonical feedback types — the admin feedback-suggestions views and\n * the user-facing feedback-submission surface render these instead of restating copy. Keyed\n * by FeedbackType, so a new FEEDBACK_TYPES member fails the build until its label exists.\n * UI copy uses the SHORT settled terms (Trade → \"Trades\", Craft → \"Craft Tags\", Genre →\n * \"<Kind> Genres\"), never the compound code identifiers (ARCH-107). */\nexport const FEEDBACK_TYPE_LABELS: Record<FeedbackType, string> = {\n tradeProfessionSuggestions: 'Trades',\n craftSkillTagSuggestions: 'Craft Tags',\n talesWorkGenreSuggestions: 'Tales Genres',\n tunesWorkGenreSuggestions: 'Tunes Genres',\n televisionWorkGenreSuggestions: 'Television Genres',\n};\n\n/**\n * Human labels for the raw clearable/changeable TEXT-FIELD names the moderation text-clear\n * remedy and the published \"Update details\" change-request flow work in. The backend stores and\n * validates the raw doc field names (`workingTitle`, `description`, `content`); these are the\n * only display strings for them — rendered by the member-facing \"text removed by moderation\"\n * banners, every admin clear-text field picker, the change-request dialog, and the admin\n * change-request work view. Keyed by the derived ClearableTextFieldName union, so a new\n * clearable field fails the build here until it has a label (ARCH-102).\n *\n * The `working*` pair belongs to the Work shell and the Realm doc; the labels stay the plain\n * short terms (ARCH-107 — the code identifier carries `working`, the UI never shows it).\n */\nexport const CLEARABLE_TEXT_FIELD_LABELS: Record<ClearableTextFieldName, string> = {\n workingTitle: 'Title',\n workingDescription: 'Description',\n title: 'Title',\n description: 'Description',\n content: 'Content',\n};\n\n/**\n * Per-surface label overrides for the field labels above: `[surface][field] → label`. Only a\n * surface that genuinely names a field differently appears here; everything else resolves to the\n * base map. Each surface's override keys are restricted to the fields THAT surface exposes\n * (indexed off `HALL_CONTENT_TEXT_FIELDS`), so an override for a field the surface does not have\n * is a compile error — as is an override for a surface outside `HallContentTextSurface`.\n */\nexport type ClearableTextFieldLabelOverrides = {\n [S in HallContentTextSurface]?: {\n [F in (typeof HALL_CONTENT_TEXT_FIELDS)[S][number]]?: string;\n };\n};\n\n/**\n * A Realm's identity field is called **Name** on every Realm surface (DJ ruling 2026-07-29,\n * settling a four-surface Name/Title conflict: the creation flow said \"Realm Name\", the inline\n * edit form \"Working Title\", the moderation-cleared banner \"Title\", and the request-update\n * dialog \"Name\"). The `workingTitle` doc field is shared with the Work shell, where it IS a\n * Title — so the difference is per-surface, not per-field, and lives here rather than flattening\n * one of the two settled terms.\n */\nexport const CLEARABLE_TEXT_FIELD_LABEL_OVERRIDES = {\n workRealm: { workingTitle: 'Name' },\n} as const satisfies ClearableTextFieldLabelOverrides;\n\n/**\n * The display label for one raw clearable text-field name: the surface's override when it has\n * one, otherwise the base label, otherwise the raw name. This is the ONE accessor every surface\n * calls — pass the surface whenever the caller knows it (a Realm surface must, or it renders\n * \"Title\" for a Name); omit it only for a genuinely surface-agnostic caller.\n *\n * Both parameters tolerate a plain `string` because callers read field names off stored documents\n * (`moderationClearedFields`) and callable payloads, and the surface may be the `workProject`\n * shell — which is a clearable surface but not a `HallContentTextSurface`, so it simply has no\n * overrides and falls through to the base map.\n */\nexport function clearableTextFieldLabel(field: string, surface?: string): string {\n const overrides = surface\n ? (CLEARABLE_TEXT_FIELD_LABEL_OVERRIDES as Record<string, Record<string, string> | undefined>)[\n surface\n ]\n : undefined;\n return (\n overrides?.[field] ?? (CLEARABLE_TEXT_FIELD_LABELS as Record<string, string>)[field] ?? field\n );\n}\n\n/** Human labels for the dead-letter replay ledgers (Ops Repairs dead-letter table). */\nexport const DEAD_LETTER_COLLECTION_LABELS: Record<DeadLetterCollection, string> = {\n chatSyncEvents: 'Chat sync event',\n chatAdminActionCommands: 'Chat moderation command',\n notificationDeliveries: 'Notification delivery',\n chatMessageOutbox: 'Chat message publish',\n squareAnnouncementJobs: 'Square announcement',\n chatSyncFanoutJobs: 'Chat access fanout',\n mediaAssets: 'Media authority sync',\n quarantineSagaJobs: 'Quarantine saga',\n nciiRemovalJobs: 'NCII removal',\n safetyEvidenceJobs: 'Safety evidence job',\n accountActionCommands: 'Account safety action',\n activeReportGroups: 'Report edge sync',\n hallSubItemEdgeSync: 'Hall sub-item edge sync',\n};\n\n/** Operator-settable report dispositions with their console copy. 'undetermined' is the\n * initial state, never a settable target, so it carries no option entry. */\nexport const REPORT_DISPOSITION_OPTIONS: readonly {\n value: Exclude<ReportDisposition, 'undetermined'>;\n label: string;\n description: string;\n}[] = [\n {\n value: 'reportRequired',\n label: 'Report required (NCMEC)',\n description:\n 'Apparent CSAM — a report is legally required. Establishes actual knowledge + arms the clock.',\n },\n {\n value: 'notRequired',\n label: 'No report required',\n description: 'No reporting obligation ever arose. Disallowed once there is a validated match.',\n },\n {\n value: 'correctedNoApparentViolation',\n label: 'False positive — correct it',\n description: 'There was a triggering signal but on review it is a false positive.',\n },\n];\n\n/** One user-facing reason option (shown to the affected user for any user-affecting action). */\nexport interface UserFacingReasonOption {\n code: string;\n label: string;\n description: string;\n}\n\n/** User-facing reason picklist for the guided case-resolution flow — the affected user sees the\n * label for any user-affecting action. Canonical home (ARCH-102): the codes ARE this list's own\n * enumeration, so every client (web, phone, TV, admin app) renders the same options + labels by\n * importing from here. Final user-/legal-facing wording is subject to lawyer review; these are\n * functional defaults. */\nexport const USER_FACING_REASON_OPTIONS: readonly UserFacingReasonOption[] = [\n { code: 'harassment', label: 'Harassment or bullying', description: 'Targeted abuse, threats, or sustained harassment of a person.' },\n { code: 'hate', label: 'Hate speech', description: 'Attacks on people based on a protected characteristic.' },\n { code: 'adult-content', label: 'Explicit / adult content', description: 'Sexual or graphic content not allowed on the platform.' },\n { code: 'violence', label: 'Violence or threats', description: 'Threats of violence, or content glorifying or inciting it.' },\n { code: 'spam', label: 'Spam or scam', description: 'Unsolicited bulk content, deceptive links, or fraud.' },\n { code: 'impersonation', label: 'Impersonation', description: 'Pretending to be another person, brand, or entity.' },\n { code: 'ip', label: 'Intellectual property', description: 'Use of someone else’s work without the right to do so.' },\n { code: 'nonconsensual', label: 'Nonconsensual intimate imagery', description: 'Intimate or sexual imagery shared without the subject’s consent.' },\n { code: 'safety', label: 'Safety violation', description: 'A serious safety violation handled under our safety policies.' },\n { code: 'other', label: 'Other (explain)', description: 'A policy violation not covered above — describe it in the detail box.' },\n] as const;\n\n/** The user-facing label for a reason code (undefined when the code is unknown/absent). */\nexport function userFacingReasonLabel(code: string | undefined): string | undefined {\n return USER_FACING_REASON_OPTIONS.find((o) => o.code === code)?.label;\n}\n\n// --- Rules-surface group titles ---\n// The two rule-GROUP headings for the platform rules content (`Rule.group`\n// 'workProjectType' / 'hallWingType' — see schemas/admin.ts). BOTH the admin rules editor\n// and the public rules page render these, so they are declared once here instead of being\n// restated as literals on each surface (ENG-002). Copy uses the short settled terms Work /\n// Hall / Wing (ARCH-107).\n\nexport const WORK_PROJECT_TYPE_RULE_GROUP_TITLE = 'Work Type Rules';\nexport const HALL_WING_TYPE_RULE_GROUP_TITLE = 'Hall Wing Rules';\n"]}
|
|
@@ -43,6 +43,13 @@ export declare const MODERATION_CLEARABLE_TEXT_FIELDS: {
|
|
|
43
43
|
};
|
|
44
44
|
/** A surface whose text fields the moderation clear remedy can neutralize. */
|
|
45
45
|
export type ModerationClearableSurface = keyof typeof MODERATION_CLEARABLE_TEXT_FIELDS;
|
|
46
|
+
/**
|
|
47
|
+
* Every DISTINCT clearable/changeable text-field NAME, DERIVED from the canonical
|
|
48
|
+
* MODERATION_CLEARABLE_TEXT_FIELDS map (the union of every surface's tuple). Label maps and
|
|
49
|
+
* per-field cap maps key on this instead of `string`, so adding a field to a surface is a
|
|
50
|
+
* compile error until its label and cap exist.
|
|
51
|
+
*/
|
|
52
|
+
export type ClearableTextFieldName = (typeof MODERATION_CLEARABLE_TEXT_FIELDS)[ModerationClearableSurface][number];
|
|
46
53
|
/**
|
|
47
54
|
* The DISTINCT clearable text-field NAMES across the whole hall content family (tale/tune/
|
|
48
55
|
* television detail → title/description; chapter → title/content; track/episode →
|
|
@@ -74,7 +81,9 @@ export declare const HALL_CONTENT_TEXT_FIELDS: {
|
|
|
74
81
|
/** Per-field max lengths for proposed hall-content text. DERIVED from the owning
|
|
75
82
|
* constants — never independent numbers — so the change-request pipeline can never
|
|
76
83
|
* drift from the authoring limits again (the pre-2026-07-13 copy carried its own
|
|
77
|
-
* 200/5000/100000 set while authoring enforced 150/300/2500).
|
|
84
|
+
* 200/5000/100000 set while authoring enforced 150/300/2500). Keyed on the derived
|
|
85
|
+
* ClearableTextFieldName union, so a new clearable field fails the build here until
|
|
86
|
+
* it has a cap. */
|
|
78
87
|
export declare const HALL_CONTENT_TEXT_FIELD_MAX: {
|
|
79
88
|
readonly title: 150;
|
|
80
89
|
readonly description: 1000;
|
|
@@ -82,6 +91,53 @@ export declare const HALL_CONTENT_TEXT_FIELD_MAX: {
|
|
|
82
91
|
readonly workingTitle: 150;
|
|
83
92
|
readonly workingDescription: 1000;
|
|
84
93
|
};
|
|
94
|
+
/** One work-project type's two hall text surfaces — the published DETAIL on the hall parent
|
|
95
|
+
* and its chapter/track/episode SUB-ITEM — each with the clearable/changeable field tuple
|
|
96
|
+
* that surface exposes. */
|
|
97
|
+
export interface HallContentSurfaceRouting {
|
|
98
|
+
/** Surface identity of the hall parent DETAIL (tale / tune / television). */
|
|
99
|
+
detailSurface: ModerationClearableSurface;
|
|
100
|
+
/** The DETAIL surface's clearable text fields. */
|
|
101
|
+
detailFields: readonly ClearableTextFieldName[];
|
|
102
|
+
/** Surface identity of the SUB-ITEM (chapter / tuneTrack / televisionEpisode). */
|
|
103
|
+
subItemSurface: ModerationClearableSurface;
|
|
104
|
+
/** The SUB-ITEM surface's clearable text fields — a Tale chapter carries title/content, a
|
|
105
|
+
* Tune track and a Television episode title/description. */
|
|
106
|
+
subItemFields: readonly ClearableTextFieldName[];
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* CANONICAL WorkProjectType → hall text-surface routing. The ONE owner of "a Tale's sub-item is
|
|
110
|
+
* a chapter, a Tune's is a tuneTrack, a Television's is a televisionEpisode" and of which fields
|
|
111
|
+
* each of those surfaces exposes. Cross-boundary: the backend text-clear and change-request
|
|
112
|
+
* runners resolve `surface` from (workProjectType, is-sub-item?) through this map, and the admin
|
|
113
|
+
* field pickers project their checkbox options from the same entry — three sites that each
|
|
114
|
+
* hand-rolled the routing before (a ternary that fell through to the tuneTrack tuple for
|
|
115
|
+
* Television, silently correct only because the two tuples happen to match today).
|
|
116
|
+
*
|
|
117
|
+
* Every field tuple is PROJECTED from MODERATION_CLEARABLE_TEXT_FIELDS above — no field literal
|
|
118
|
+
* is restated here — and the `satisfies Record<WorkProjectType, …>` makes adding a work-project
|
|
119
|
+
* type a compile error until its surfaces are routed.
|
|
120
|
+
*/
|
|
121
|
+
export declare const HALL_CONTENT_SURFACES_BY_WORK_TYPE: {
|
|
122
|
+
readonly Tales: {
|
|
123
|
+
readonly detailSurface: "tale";
|
|
124
|
+
readonly detailFields: readonly ["title", "description"];
|
|
125
|
+
readonly subItemSurface: "chapter";
|
|
126
|
+
readonly subItemFields: readonly ["title", "content"];
|
|
127
|
+
};
|
|
128
|
+
readonly Tunes: {
|
|
129
|
+
readonly detailSurface: "tune";
|
|
130
|
+
readonly detailFields: readonly ["title", "description"];
|
|
131
|
+
readonly subItemSurface: "tuneTrack";
|
|
132
|
+
readonly subItemFields: readonly ["title", "description"];
|
|
133
|
+
};
|
|
134
|
+
readonly Television: {
|
|
135
|
+
readonly detailSurface: "television";
|
|
136
|
+
readonly detailFields: readonly ["title", "description"];
|
|
137
|
+
readonly subItemSurface: "televisionEpisode";
|
|
138
|
+
readonly subItemFields: readonly ["title", "description"];
|
|
139
|
+
};
|
|
140
|
+
};
|
|
85
141
|
/** Admin decision reason on a published change request (required on a deny; shown to
|
|
86
142
|
* the member). One owner for the review callable schema AND the admin work-view input. */
|
|
87
143
|
export declare const MAX_HALL_CHANGE_REQUEST_REASON_LENGTH = 2000;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"business-content.d.ts","sourceRoot":"","sources":["../../src/constants/business-content.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"business-content.d.ts","sourceRoot":"","sources":["../../src/constants/business-content.ts"],"names":[],"mappings":"AAYA,gGAAgG;AAChG,eAAO,MAAM,qCAAqC,MAAM,CAAC;AAIzD,8EAA8E;AAC9E,eAAO,MAAM,uBAAuB,QAAkD,CAAC;AAEvF,iEAAiE;AACjE,eAAO,MAAM,2BAA2B,IAAI,CAAC;AAE7C,6CAA6C;AAC7C,eAAO,MAAM,2BAA2B,MAAgC,CAAC;AAEzE,kEAAkE;AAClE,eAAO,MAAM,iCAAiC,MAAM,CAAC;AAIrD;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,oEACqB,CAAC;AAE/D;;;;;GAKG;AACH,eAAO,MAAM,iCAAiC,2BAA2B,CAAC;AAC1E,eAAO,MAAM,iCAAiC,6CAA6C,CAAC;AAE5F;;;;;;;;GAQG;AACH,eAAO,MAAM,gCAAgC;;;;;;;;;CAYS,CAAC;AAEvD,8EAA8E;AAC9E,MAAM,MAAM,0BAA0B,GAAG,MAAM,OAAO,gCAAgC,CAAC;AAEvF;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAChC,CAAC,OAAO,gCAAgC,CAAC,CAAC,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhF;;;;;;;;GAQG;AACH,eAAO,MAAM,+BAA+B,8CAIlC,CAAC;AAEX;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;CASiB,CAAC;AAEvD;;;;;oBAKoB;AACpB,eAAO,MAAM,2BAA2B;;;;;;CAMmB,CAAC;AAE5D;;4BAE4B;AAC5B,MAAM,WAAW,yBAAyB;IACxC,6EAA6E;IAC7E,aAAa,EAAE,0BAA0B,CAAC;IAC1C,kDAAkD;IAClD,YAAY,EAAE,SAAS,sBAAsB,EAAE,CAAC;IAChD,kFAAkF;IAClF,cAAc,EAAE,0BAA0B,CAAC;IAC3C;iEAC6D;IAC7D,aAAa,EAAE,SAAS,sBAAsB,EAAE,CAAC;CAClD;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,kCAAkC;;;;;;;;;;;;;;;;;;;CAmBwB,CAAC;AAExE;2FAC2F;AAC3F,eAAO,MAAM,qCAAqC,OAAO,CAAC;AAI1D;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,6BAA6B,QAEiC,CAAC;AAE5E,eAAO,MAAM,8BAA8B,QAMO,CAAC;AAInD;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB;;;;;CAKO,CAAC;AAI5C,4CAA4C;AAC5C,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAE7C;;4EAE4E;AAC5E,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAC9C,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAE9C,kDAAkD;AAClD,eAAO,MAAM,+BAA+B,OAAO,CAAC;AAEpD;;;;;GAKG;AACH,eAAO,MAAM,iCAAiC,SAAU,CAAC;AAIzD,+CAA+C;AAC/C,eAAO,MAAM,eAAe,MAAM,CAAC;AAEnC,yEAAyE;AACzE,eAAO,MAAM,YAAY,IAAI,CAAC;AAE9B,8EAA8E;AAC9E,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAI7C,iDAAiD;AACjD,eAAO,MAAM,+BAA+B,MAAM,CAAC;AAEnD,kDAAkD;AAClD,eAAO,MAAM,iCAAiC,MAAM,CAAC"}
|
|
@@ -86,7 +86,9 @@ export const HALL_CONTENT_TEXT_FIELDS = {
|
|
|
86
86
|
/** Per-field max lengths for proposed hall-content text. DERIVED from the owning
|
|
87
87
|
* constants — never independent numbers — so the change-request pipeline can never
|
|
88
88
|
* drift from the authoring limits again (the pre-2026-07-13 copy carried its own
|
|
89
|
-
* 200/5000/100000 set while authoring enforced 150/300/2500).
|
|
89
|
+
* 200/5000/100000 set while authoring enforced 150/300/2500). Keyed on the derived
|
|
90
|
+
* ClearableTextFieldName union, so a new clearable field fails the build here until
|
|
91
|
+
* it has a cap. */
|
|
90
92
|
export const HALL_CONTENT_TEXT_FIELD_MAX = {
|
|
91
93
|
title: MAX_WORK_PROJECT_TITLE_LENGTH,
|
|
92
94
|
description: MAX_WORK_PROJECT_DESCRIPTION_LENGTH,
|
|
@@ -94,6 +96,39 @@ export const HALL_CONTENT_TEXT_FIELD_MAX = {
|
|
|
94
96
|
workingTitle: MAX_WORK_REALM_TITLE_LENGTH,
|
|
95
97
|
workingDescription: MAX_WORK_REALM_DESCRIPTION_LENGTH,
|
|
96
98
|
};
|
|
99
|
+
/**
|
|
100
|
+
* CANONICAL WorkProjectType → hall text-surface routing. The ONE owner of "a Tale's sub-item is
|
|
101
|
+
* a chapter, a Tune's is a tuneTrack, a Television's is a televisionEpisode" and of which fields
|
|
102
|
+
* each of those surfaces exposes. Cross-boundary: the backend text-clear and change-request
|
|
103
|
+
* runners resolve `surface` from (workProjectType, is-sub-item?) through this map, and the admin
|
|
104
|
+
* field pickers project their checkbox options from the same entry — three sites that each
|
|
105
|
+
* hand-rolled the routing before (a ternary that fell through to the tuneTrack tuple for
|
|
106
|
+
* Television, silently correct only because the two tuples happen to match today).
|
|
107
|
+
*
|
|
108
|
+
* Every field tuple is PROJECTED from MODERATION_CLEARABLE_TEXT_FIELDS above — no field literal
|
|
109
|
+
* is restated here — and the `satisfies Record<WorkProjectType, …>` makes adding a work-project
|
|
110
|
+
* type a compile error until its surfaces are routed.
|
|
111
|
+
*/
|
|
112
|
+
export const HALL_CONTENT_SURFACES_BY_WORK_TYPE = {
|
|
113
|
+
Tales: {
|
|
114
|
+
detailSurface: 'tale',
|
|
115
|
+
detailFields: MODERATION_CLEARABLE_TEXT_FIELDS.tale,
|
|
116
|
+
subItemSurface: 'chapter',
|
|
117
|
+
subItemFields: MODERATION_CLEARABLE_TEXT_FIELDS.chapter,
|
|
118
|
+
},
|
|
119
|
+
Tunes: {
|
|
120
|
+
detailSurface: 'tune',
|
|
121
|
+
detailFields: MODERATION_CLEARABLE_TEXT_FIELDS.tune,
|
|
122
|
+
subItemSurface: 'tuneTrack',
|
|
123
|
+
subItemFields: MODERATION_CLEARABLE_TEXT_FIELDS.tuneTrack,
|
|
124
|
+
},
|
|
125
|
+
Television: {
|
|
126
|
+
detailSurface: 'television',
|
|
127
|
+
detailFields: MODERATION_CLEARABLE_TEXT_FIELDS.television,
|
|
128
|
+
subItemSurface: 'televisionEpisode',
|
|
129
|
+
subItemFields: MODERATION_CLEARABLE_TEXT_FIELDS.televisionEpisode,
|
|
130
|
+
},
|
|
131
|
+
};
|
|
97
132
|
/** Admin decision reason on a published change request (required on a deny; shown to
|
|
98
133
|
* the member). One owner for the review callable schema AND the admin work-view input. */
|
|
99
134
|
export const MAX_HALL_CHANGE_REQUEST_REASON_LENGTH = 2000;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"business-content.js","sourceRoot":"","sources":["../../src/constants/business-content.ts"],"names":[],"mappings":"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","sourcesContent":["// Content-surface business-rule constants — commissions, auditions, the social\n// feed, and messaging.\nimport {\n MAX_WORK_PROJECT_TITLE_LENGTH,\n MAX_WORK_PROJECT_DESCRIPTION_LENGTH,\n MAX_CHAPTER_CONTENT_LENGTH,\n MAX_WORK_REALM_TITLE_LENGTH,\n MAX_WORK_REALM_DESCRIPTION_LENGTH,\n} from \"./business-work-project.js\";\nimport { ACTIVE_LIMITS } from './app-mode.js';\n\n/** The maximum character length for a SquareStreetz post created on behalf of a workProject. */\nexport const MAX_SQUARE_STREETZ_DESCRIPTION_LENGTH = 150;\n\n// --- Commission Board & Proposals ---\n\n/** Maximum number of open commissions a workProject can have. Mode-varied. */\nexport const MAX_COMMISSION_LISTINGS = ACTIVE_LIMITS.workProject.maxCommissionListings;\n\n/** Maximum number of proposal artisans saved to a commission. */\nexport const MAX_SAVED_PROPOSAL_ARTISANS = 5;\n\n/** Maximum length for a commission title. */\nexport const MAX_COMMISSION_TITLE_LENGTH = MAX_WORK_PROJECT_TITLE_LENGTH;\n\n/** Maximum length for a commission description / cover letter. */\nexport const MAX_COMMISSION_DESCRIPTION_LENGTH = 400;\n\n// --- Moderation text-clear + published hall-content text fields ---\n\n/**\n * Neutral placeholder written into a single cleared text field by the moderation\n * text-clear remedy. Canonical wording — the backend `runModerationClearText`\n * core writes exactly this string; a wording change is a single edit here.\n */\nexport const MODERATION_CLEAR_PLACEHOLDER =\n 'Removed by moderation — awaiting an update by the steward.';\n\n/**\n * Default REASON strings recorded on a moderation action when the admin supplies no\n * user-facing reason. Distinct from MODERATION_CLEAR_PLACEHOLDER (which is written INTO\n * cleared content fields) — these are the recorded justification text. Canonical wording;\n * consumers (resolveAdminTask's forceRetitle / chat-delete actions) never inline them.\n */\nexport const MODERATION_DEFAULT_REMOVAL_REASON = 'Removed by moderation.';\nexport const MODERATION_DEFAULT_RETITLE_REASON = 'Title/description removed by moderation.';\n\n/**\n * CANONICAL clearable text-field map for the per-field moderation TEXT-CLEAR remedy.\n * Cross-boundary single owner: the admin field-picker offers this set per surface and\n * the backend clear runner validates + normalizes caller-supplied fields against it.\n * Keys are surfaces; values are the exact document field names (NOT display labels)\n * recorded verbatim in `moderationClearedFields`. Covers every clearable surface —\n * workProject/workRealm shell metadata, hall parent details (tale/tune/television),\n * and hall sub-items (chapter/track/episode).\n */\nexport const MODERATION_CLEARABLE_TEXT_FIELDS = {\n // workProject + workRealm shell metadata\n workProject: ['workingTitle', 'workingDescription'],\n workRealm: ['workingTitle', 'workingDescription'],\n // hall content parent details\n tale: ['title', 'description'],\n tune: ['title', 'description'],\n television: ['title', 'description'],\n // hall content sub-items\n chapter: ['title', 'content'],\n tuneTrack: ['title', 'description'],\n televisionEpisode: ['title', 'description'],\n} as const satisfies Record<string, readonly string[]>;\n\n/** A surface whose text fields the moderation clear remedy can neutralize. */\nexport type ModerationClearableSurface = keyof typeof MODERATION_CLEARABLE_TEXT_FIELDS;\n\n/**\n * The DISTINCT clearable text-field NAMES across the whole hall content family (tale/tune/\n * television detail → title/description; chapter → title/content; track/episode →\n * title/description). DERIVED from the canonical MODERATION_CLEARABLE_TEXT_FIELDS map — the\n * union of every hall surface's fields — so the `clearHallContentText` callable's field-enum\n * (`HallClearFieldSchema`) never restates the `title`/`description`/`content` literals. Index\n * access on the map's readonly tuples preserves the literal types, so this stays a typed\n * `readonly ['title','description','content']` a `z.enum(...)` can consume directly.\n */\nexport const HALL_CLEARABLE_TEXT_FIELD_NAMES = [\n MODERATION_CLEARABLE_TEXT_FIELDS.tale[0], // title\n MODERATION_CLEARABLE_TEXT_FIELDS.tale[1], // description\n MODERATION_CLEARABLE_TEXT_FIELDS.chapter[1], // content\n] as const;\n\n/**\n * The raw doc field names each published hall-content surface exposes as changeable TEXT.\n * Cross-boundary: the member \"Update details\" field picker offers this set per surface and\n * the change-request submit runner validates against it. Detail surfaces (tale/tune/\n * television) live on the hall parent doc; sub-item surfaces on the published chapter/\n * track/episode doc. This is the HALL-SURFACE SUBSET of the canonical\n * MODERATION_CLEARABLE_TEXT_FIELDS above (it excludes the `workProject` shell) — every\n * tuple is projected from that one owner, so the two can never drift.\n */\nexport const HALL_CONTENT_TEXT_FIELDS = {\n tale: MODERATION_CLEARABLE_TEXT_FIELDS.tale,\n tune: MODERATION_CLEARABLE_TEXT_FIELDS.tune,\n television: MODERATION_CLEARABLE_TEXT_FIELDS.television,\n chapter: MODERATION_CLEARABLE_TEXT_FIELDS.chapter,\n tuneTrack: MODERATION_CLEARABLE_TEXT_FIELDS.tuneTrack,\n televisionEpisode: MODERATION_CLEARABLE_TEXT_FIELDS.televisionEpisode,\n // Realm grain (R1, 2026-07-12): targets the `workRealms/{id}` doc directly.\n workRealm: MODERATION_CLEARABLE_TEXT_FIELDS.workRealm,\n} as const satisfies Record<string, readonly string[]>;\n\n/** Per-field max lengths for proposed hall-content text. DERIVED from the owning\n * constants — never independent numbers — so the change-request pipeline can never\n * drift from the authoring limits again (the pre-2026-07-13 copy carried its own\n * 200/5000/100000 set while authoring enforced 150/300/2500). */\nexport const HALL_CONTENT_TEXT_FIELD_MAX = {\n title: MAX_WORK_PROJECT_TITLE_LENGTH,\n description: MAX_WORK_PROJECT_DESCRIPTION_LENGTH,\n content: MAX_CHAPTER_CONTENT_LENGTH,\n workingTitle: MAX_WORK_REALM_TITLE_LENGTH,\n workingDescription: MAX_WORK_REALM_DESCRIPTION_LENGTH,\n} as const satisfies Record<string, number>;\n\n/** Admin decision reason on a published change request (required on a deny; shown to\n * the member). One owner for the review callable schema AND the admin work-view input. */\nexport const MAX_HALL_CHANGE_REQUEST_REASON_LENGTH = 2000;\n\n// --- Real-people / parody disclaimer (R3, 2026-07-12) ---\n\n/**\n * The ONE standard platform disclaimer rendered on every published work whose\n * author attested it depicts real people (parody / satire / commentary). Two\n * layers, always shown together (DJ, 2026-07-12): the themed playbill HEADER\n * on top, the plain legal MESSAGE underneath. There is no free-text disclaimer\n * anywhere — these constants are the only wording, so a wording change is a\n * single edit here (display surfaces and any backend consumer read these; the\n * text is never persisted on docs). The MESSAGE deliberately never ADMITS the\n * work depicts real people — it hedges (\"even those based on real people\",\n * the standard film-boilerplate move) so the disclaimer never hands over the\n * depiction element of a claim. Legal wording pending counsel confirmation\n * (tracked in docs/ttt-prod-legal/).\n */\nexport const REAL_PEOPLE_DISCLAIMER_HEADER =\n 'A Notice from the Management: the faces may be familiar, but the players are pure ' +\n 'invention — parody and satire, in the grand old tradition of the stage.';\n\nexport const REAL_PEOPLE_DISCLAIMER_MESSAGE =\n 'All characters, statements, and events in this work, even those based on real people, ' +\n 'are entirely fictional and are presented as parody, satire, or commentary. Any voices, ' +\n 'likenesses, or portrayals of real people are impersonated or fictionalized, and nothing ' +\n 'in this work should be understood as a statement of fact about, or as speech by, any ' +\n 'real person. This work is not created by, affiliated with, sponsored by, or endorsed by ' +\n 'any real person portrayed or referenced in it.';\n\n// --- Hall library per-user viewing-state doc (hall-viewing-experience Area 2, ruled 2026-07-04) ---\n\n/**\n * Caps for the per-user Hall viewing-state doc (`HallLibraryPreferencesSchema`,\n * `userProfiles/{uid}/privateData/hallLibraryPreferences`). Every list on that doc is\n * capped for launch — no unbounded per-user lists. `hiddenWorkIds`/`inkedWorkIds` are\n * oldest-pruned (or the write is rejected with a friendly message once full);\n * `inProgress` is LRU-pruned by `updatedAt`; `recentlyViewed` is capped, newest-kept.\n * Enforcement lives in the backend core (`runX`) that owns this doc — this is the\n * shared source of truth for the cap values themselves.\n */\nexport const HALL_LIBRARY_PREFS_CAPS = {\n hiddenWorkIds: 200,\n inkedWorkIds: 200,\n inProgress: 50,\n recentlyViewed: 20,\n} as const satisfies Record<string, number>;\n\n// --- Auditions ---\n\n/** Maximum length for an audition title. */\nexport const MAX_AUDITION_TITLE_LENGTH = 150;\n\n/** Curated-audition option-video batch bounds (the fixed 2..8 option count carried\n * from the Create click through targetInfo/upload-variables to the create core's\n * re-check). ONE declaration — every `.min()/.max()` derives from these. */\nexport const MIN_CURATED_AUDITION_OPTIONS = 2;\nexport const MAX_CURATED_AUDITION_OPTIONS = 8;\n\n/** Maximum length for an audition description. */\nexport const MAX_AUDITION_DESCRIPTION_LENGTH = 1000;\n\n/**\n * Maximum sponsored-audition payout amount in whole USD accepted at the upload\n * trust boundary. Mirrors MAX_PLEDGE_PAYMENT_AMOUNT_CENTS ($500,000) expressed\n * in dollars — a finite ceiling that rejects absurd/garbage amounts before any\n * downstream processing.\n */\nexport const MAX_SPONSORED_AUDITION_AMOUNT_USD = 500_000;\n\n// --- SquareStreetz (Social Feed) ---\n\n/** Maximum length for a SquareStreetz post. */\nexport const MAX_POST_LENGTH = 500;\n\n/** Maximum number of mentions allowed in a single SquareStreetz post. */\nexport const MAX_MENTIONS = 3;\n\n/** Maximum characters of a mention's display name shown before truncation. */\nexport const MAX_MENTION_DISPLAY_LENGTH = 30;\n\n// --- Messages & Invites ---\n\n/** Maximum length for a guild-invite message. */\nexport const MAX_GUILD_INVITE_MESSAGE_LENGTH = 500;\n\n/** Maximum length for a pledgePayment message. */\nexport const MAX_PLEDGE_PAYMENT_MESSAGE_LENGTH = 500;\n"]}
|
|
1
|
+
{"version":3,"file":"business-content.js","sourceRoot":"","sources":["../../src/constants/business-content.ts"],"names":[],"mappings":"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","sourcesContent":["// Content-surface business-rule constants — commissions, auditions, the social\n// feed, and messaging.\nimport {\n MAX_WORK_PROJECT_TITLE_LENGTH,\n MAX_WORK_PROJECT_DESCRIPTION_LENGTH,\n MAX_CHAPTER_CONTENT_LENGTH,\n MAX_WORK_REALM_TITLE_LENGTH,\n MAX_WORK_REALM_DESCRIPTION_LENGTH,\n} from \"./business-work-project.js\";\nimport { ACTIVE_LIMITS } from './app-mode.js';\nimport type { WorkProjectType } from '../types/content.js';\n\n/** The maximum character length for a SquareStreetz post created on behalf of a workProject. */\nexport const MAX_SQUARE_STREETZ_DESCRIPTION_LENGTH = 150;\n\n// --- Commission Board & Proposals ---\n\n/** Maximum number of open commissions a workProject can have. Mode-varied. */\nexport const MAX_COMMISSION_LISTINGS = ACTIVE_LIMITS.workProject.maxCommissionListings;\n\n/** Maximum number of proposal artisans saved to a commission. */\nexport const MAX_SAVED_PROPOSAL_ARTISANS = 5;\n\n/** Maximum length for a commission title. */\nexport const MAX_COMMISSION_TITLE_LENGTH = MAX_WORK_PROJECT_TITLE_LENGTH;\n\n/** Maximum length for a commission description / cover letter. */\nexport const MAX_COMMISSION_DESCRIPTION_LENGTH = 400;\n\n// --- Moderation text-clear + published hall-content text fields ---\n\n/**\n * Neutral placeholder written into a single cleared text field by the moderation\n * text-clear remedy. Canonical wording — the backend `runModerationClearText`\n * core writes exactly this string; a wording change is a single edit here.\n */\nexport const MODERATION_CLEAR_PLACEHOLDER =\n 'Removed by moderation — awaiting an update by the steward.';\n\n/**\n * Default REASON strings recorded on a moderation action when the admin supplies no\n * user-facing reason. Distinct from MODERATION_CLEAR_PLACEHOLDER (which is written INTO\n * cleared content fields) — these are the recorded justification text. Canonical wording;\n * consumers (resolveAdminTask's forceRetitle / chat-delete actions) never inline them.\n */\nexport const MODERATION_DEFAULT_REMOVAL_REASON = 'Removed by moderation.';\nexport const MODERATION_DEFAULT_RETITLE_REASON = 'Title/description removed by moderation.';\n\n/**\n * CANONICAL clearable text-field map for the per-field moderation TEXT-CLEAR remedy.\n * Cross-boundary single owner: the admin field-picker offers this set per surface and\n * the backend clear runner validates + normalizes caller-supplied fields against it.\n * Keys are surfaces; values are the exact document field names (NOT display labels)\n * recorded verbatim in `moderationClearedFields`. Covers every clearable surface —\n * workProject/workRealm shell metadata, hall parent details (tale/tune/television),\n * and hall sub-items (chapter/track/episode).\n */\nexport const MODERATION_CLEARABLE_TEXT_FIELDS = {\n // workProject + workRealm shell metadata\n workProject: ['workingTitle', 'workingDescription'],\n workRealm: ['workingTitle', 'workingDescription'],\n // hall content parent details\n tale: ['title', 'description'],\n tune: ['title', 'description'],\n television: ['title', 'description'],\n // hall content sub-items\n chapter: ['title', 'content'],\n tuneTrack: ['title', 'description'],\n televisionEpisode: ['title', 'description'],\n} as const satisfies Record<string, readonly string[]>;\n\n/** A surface whose text fields the moderation clear remedy can neutralize. */\nexport type ModerationClearableSurface = keyof typeof MODERATION_CLEARABLE_TEXT_FIELDS;\n\n/**\n * Every DISTINCT clearable/changeable text-field NAME, DERIVED from the canonical\n * MODERATION_CLEARABLE_TEXT_FIELDS map (the union of every surface's tuple). Label maps and\n * per-field cap maps key on this instead of `string`, so adding a field to a surface is a\n * compile error until its label and cap exist.\n */\nexport type ClearableTextFieldName =\n (typeof MODERATION_CLEARABLE_TEXT_FIELDS)[ModerationClearableSurface][number];\n\n/**\n * The DISTINCT clearable text-field NAMES across the whole hall content family (tale/tune/\n * television detail → title/description; chapter → title/content; track/episode →\n * title/description). DERIVED from the canonical MODERATION_CLEARABLE_TEXT_FIELDS map — the\n * union of every hall surface's fields — so the `clearHallContentText` callable's field-enum\n * (`HallClearFieldSchema`) never restates the `title`/`description`/`content` literals. Index\n * access on the map's readonly tuples preserves the literal types, so this stays a typed\n * `readonly ['title','description','content']` a `z.enum(...)` can consume directly.\n */\nexport const HALL_CLEARABLE_TEXT_FIELD_NAMES = [\n MODERATION_CLEARABLE_TEXT_FIELDS.tale[0], // title\n MODERATION_CLEARABLE_TEXT_FIELDS.tale[1], // description\n MODERATION_CLEARABLE_TEXT_FIELDS.chapter[1], // content\n] as const;\n\n/**\n * The raw doc field names each published hall-content surface exposes as changeable TEXT.\n * Cross-boundary: the member \"Update details\" field picker offers this set per surface and\n * the change-request submit runner validates against it. Detail surfaces (tale/tune/\n * television) live on the hall parent doc; sub-item surfaces on the published chapter/\n * track/episode doc. This is the HALL-SURFACE SUBSET of the canonical\n * MODERATION_CLEARABLE_TEXT_FIELDS above (it excludes the `workProject` shell) — every\n * tuple is projected from that one owner, so the two can never drift.\n */\nexport const HALL_CONTENT_TEXT_FIELDS = {\n tale: MODERATION_CLEARABLE_TEXT_FIELDS.tale,\n tune: MODERATION_CLEARABLE_TEXT_FIELDS.tune,\n television: MODERATION_CLEARABLE_TEXT_FIELDS.television,\n chapter: MODERATION_CLEARABLE_TEXT_FIELDS.chapter,\n tuneTrack: MODERATION_CLEARABLE_TEXT_FIELDS.tuneTrack,\n televisionEpisode: MODERATION_CLEARABLE_TEXT_FIELDS.televisionEpisode,\n // Realm grain (R1, 2026-07-12): targets the `workRealms/{id}` doc directly.\n workRealm: MODERATION_CLEARABLE_TEXT_FIELDS.workRealm,\n} as const satisfies Record<string, readonly string[]>;\n\n/** Per-field max lengths for proposed hall-content text. DERIVED from the owning\n * constants — never independent numbers — so the change-request pipeline can never\n * drift from the authoring limits again (the pre-2026-07-13 copy carried its own\n * 200/5000/100000 set while authoring enforced 150/300/2500). Keyed on the derived\n * ClearableTextFieldName union, so a new clearable field fails the build here until\n * it has a cap. */\nexport const HALL_CONTENT_TEXT_FIELD_MAX = {\n title: MAX_WORK_PROJECT_TITLE_LENGTH,\n description: MAX_WORK_PROJECT_DESCRIPTION_LENGTH,\n content: MAX_CHAPTER_CONTENT_LENGTH,\n workingTitle: MAX_WORK_REALM_TITLE_LENGTH,\n workingDescription: MAX_WORK_REALM_DESCRIPTION_LENGTH,\n} as const satisfies Record<ClearableTextFieldName, number>;\n\n/** One work-project type's two hall text surfaces — the published DETAIL on the hall parent\n * and its chapter/track/episode SUB-ITEM — each with the clearable/changeable field tuple\n * that surface exposes. */\nexport interface HallContentSurfaceRouting {\n /** Surface identity of the hall parent DETAIL (tale / tune / television). */\n detailSurface: ModerationClearableSurface;\n /** The DETAIL surface's clearable text fields. */\n detailFields: readonly ClearableTextFieldName[];\n /** Surface identity of the SUB-ITEM (chapter / tuneTrack / televisionEpisode). */\n subItemSurface: ModerationClearableSurface;\n /** The SUB-ITEM surface's clearable text fields — a Tale chapter carries title/content, a\n * Tune track and a Television episode title/description. */\n subItemFields: readonly ClearableTextFieldName[];\n}\n\n/**\n * CANONICAL WorkProjectType → hall text-surface routing. The ONE owner of \"a Tale's sub-item is\n * a chapter, a Tune's is a tuneTrack, a Television's is a televisionEpisode\" and of which fields\n * each of those surfaces exposes. Cross-boundary: the backend text-clear and change-request\n * runners resolve `surface` from (workProjectType, is-sub-item?) through this map, and the admin\n * field pickers project their checkbox options from the same entry — three sites that each\n * hand-rolled the routing before (a ternary that fell through to the tuneTrack tuple for\n * Television, silently correct only because the two tuples happen to match today).\n *\n * Every field tuple is PROJECTED from MODERATION_CLEARABLE_TEXT_FIELDS above — no field literal\n * is restated here — and the `satisfies Record<WorkProjectType, …>` makes adding a work-project\n * type a compile error until its surfaces are routed.\n */\nexport const HALL_CONTENT_SURFACES_BY_WORK_TYPE = {\n Tales: {\n detailSurface: 'tale',\n detailFields: MODERATION_CLEARABLE_TEXT_FIELDS.tale,\n subItemSurface: 'chapter',\n subItemFields: MODERATION_CLEARABLE_TEXT_FIELDS.chapter,\n },\n Tunes: {\n detailSurface: 'tune',\n detailFields: MODERATION_CLEARABLE_TEXT_FIELDS.tune,\n subItemSurface: 'tuneTrack',\n subItemFields: MODERATION_CLEARABLE_TEXT_FIELDS.tuneTrack,\n },\n Television: {\n detailSurface: 'television',\n detailFields: MODERATION_CLEARABLE_TEXT_FIELDS.television,\n subItemSurface: 'televisionEpisode',\n subItemFields: MODERATION_CLEARABLE_TEXT_FIELDS.televisionEpisode,\n },\n} as const satisfies Record<WorkProjectType, HallContentSurfaceRouting>;\n\n/** Admin decision reason on a published change request (required on a deny; shown to\n * the member). One owner for the review callable schema AND the admin work-view input. */\nexport const MAX_HALL_CHANGE_REQUEST_REASON_LENGTH = 2000;\n\n// --- Real-people / parody disclaimer (R3, 2026-07-12) ---\n\n/**\n * The ONE standard platform disclaimer rendered on every published work whose\n * author attested it depicts real people (parody / satire / commentary). Two\n * layers, always shown together (DJ, 2026-07-12): the themed playbill HEADER\n * on top, the plain legal MESSAGE underneath. There is no free-text disclaimer\n * anywhere — these constants are the only wording, so a wording change is a\n * single edit here (display surfaces and any backend consumer read these; the\n * text is never persisted on docs). The MESSAGE deliberately never ADMITS the\n * work depicts real people — it hedges (\"even those based on real people\",\n * the standard film-boilerplate move) so the disclaimer never hands over the\n * depiction element of a claim. Legal wording pending counsel confirmation\n * (tracked in docs/ttt-prod-legal/).\n */\nexport const REAL_PEOPLE_DISCLAIMER_HEADER =\n 'A Notice from the Management: the faces may be familiar, but the players are pure ' +\n 'invention — parody and satire, in the grand old tradition of the stage.';\n\nexport const REAL_PEOPLE_DISCLAIMER_MESSAGE =\n 'All characters, statements, and events in this work, even those based on real people, ' +\n 'are entirely fictional and are presented as parody, satire, or commentary. Any voices, ' +\n 'likenesses, or portrayals of real people are impersonated or fictionalized, and nothing ' +\n 'in this work should be understood as a statement of fact about, or as speech by, any ' +\n 'real person. This work is not created by, affiliated with, sponsored by, or endorsed by ' +\n 'any real person portrayed or referenced in it.';\n\n// --- Hall library per-user viewing-state doc (hall-viewing-experience Area 2, ruled 2026-07-04) ---\n\n/**\n * Caps for the per-user Hall viewing-state doc (`HallLibraryPreferencesSchema`,\n * `userProfiles/{uid}/privateData/hallLibraryPreferences`). Every list on that doc is\n * capped for launch — no unbounded per-user lists. `hiddenWorkIds`/`inkedWorkIds` are\n * oldest-pruned (or the write is rejected with a friendly message once full);\n * `inProgress` is LRU-pruned by `updatedAt`; `recentlyViewed` is capped, newest-kept.\n * Enforcement lives in the backend core (`runX`) that owns this doc — this is the\n * shared source of truth for the cap values themselves.\n */\nexport const HALL_LIBRARY_PREFS_CAPS = {\n hiddenWorkIds: 200,\n inkedWorkIds: 200,\n inProgress: 50,\n recentlyViewed: 20,\n} as const satisfies Record<string, number>;\n\n// --- Auditions ---\n\n/** Maximum length for an audition title. */\nexport const MAX_AUDITION_TITLE_LENGTH = 150;\n\n/** Curated-audition option-video batch bounds (the fixed 2..8 option count carried\n * from the Create click through targetInfo/upload-variables to the create core's\n * re-check). ONE declaration — every `.min()/.max()` derives from these. */\nexport const MIN_CURATED_AUDITION_OPTIONS = 2;\nexport const MAX_CURATED_AUDITION_OPTIONS = 8;\n\n/** Maximum length for an audition description. */\nexport const MAX_AUDITION_DESCRIPTION_LENGTH = 1000;\n\n/**\n * Maximum sponsored-audition payout amount in whole USD accepted at the upload\n * trust boundary. Mirrors MAX_PLEDGE_PAYMENT_AMOUNT_CENTS ($500,000) expressed\n * in dollars — a finite ceiling that rejects absurd/garbage amounts before any\n * downstream processing.\n */\nexport const MAX_SPONSORED_AUDITION_AMOUNT_USD = 500_000;\n\n// --- SquareStreetz (Social Feed) ---\n\n/** Maximum length for a SquareStreetz post. */\nexport const MAX_POST_LENGTH = 500;\n\n/** Maximum number of mentions allowed in a single SquareStreetz post. */\nexport const MAX_MENTIONS = 3;\n\n/** Maximum characters of a mention's display name shown before truncation. */\nexport const MAX_MENTION_DISPLAY_LENGTH = 30;\n\n// --- Messages & Invites ---\n\n/** Maximum length for a guild-invite message. */\nexport const MAX_GUILD_INVITE_MESSAGE_LENGTH = 500;\n\n/** Maximum length for a pledgePayment message. */\nexport const MAX_PLEDGE_PAYMENT_MESSAGE_LENGTH = 500;\n"]}
|
|
@@ -61,7 +61,9 @@ export declare const AUDITION_TYPE_FILTER_ALL = "All";
|
|
|
61
61
|
/** Audition-board type-filter state: one canonical audition type, or the ALL sentinel.
|
|
62
62
|
* Filter state derives this instead of being typed `string`. */
|
|
63
63
|
export type AuditionTypeFilter = AuditionType | typeof AUDITION_TYPE_FILTER_ALL;
|
|
64
|
-
/** Sort options shown on the audition feeds, keyed by feed type.
|
|
64
|
+
/** Sort options shown on the audition feeds, keyed by feed type. `default` serves the board's
|
|
65
|
+
* ALL filter; `platformAudition` is the base pair on purpose — the by-type lookup must be total
|
|
66
|
+
* over AuditionType (see the `AUDITION_SORT_OPTIONS[filter]` call sites). */
|
|
65
67
|
export declare const AUDITION_SORT_OPTIONS: {
|
|
66
68
|
readonly default: {
|
|
67
69
|
readonly newest: {
|
|
@@ -88,16 +90,6 @@ export declare const AUDITION_SORT_OPTIONS: {
|
|
|
88
90
|
};
|
|
89
91
|
};
|
|
90
92
|
readonly sponsoredAudition: {
|
|
91
|
-
readonly newest: {
|
|
92
|
-
readonly label: "Newest First";
|
|
93
|
-
readonly field: "createdOn";
|
|
94
|
-
readonly direction: "desc";
|
|
95
|
-
};
|
|
96
|
-
readonly endingSoon: {
|
|
97
|
-
readonly label: "Ending Soon";
|
|
98
|
-
readonly field: "openTill";
|
|
99
|
-
readonly direction: "asc";
|
|
100
|
-
};
|
|
101
93
|
readonly highestPrice: {
|
|
102
94
|
readonly label: "Highest Price";
|
|
103
95
|
readonly field: "sponsoredAuditionAmountUSD";
|
|
@@ -108,8 +100,6 @@ export declare const AUDITION_SORT_OPTIONS: {
|
|
|
108
100
|
readonly field: "sponsoredAuditionAmountUSD";
|
|
109
101
|
readonly direction: "asc";
|
|
110
102
|
};
|
|
111
|
-
};
|
|
112
|
-
readonly workAudition: {
|
|
113
103
|
readonly newest: {
|
|
114
104
|
readonly label: "Newest First";
|
|
115
105
|
readonly field: "createdOn";
|
|
@@ -120,6 +110,8 @@ export declare const AUDITION_SORT_OPTIONS: {
|
|
|
120
110
|
readonly field: "openTill";
|
|
121
111
|
readonly direction: "asc";
|
|
122
112
|
};
|
|
113
|
+
};
|
|
114
|
+
readonly workAudition: {
|
|
123
115
|
readonly highestStakeShares: {
|
|
124
116
|
readonly label: "Highest Stakes";
|
|
125
117
|
readonly field: "stakeSharesOffered";
|
|
@@ -130,6 +122,16 @@ export declare const AUDITION_SORT_OPTIONS: {
|
|
|
130
122
|
readonly field: "stakeSharesOffered";
|
|
131
123
|
readonly direction: "asc";
|
|
132
124
|
};
|
|
125
|
+
readonly newest: {
|
|
126
|
+
readonly label: "Newest First";
|
|
127
|
+
readonly field: "createdOn";
|
|
128
|
+
readonly direction: "desc";
|
|
129
|
+
};
|
|
130
|
+
readonly endingSoon: {
|
|
131
|
+
readonly label: "Ending Soon";
|
|
132
|
+
readonly field: "openTill";
|
|
133
|
+
readonly direction: "asc";
|
|
134
|
+
};
|
|
133
135
|
};
|
|
134
136
|
};
|
|
135
137
|
/** Every sort key any audition feed offers, DERIVED from AUDITION_SORT_OPTIONS above — a new
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/constants/options.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAQ5D;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,4TAyB3B,CAAC;AAEX;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,2bA8B1B,CAAC;AAEX,4FAA4F;AAC5F,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvE,8CAA8C;AAC9C,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1E;gFACgF;AAChF,eAAO,MAAM,uBAAuB,EAA0C,CAC5E,iBAAiB,EACjB,GAAG,iBAAiB,EAAE,CACvB,CAAC;AAEF;oFACoF;AACpF,eAAO,MAAM,sBAAsB,EAAyC,CAC1E,eAAe,EACf,GAAG,eAAe,EAAE,CACrB,CAAC;AAEF,sFAAsF;AACtF,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,CAyB3F,CAAC;AAIF;;;;GAIG;AACH,eAAO,MAAM,4BAA4B;;;;CAiD/B,CAAC;AAIX,mEAAmE;AACnE,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,YAAY,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAaxF,CAAC;AAEF,oEAAoE;AACpE,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,eAAe,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAa9F,CAAC;AAIF;;6EAE6E;AAC7E,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,YAAY,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAavF,CAAC;AAEF;sFACsF;AACtF,eAAO,MAAM,wBAAwB,QAAQ,CAAC;AAE9C;gEACgE;AAChE,MAAM,MAAM,kBAAkB,GAAG,YAAY,GAAG,OAAO,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../../src/constants/options.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAQ5D;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,4TAyB3B,CAAC;AAEX;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,2bA8B1B,CAAC;AAEX,4FAA4F;AAC5F,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvE,8CAA8C;AAC9C,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1E;gFACgF;AAChF,eAAO,MAAM,uBAAuB,EAA0C,CAC5E,iBAAiB,EACjB,GAAG,iBAAiB,EAAE,CACvB,CAAC;AAEF;oFACoF;AACpF,eAAO,MAAM,sBAAsB,EAAyC,CAC1E,eAAe,EACf,GAAG,eAAe,EAAE,CACrB,CAAC;AAEF,sFAAsF;AACtF,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,CAyB3F,CAAC;AAIF;;;;GAIG;AACH,eAAO,MAAM,4BAA4B;;;;CAiD/B,CAAC;AAIX,mEAAmE;AACnE,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,YAAY,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAaxF,CAAC;AAEF,oEAAoE;AACpE,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,eAAe,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAa9F,CAAC;AAIF;;6EAE6E;AAC7E,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,YAAY,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAavF,CAAC;AAEF;sFACsF;AACtF,eAAO,MAAM,wBAAwB,QAAQ,CAAC;AAE9C;gEACgE;AAChE,MAAM,MAAM,kBAAkB,GAAG,YAAY,GAAG,OAAO,wBAAwB,CAAC;AAchF;;6EAE6E;AAC7E,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAaxB,CAAC;AAEX;wFACwF;AACxF,MAAM,MAAM,eAAe,GAAG;KAC3B,CAAC,IAAI,MAAM,OAAO,qBAAqB,GAAG,MAAM,CAAC,OAAO,qBAAqB,CAAC,CAAC,CAAC,CAAC;CACnF,CAAC,MAAM,OAAO,qBAAqB,CAAC,CAAC;AAEtC,oFAAoF;AACpF,eAAO,MAAM,qBAAqB,EAAE,eAA0B,CAAC;AAE/D,kDAAkD;AAClD,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAC5C,MAAM,EACN;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,KAAK,GAAG,MAAM,CAAA;CAAE,CAK5D,CAAC"}
|
|
@@ -216,25 +216,28 @@ export const AUDITION_TYPES = {
|
|
|
216
216
|
* previously hand-rolled app-locally). It doubles as the chip's own display label. */
|
|
217
217
|
export const AUDITION_TYPE_FILTER_ALL = 'All';
|
|
218
218
|
// --- Sort Options ---
|
|
219
|
-
/**
|
|
219
|
+
/**
|
|
220
|
+
* The two sort options EVERY audition feed offers — declared ONCE and spread into each feed's
|
|
221
|
+
* option set below (ENG-002). They used to be restated verbatim in all four feed entries, so
|
|
222
|
+
* a label or field change had to be made four times to avoid drift.
|
|
223
|
+
*/
|
|
224
|
+
const AUDITION_SORT_OPTIONS_BASE = {
|
|
225
|
+
newest: { label: 'Newest First', field: 'createdOn', direction: 'desc' },
|
|
226
|
+
endingSoon: { label: 'Ending Soon', field: 'openTill', direction: 'asc' },
|
|
227
|
+
};
|
|
228
|
+
/** Sort options shown on the audition feeds, keyed by feed type. `default` serves the board's
|
|
229
|
+
* ALL filter; `platformAudition` is the base pair on purpose — the by-type lookup must be total
|
|
230
|
+
* over AuditionType (see the `AUDITION_SORT_OPTIONS[filter]` call sites). */
|
|
220
231
|
export const AUDITION_SORT_OPTIONS = {
|
|
221
|
-
default: {
|
|
222
|
-
|
|
223
|
-
endingSoon: { label: 'Ending Soon', field: 'openTill', direction: 'asc' },
|
|
224
|
-
},
|
|
225
|
-
platformAudition: {
|
|
226
|
-
newest: { label: 'Newest First', field: 'createdOn', direction: 'desc' },
|
|
227
|
-
endingSoon: { label: 'Ending Soon', field: 'openTill', direction: 'asc' },
|
|
228
|
-
},
|
|
232
|
+
default: { ...AUDITION_SORT_OPTIONS_BASE },
|
|
233
|
+
platformAudition: { ...AUDITION_SORT_OPTIONS_BASE },
|
|
229
234
|
sponsoredAudition: {
|
|
230
|
-
|
|
231
|
-
endingSoon: { label: 'Ending Soon', field: 'openTill', direction: 'asc' },
|
|
235
|
+
...AUDITION_SORT_OPTIONS_BASE,
|
|
232
236
|
highestPrice: { label: 'Highest Price', field: 'sponsoredAuditionAmountUSD', direction: 'desc' },
|
|
233
237
|
lowestPrice: { label: 'Lowest Price', field: 'sponsoredAuditionAmountUSD', direction: 'asc' },
|
|
234
238
|
},
|
|
235
239
|
workAudition: {
|
|
236
|
-
|
|
237
|
-
endingSoon: { label: 'Ending Soon', field: 'openTill', direction: 'asc' },
|
|
240
|
+
...AUDITION_SORT_OPTIONS_BASE,
|
|
238
241
|
highestStakeShares: { label: 'Highest Stakes', field: 'stakeSharesOffered', direction: 'desc' },
|
|
239
242
|
lowestStakeShares: { label: 'Lowest Stakes', field: 'stakeSharesOffered', direction: 'asc' },
|
|
240
243
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/constants/options.ts"],"names":[],"mappings":"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","sourcesContent":["// UI option lists shared between frontend and backend admin tooling.\n\nimport type { HallWingType, WorkProjectType } from '../types/content.js';\nimport type { AuditionType } from '../types/commissions.js';\n\n// --- WorkProject Guild Standings ---\n// WorkProject guild-standing IDs, labels, and assignment policy live in ../permissions/.\n// Keep guild-standing picker UIs backed by GUILD_STANDINGS instead of a duplicated option map.\n\n// --- Trade & Craft Options ---\n\n/**\n * Trade professions (20) — role-shaped labels used for guild roles, commission\n * requests, and file-folder permission keys. Display strings are stored/validated\n * directly (they double as the enum values in the callable input schemas that derive\n * from this constant). Kept in curated order; not alphabetized.\n */\nexport const TRADE_PROFESSION_OPTIONS = [\n // Performance\n 'Actor',\n 'Voice Actor',\n 'Singer',\n 'Musician',\n 'Dancer & Choreographer',\n // Story\n 'Writer',\n 'Editor',\n 'Director',\n 'Producer',\n // Camera & visual\n 'Cinematographer',\n 'Photographer',\n 'Animator',\n 'Artist',\n 'Graphic Designer',\n 'VFX Artist',\n 'Costume & Makeup Artist',\n 'Set & Prop Designer',\n // Audio\n 'Composer',\n 'Music Producer',\n 'Sound Designer',\n] as const;\n\n/**\n * Craft-skill discipline tags (23). Tags are Firestore doc IDs in the\n * `craftSkillsByTag/{tag}` index, so the STORED value is a machine-safe kebab-case ID\n * (`CRAFT_SKILL_TAG_OPTIONS`) — this is what the wire schema validates and what path\n * builders write. Human-readable labels (with spaces / ampersands) are mapped over the\n * IDs via `CRAFT_SKILL_TAG_LABELS`; render pickers/badges through that map. Kept in\n * curated discipline order (Performance → Writing → Visual → Film → Audio); not sorted.\n */\nexport const CRAFT_SKILL_TAG_OPTIONS = [\n // Performance\n 'acting',\n 'voice-over',\n 'singing',\n 'rapping',\n 'instrumental-performance',\n 'dance-choreography',\n 'stand-up-sketch-comedy',\n // Writing\n 'writing-storytelling',\n 'songwriting',\n 'poetry-spoken-word',\n // Visual arts\n 'drawing-illustration',\n 'painting',\n 'animation',\n 'graphic-design',\n 'photography',\n // Film & video\n 'cinematography-camera',\n 'video-editing',\n 'visual-effects',\n 'directing',\n 'costume-makeup',\n 'set-prop-design',\n // Audio\n 'music-production',\n 'composing-scoring',\n 'sound-design',\n] as const;\n\n/** The canonical tag-ID type — every tags field/param derives from this, never `string`. */\nexport type CraftSkillTagId = (typeof CRAFT_SKILL_TAG_OPTIONS)[number];\n\n/** The canonical trade-profession ID type. */\nexport type TradeProfessionId = (typeof TRADE_PROFESSION_OPTIONS)[number];\n\n/** TRADE_PROFESSION_OPTIONS as a non-empty tuple for `z.enum(...)` consumers — the ONE\n * cast, here beside the declaration (never re-cast locally in schema files). */\nexport const TRADE_PROFESSION_VALUES = TRADE_PROFESSION_OPTIONS as unknown as [\n TradeProfessionId,\n ...TradeProfessionId[],\n];\n\n/** The same allowlist as a non-empty tuple for `z.enum(...)` consumers — the ONE cast,\n * here beside the declaration (schema files import this, never re-cast locally). */\nexport const CRAFT_SKILL_TAG_VALUES = CRAFT_SKILL_TAG_OPTIONS as unknown as [\n CraftSkillTagId,\n ...CraftSkillTagId[],\n];\n\n/** Human display labels for each craft-skill tag ID. Keyed by the machine-safe ID. */\nexport const CRAFT_SKILL_TAG_LABELS: Record<(typeof CRAFT_SKILL_TAG_OPTIONS)[number], string> = {\n 'acting': 'Acting',\n 'voice-over': 'Voice Over',\n 'singing': 'Singing',\n 'rapping': 'Rapping',\n 'instrumental-performance': 'Instrumental Performance',\n 'dance-choreography': 'Dance & Choreography',\n 'stand-up-sketch-comedy': 'Stand-Up & Sketch Comedy',\n 'writing-storytelling': 'Writing & Storytelling',\n 'songwriting': 'Songwriting',\n 'poetry-spoken-word': 'Poetry & Spoken Word',\n 'drawing-illustration': 'Drawing & Illustration',\n 'painting': 'Painting',\n 'animation': 'Animation',\n 'graphic-design': 'Graphic Design',\n 'photography': 'Photography',\n 'cinematography-camera': 'Cinematography & Camera',\n 'video-editing': 'Video Editing',\n 'visual-effects': 'Visual Effects',\n 'directing': 'Directing',\n 'costume-makeup': 'Costume & Makeup',\n 'set-prop-design': 'Set & Prop Design',\n 'music-production': 'Music Production',\n 'composing-scoring': 'Composing & Scoring',\n 'sound-design': 'Sound Design',\n};\n\n// --- WorkProject-Specific Genres ---\n\n/**\n * Genres shown for each workProject type. Curated final lists (kept in the doc's order,\n * not alphabetized). \"Spooky\" (not \"Horror\") is deliberate for V1: the name carries the\n * all-ages ceiling; \"Horror\" is the natural mature sibling if mature content ever ships.\n */\nexport const WORK_PROJECT_SPECIFIC_GENRES = {\n Tales: [\n 'Adventure',\n 'Comedy',\n 'Drama',\n 'Fantasy',\n 'Fairy Tale & Fable',\n 'Historical',\n 'Mystery',\n 'Romance',\n 'Sci-Fi',\n 'Slice of Life',\n 'Spooky',\n 'Thriller',\n ],\n Tunes: [\n 'Audiobook & Spoken Word',\n 'Blues',\n 'Classical',\n 'Country',\n 'Electronic',\n 'Folk',\n 'Hip Hop & Rap',\n 'Jazz',\n 'Metal',\n 'Podcast',\n 'Pop',\n 'R&B & Soul',\n 'Reggae',\n 'Rock',\n 'Soundtrack & Score',\n ],\n Television: [\n 'Action',\n 'Animation',\n 'Comedy',\n 'Documentary',\n 'Drama',\n 'Fantasy',\n 'Kids & Family',\n 'Music Video',\n 'Mystery',\n 'Reality',\n 'Sci-Fi',\n 'Sketch & Variety',\n 'Spooky',\n 'Talk Show',\n 'Thriller',\n ],\n} as const;\n\n// --- HallLibrary / WorkProject Type Display Maps ---\n\n/** HallLibrary type display info. Used in dropdowns and badges. */\nexport const HALL_WING_TYPES: Record<HallWingType, { label: string; description: string }> = {\n entertainment: {\n label: 'Entertainment',\n description: 'Fun and engaging content',\n },\n educational: {\n label: 'Educational',\n description: 'Learning materials and resources',\n },\n newsPolitical: {\n label: 'News/Political',\n description: 'Current events and political content',\n },\n};\n\n/** WorkProject type display info. Used in dropdowns and headers. */\nexport const WORK_PROJECT_TYPES: Record<WorkProjectType, { label: string; description: string }> = {\n Tales: {\n label: 'Tales',\n description: 'Stories and narratives',\n },\n Tunes: {\n label: 'Tunes',\n description: 'Music and audio content',\n },\n Television: {\n label: 'Television',\n description: 'Video and TV content',\n },\n};\n\n// --- Audition Type Display + Board Filter ---\n\n/** Audition type display info. Used on the audition board's type chips/filters and on\n * audition headers. Record-keyed by the canonical AuditionType union, so adding an\n * audition type fails the build here until its label + description exist. */\nexport const AUDITION_TYPES: Record<AuditionType, { label: string; description: string }> = {\n platformAudition: {\n label: 'Platform',\n description: 'Run by TTT admins to gather community feedback.',\n },\n sponsoredAudition: {\n label: 'Sponsored',\n description: 'Backed by funding — votes decide where the money goes.',\n },\n workAudition: {\n label: 'Work',\n description: \"Created by a Work's Guildmates seeking feedback.\",\n },\n};\n\n/** The audition board's \"every type\" filter sentinel — the ONE declaration (it was\n * previously hand-rolled app-locally). It doubles as the chip's own display label. */\nexport const AUDITION_TYPE_FILTER_ALL = 'All';\n\n/** Audition-board type-filter state: one canonical audition type, or the ALL sentinel.\n * Filter state derives this instead of being typed `string`. */\nexport type AuditionTypeFilter = AuditionType | typeof AUDITION_TYPE_FILTER_ALL;\n\n// --- Sort Options ---\n\n/** Sort options shown on the audition feeds, keyed by feed type. */\nexport const AUDITION_SORT_OPTIONS = {\n default: {\n newest: { label: 'Newest First', field: 'createdOn', direction: 'desc' },\n endingSoon: { label: 'Ending Soon', field: 'openTill', direction: 'asc' },\n },\n platformAudition: {\n newest: { label: 'Newest First', field: 'createdOn', direction: 'desc' },\n endingSoon: { label: 'Ending Soon', field: 'openTill', direction: 'asc' },\n },\n sponsoredAudition: {\n newest: { label: 'Newest First', field: 'createdOn', direction: 'desc' },\n endingSoon: { label: 'Ending Soon', field: 'openTill', direction: 'asc' },\n highestPrice: { label: 'Highest Price', field: 'sponsoredAuditionAmountUSD', direction: 'desc' },\n lowestPrice: { label: 'Lowest Price', field: 'sponsoredAuditionAmountUSD', direction: 'asc' },\n },\n workAudition: {\n newest: { label: 'Newest First', field: 'createdOn', direction: 'desc' },\n endingSoon: { label: 'Ending Soon', field: 'openTill', direction: 'asc' },\n highestStakeShares: { label: 'Highest Stakes', field: 'stakeSharesOffered', direction: 'desc' },\n lowestStakeShares: { label: 'Lowest Stakes', field: 'stakeSharesOffered', direction: 'asc' },\n },\n} as const;\n\n/** Every sort key any audition feed offers, DERIVED from AUDITION_SORT_OPTIONS above — a new\n * sort option widens the union automatically, so sort state is never typed `string`. */\nexport type AuditionSortKey = {\n [F in keyof typeof AUDITION_SORT_OPTIONS]: keyof (typeof AUDITION_SORT_OPTIONS)[F];\n}[keyof typeof AUDITION_SORT_OPTIONS];\n\n/** The audition board's initial sort selection. Every feed type offers this key. */\nexport const DEFAULT_AUDITION_SORT: AuditionSortKey = 'newest';\n\n/** Sort options shown on the hallLibrary feed. */\nexport const HALL_LIBRARY_SORT_OPTIONS: Record<\n string,\n { label: string; field: string; direction: 'asc' | 'desc' }\n> = {\n newest: { label: 'Newest First', field: 'createdOn', direction: 'desc' },\n oldest: { label: 'Oldest First', field: 'createdOn', direction: 'asc' },\n most_followed: { label: 'Most Followed', field: 'followerCount', direction: 'desc' },\n};\n\n\n\n"]}
|
|
1
|
+
{"version":3,"file":"options.js","sourceRoot":"","sources":["../../src/constants/options.ts"],"names":[],"mappings":"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","sourcesContent":["// UI option lists shared between frontend and backend admin tooling.\n\nimport type { HallWingType, WorkProjectType } from '../types/content.js';\nimport type { AuditionType } from '../types/commissions.js';\n\n// --- WorkProject Guild Standings ---\n// WorkProject guild-standing IDs, labels, and assignment policy live in ../permissions/.\n// Keep guild-standing picker UIs backed by GUILD_STANDINGS instead of a duplicated option map.\n\n// --- Trade & Craft Options ---\n\n/**\n * Trade professions (20) — role-shaped labels used for guild roles, commission\n * requests, and file-folder permission keys. Display strings are stored/validated\n * directly (they double as the enum values in the callable input schemas that derive\n * from this constant). Kept in curated order; not alphabetized.\n */\nexport const TRADE_PROFESSION_OPTIONS = [\n // Performance\n 'Actor',\n 'Voice Actor',\n 'Singer',\n 'Musician',\n 'Dancer & Choreographer',\n // Story\n 'Writer',\n 'Editor',\n 'Director',\n 'Producer',\n // Camera & visual\n 'Cinematographer',\n 'Photographer',\n 'Animator',\n 'Artist',\n 'Graphic Designer',\n 'VFX Artist',\n 'Costume & Makeup Artist',\n 'Set & Prop Designer',\n // Audio\n 'Composer',\n 'Music Producer',\n 'Sound Designer',\n] as const;\n\n/**\n * Craft-skill discipline tags (23). Tags are Firestore doc IDs in the\n * `craftSkillsByTag/{tag}` index, so the STORED value is a machine-safe kebab-case ID\n * (`CRAFT_SKILL_TAG_OPTIONS`) — this is what the wire schema validates and what path\n * builders write. Human-readable labels (with spaces / ampersands) are mapped over the\n * IDs via `CRAFT_SKILL_TAG_LABELS`; render pickers/badges through that map. Kept in\n * curated discipline order (Performance → Writing → Visual → Film → Audio); not sorted.\n */\nexport const CRAFT_SKILL_TAG_OPTIONS = [\n // Performance\n 'acting',\n 'voice-over',\n 'singing',\n 'rapping',\n 'instrumental-performance',\n 'dance-choreography',\n 'stand-up-sketch-comedy',\n // Writing\n 'writing-storytelling',\n 'songwriting',\n 'poetry-spoken-word',\n // Visual arts\n 'drawing-illustration',\n 'painting',\n 'animation',\n 'graphic-design',\n 'photography',\n // Film & video\n 'cinematography-camera',\n 'video-editing',\n 'visual-effects',\n 'directing',\n 'costume-makeup',\n 'set-prop-design',\n // Audio\n 'music-production',\n 'composing-scoring',\n 'sound-design',\n] as const;\n\n/** The canonical tag-ID type — every tags field/param derives from this, never `string`. */\nexport type CraftSkillTagId = (typeof CRAFT_SKILL_TAG_OPTIONS)[number];\n\n/** The canonical trade-profession ID type. */\nexport type TradeProfessionId = (typeof TRADE_PROFESSION_OPTIONS)[number];\n\n/** TRADE_PROFESSION_OPTIONS as a non-empty tuple for `z.enum(...)` consumers — the ONE\n * cast, here beside the declaration (never re-cast locally in schema files). */\nexport const TRADE_PROFESSION_VALUES = TRADE_PROFESSION_OPTIONS as unknown as [\n TradeProfessionId,\n ...TradeProfessionId[],\n];\n\n/** The same allowlist as a non-empty tuple for `z.enum(...)` consumers — the ONE cast,\n * here beside the declaration (schema files import this, never re-cast locally). */\nexport const CRAFT_SKILL_TAG_VALUES = CRAFT_SKILL_TAG_OPTIONS as unknown as [\n CraftSkillTagId,\n ...CraftSkillTagId[],\n];\n\n/** Human display labels for each craft-skill tag ID. Keyed by the machine-safe ID. */\nexport const CRAFT_SKILL_TAG_LABELS: Record<(typeof CRAFT_SKILL_TAG_OPTIONS)[number], string> = {\n 'acting': 'Acting',\n 'voice-over': 'Voice Over',\n 'singing': 'Singing',\n 'rapping': 'Rapping',\n 'instrumental-performance': 'Instrumental Performance',\n 'dance-choreography': 'Dance & Choreography',\n 'stand-up-sketch-comedy': 'Stand-Up & Sketch Comedy',\n 'writing-storytelling': 'Writing & Storytelling',\n 'songwriting': 'Songwriting',\n 'poetry-spoken-word': 'Poetry & Spoken Word',\n 'drawing-illustration': 'Drawing & Illustration',\n 'painting': 'Painting',\n 'animation': 'Animation',\n 'graphic-design': 'Graphic Design',\n 'photography': 'Photography',\n 'cinematography-camera': 'Cinematography & Camera',\n 'video-editing': 'Video Editing',\n 'visual-effects': 'Visual Effects',\n 'directing': 'Directing',\n 'costume-makeup': 'Costume & Makeup',\n 'set-prop-design': 'Set & Prop Design',\n 'music-production': 'Music Production',\n 'composing-scoring': 'Composing & Scoring',\n 'sound-design': 'Sound Design',\n};\n\n// --- WorkProject-Specific Genres ---\n\n/**\n * Genres shown for each workProject type. Curated final lists (kept in the doc's order,\n * not alphabetized). \"Spooky\" (not \"Horror\") is deliberate for V1: the name carries the\n * all-ages ceiling; \"Horror\" is the natural mature sibling if mature content ever ships.\n */\nexport const WORK_PROJECT_SPECIFIC_GENRES = {\n Tales: [\n 'Adventure',\n 'Comedy',\n 'Drama',\n 'Fantasy',\n 'Fairy Tale & Fable',\n 'Historical',\n 'Mystery',\n 'Romance',\n 'Sci-Fi',\n 'Slice of Life',\n 'Spooky',\n 'Thriller',\n ],\n Tunes: [\n 'Audiobook & Spoken Word',\n 'Blues',\n 'Classical',\n 'Country',\n 'Electronic',\n 'Folk',\n 'Hip Hop & Rap',\n 'Jazz',\n 'Metal',\n 'Podcast',\n 'Pop',\n 'R&B & Soul',\n 'Reggae',\n 'Rock',\n 'Soundtrack & Score',\n ],\n Television: [\n 'Action',\n 'Animation',\n 'Comedy',\n 'Documentary',\n 'Drama',\n 'Fantasy',\n 'Kids & Family',\n 'Music Video',\n 'Mystery',\n 'Reality',\n 'Sci-Fi',\n 'Sketch & Variety',\n 'Spooky',\n 'Talk Show',\n 'Thriller',\n ],\n} as const;\n\n// --- HallLibrary / WorkProject Type Display Maps ---\n\n/** HallLibrary type display info. Used in dropdowns and badges. */\nexport const HALL_WING_TYPES: Record<HallWingType, { label: string; description: string }> = {\n entertainment: {\n label: 'Entertainment',\n description: 'Fun and engaging content',\n },\n educational: {\n label: 'Educational',\n description: 'Learning materials and resources',\n },\n newsPolitical: {\n label: 'News/Political',\n description: 'Current events and political content',\n },\n};\n\n/** WorkProject type display info. Used in dropdowns and headers. */\nexport const WORK_PROJECT_TYPES: Record<WorkProjectType, { label: string; description: string }> = {\n Tales: {\n label: 'Tales',\n description: 'Stories and narratives',\n },\n Tunes: {\n label: 'Tunes',\n description: 'Music and audio content',\n },\n Television: {\n label: 'Television',\n description: 'Video and TV content',\n },\n};\n\n// --- Audition Type Display + Board Filter ---\n\n/** Audition type display info. Used on the audition board's type chips/filters and on\n * audition headers. Record-keyed by the canonical AuditionType union, so adding an\n * audition type fails the build here until its label + description exist. */\nexport const AUDITION_TYPES: Record<AuditionType, { label: string; description: string }> = {\n platformAudition: {\n label: 'Platform',\n description: 'Run by TTT admins to gather community feedback.',\n },\n sponsoredAudition: {\n label: 'Sponsored',\n description: 'Backed by funding — votes decide where the money goes.',\n },\n workAudition: {\n label: 'Work',\n description: \"Created by a Work's Guildmates seeking feedback.\",\n },\n};\n\n/** The audition board's \"every type\" filter sentinel — the ONE declaration (it was\n * previously hand-rolled app-locally). It doubles as the chip's own display label. */\nexport const AUDITION_TYPE_FILTER_ALL = 'All';\n\n/** Audition-board type-filter state: one canonical audition type, or the ALL sentinel.\n * Filter state derives this instead of being typed `string`. */\nexport type AuditionTypeFilter = AuditionType | typeof AUDITION_TYPE_FILTER_ALL;\n\n// --- Sort Options ---\n\n/**\n * The two sort options EVERY audition feed offers — declared ONCE and spread into each feed's\n * option set below (ENG-002). They used to be restated verbatim in all four feed entries, so\n * a label or field change had to be made four times to avoid drift.\n */\nconst AUDITION_SORT_OPTIONS_BASE = {\n newest: { label: 'Newest First', field: 'createdOn', direction: 'desc' },\n endingSoon: { label: 'Ending Soon', field: 'openTill', direction: 'asc' },\n} as const;\n\n/** Sort options shown on the audition feeds, keyed by feed type. `default` serves the board's\n * ALL filter; `platformAudition` is the base pair on purpose — the by-type lookup must be total\n * over AuditionType (see the `AUDITION_SORT_OPTIONS[filter]` call sites). */\nexport const AUDITION_SORT_OPTIONS = {\n default: { ...AUDITION_SORT_OPTIONS_BASE },\n platformAudition: { ...AUDITION_SORT_OPTIONS_BASE },\n sponsoredAudition: {\n ...AUDITION_SORT_OPTIONS_BASE,\n highestPrice: { label: 'Highest Price', field: 'sponsoredAuditionAmountUSD', direction: 'desc' },\n lowestPrice: { label: 'Lowest Price', field: 'sponsoredAuditionAmountUSD', direction: 'asc' },\n },\n workAudition: {\n ...AUDITION_SORT_OPTIONS_BASE,\n highestStakeShares: { label: 'Highest Stakes', field: 'stakeSharesOffered', direction: 'desc' },\n lowestStakeShares: { label: 'Lowest Stakes', field: 'stakeSharesOffered', direction: 'asc' },\n },\n} as const;\n\n/** Every sort key any audition feed offers, DERIVED from AUDITION_SORT_OPTIONS above — a new\n * sort option widens the union automatically, so sort state is never typed `string`. */\nexport type AuditionSortKey = {\n [F in keyof typeof AUDITION_SORT_OPTIONS]: keyof (typeof AUDITION_SORT_OPTIONS)[F];\n}[keyof typeof AUDITION_SORT_OPTIONS];\n\n/** The audition board's initial sort selection. Every feed type offers this key. */\nexport const DEFAULT_AUDITION_SORT: AuditionSortKey = 'newest';\n\n/** Sort options shown on the hallLibrary feed. */\nexport const HALL_LIBRARY_SORT_OPTIONS: Record<\n string,\n { label: string; field: string; direction: 'asc' | 'desc' }\n> = {\n newest: { label: 'Newest First', field: 'createdOn', direction: 'desc' },\n oldest: { label: 'Oldest First', field: 'createdOn', direction: 'asc' },\n most_followed: { label: 'Most Followed', field: 'followerCount', direction: 'desc' },\n};\n\n\n\n"]}
|