@ai-matrx/records 0.54.0 → 0.56.0
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/CHANGELOG.md +78 -0
- package/dist/core/index.cjs +2485 -8
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +154 -9
- package/dist/core/index.d.ts +154 -9
- package/dist/core/index.js +2492 -8
- package/dist/core/index.js.map +1 -1
- package/dist/index.cjs +111 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +250 -4
- package/dist/index.d.ts +250 -4
- package/dist/index.js +101 -4
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +2495 -8
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +767 -10
- package/dist/react/index.d.ts +767 -10
- package/dist/react/index.js +2491 -8
- package/dist/react/index.js.map +1 -1
- package/dist/{field-Ct7_iYEF.d.cts → types-RxnWzAWZ.d.cts} +395 -5
- package/dist/{field-Ct7_iYEF.d.ts → types-RxnWzAWZ.d.ts} +395 -5
- package/dist/use-cases/index.cjs +15 -0
- package/dist/use-cases/index.cjs.map +1 -1
- package/dist/use-cases/index.d.cts +3 -336
- package/dist/use-cases/index.d.ts +3 -336
- package/dist/use-cases/index.js +15 -0
- package/dist/use-cases/index.js.map +1 -1
- package/package.json +7 -7
package/dist/react/index.js
CHANGED
|
@@ -1,5 +1,2175 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
"use client";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __esm = (fn, res) => function __init() {
|
|
6
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
7
|
+
};
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// src/use-cases/alvarado-chen-kitchen-weekly-cooking.ts
|
|
14
|
+
var alvarado_chen_kitchen_weekly_cooking_exports = {};
|
|
15
|
+
__export(alvarado_chen_kitchen_weekly_cooking_exports, {
|
|
16
|
+
default: () => alvarado_chen_kitchen_weekly_cooking_default,
|
|
17
|
+
useCase: () => useCase
|
|
18
|
+
});
|
|
19
|
+
var useCase, alvarado_chen_kitchen_weekly_cooking_default;
|
|
20
|
+
var init_alvarado_chen_kitchen_weekly_cooking = __esm({
|
|
21
|
+
"src/use-cases/alvarado-chen-kitchen-weekly-cooking.ts"() {
|
|
22
|
+
"use strict";
|
|
23
|
+
useCase = {
|
|
24
|
+
id: "alvarado-chen-kitchen-weekly-cooking",
|
|
25
|
+
useCase: "Priya and Daniel Alvarado-Chen cook for a family of five, and they use this to keep the recipes they actually make, the ingredients each one needs, and the weekly shopping list that falls out of the meals they have planned, instead of three notebooks and a text message at the shop.",
|
|
26
|
+
industry: "Household cooking",
|
|
27
|
+
cleanupTag: "use-case:alvarado-chen-kitchen-weekly-cooking",
|
|
28
|
+
business: {
|
|
29
|
+
name: "The Alvarado-Chen Kitchen",
|
|
30
|
+
describes: "A household of five that cooks most nights and shops once a week across three shops.",
|
|
31
|
+
address: {
|
|
32
|
+
line1: "68 Winterbourne Road",
|
|
33
|
+
city: "Oak Park",
|
|
34
|
+
region: "IL",
|
|
35
|
+
postalCode: "60302",
|
|
36
|
+
country: "US"
|
|
37
|
+
},
|
|
38
|
+
phone: "+1 708 555 0126",
|
|
39
|
+
email: "kitchen@alvaradochen.net",
|
|
40
|
+
timezone: "America/Chicago"
|
|
41
|
+
},
|
|
42
|
+
tables: [
|
|
43
|
+
{
|
|
44
|
+
token: "recipes",
|
|
45
|
+
name: "Recipes",
|
|
46
|
+
labelSingular: "Recipe",
|
|
47
|
+
labelPlural: "Recipes",
|
|
48
|
+
type: "entity",
|
|
49
|
+
display: "grid",
|
|
50
|
+
weight: "heavy",
|
|
51
|
+
ordered: false,
|
|
52
|
+
icon: "chef-hat",
|
|
53
|
+
titleField: "title",
|
|
54
|
+
describes: "Every dish the household actually cooks, with who brought it in and how long it takes.",
|
|
55
|
+
fields: [
|
|
56
|
+
{ key: "title", label: "Recipe", parityType: "text", required: true, sensitivity: "internal", contextPolicy: "include" },
|
|
57
|
+
{ key: "category", label: "Course", parityType: "select", choices: ["Breakfast", "Main Course", "Side Dish", "Soup", "Dessert", "Sauce/Condiment"], sensitivity: "internal", contextPolicy: "include" },
|
|
58
|
+
{ key: "cuisine", label: "Cuisine", parityType: "select", choices: ["Mexican", "Chinese", "Italian", "American", "Middle Eastern", "Indian"], sensitivity: "internal", contextPolicy: "include" },
|
|
59
|
+
{ key: "prep_minutes", label: "Prep time", parityType: "integer", unit: "min", sensitivity: "internal", contextPolicy: "include" },
|
|
60
|
+
{ key: "cook_minutes", label: "Cook time", parityType: "integer", unit: "min", sensitivity: "internal", contextPolicy: "include" },
|
|
61
|
+
{ key: "servings", label: "Serves", parityType: "integer", sensitivity: "internal", contextPolicy: "include" },
|
|
62
|
+
{ key: "source", label: "Where it came from", parityType: "text", sensitivity: "internal", contextPolicy: "include" },
|
|
63
|
+
{ key: "contributed_by", label: "Brought in by", parityType: "text", sensitivity: "internal", contextPolicy: "include" },
|
|
64
|
+
{ key: "date_added", label: "Added", parityType: "datetime", format: "date", sensitivity: "internal", contextPolicy: "include" }
|
|
65
|
+
],
|
|
66
|
+
rows: [
|
|
67
|
+
{ key: "recipe-chilaquiles-verdes", values: { "title": "Chilaquiles Verdes", "category": "Breakfast", "cuisine": "Mexican", "prep_minutes": 15, "cook_minutes": 20, "servings": 4, "source": "Grandma Alvarado's recipe box, card #12", "contributed_by": "Rosa Alvarado", "date_added": "2026-01-08" } },
|
|
68
|
+
{ key: "recipe-kung-pao-chicken", values: { "title": "Kung Pao Chicken", "category": "Main Course", "cuisine": "Chinese", "prep_minutes": 20, "cook_minutes": 15, "servings": 4, "source": "Adapted from Fuchsia Dunlop's Land of Fish and Rice", "contributed_by": "Wei Chen", "date_added": "2026-01-15" } },
|
|
69
|
+
{ key: "recipe-slow-braised-short-rib-ragu", values: { "title": "Slow-Braised Short Rib Ragu", "category": "Main Course", "cuisine": "Italian", "prep_minutes": 25, "cook_minutes": 210, "servings": 6, "source": "Sunday dinner tradition, no written source", "contributed_by": "Marco Alvarado", "date_added": "2026-02-02" } },
|
|
70
|
+
{ key: "recipe-mapo-tofu", values: { "title": "Mapo Tofu", "category": "Main Course", "cuisine": "Chinese", "prep_minutes": 10, "cook_minutes": 15, "servings": 3, "source": "Wei's mother, dictated over the phone", "contributed_by": "Wei Chen", "date_added": "2026-02-10" } },
|
|
71
|
+
{ key: "recipe-elote-street-corn-salad", values: { "title": "Elote Street Corn Salad", "category": "Side Dish", "cuisine": "Mexican", "prep_minutes": 15, "cook_minutes": 10, "servings": 6, "source": "Farmers market recipe card", "contributed_by": "Rosa Alvarado", "date_added": "2026-03-01" } },
|
|
72
|
+
{ key: "recipe-pozole-rojo", values: { "title": "Pozole Rojo", "category": "Soup", "cuisine": "Mexican", "prep_minutes": 30, "cook_minutes": 180, "servings": 8, "source": "Family recipe, three generations", "contributed_by": "Rosa Alvarado", "date_added": "2026-03-14" } },
|
|
73
|
+
{ key: "recipe-hot-and-sour-soup", values: { "title": "Hot and Sour Soup", "category": "Soup", "cuisine": "Chinese", "prep_minutes": 15, "cook_minutes": 20, "servings": 4, "source": "Wei Chen's own recipe", "contributed_by": "Wei Chen", "date_added": "2026-03-22" } },
|
|
74
|
+
{ key: "recipe-tres-leches-cake", values: { "title": "Tres Leches Cake", "category": "Dessert", "cuisine": "Mexican", "prep_minutes": 30, "cook_minutes": 35, "servings": 12, "source": "Grandma Alvarado's recipe box, card #4", "contributed_by": "Rosa Alvarado", "date_added": "2026-04-05" } },
|
|
75
|
+
{ key: "recipe-cacio-e-pepe", values: { "title": "Cacio e Pepe", "category": "Main Course", "cuisine": "Italian", "prep_minutes": 5, "cook_minutes": 15, "servings": 2, "source": "Weeknight standby, no written source", "contributed_by": "Marco Alvarado", "date_added": "2026-04-12" } },
|
|
76
|
+
{ key: "recipe-chana-masala", values: { "title": "Chana Masala", "category": "Main Course", "cuisine": "Indian", "prep_minutes": 15, "cook_minutes": 30, "servings": 4, "source": "Learned from neighbor Priya", "contributed_by": "Wei Chen", "date_added": "2026-05-01" } },
|
|
77
|
+
{ key: "recipe-salsa-verde-cruda", values: { "title": "Salsa Verde Cruda", "category": "Sauce/Condiment", "cuisine": "Mexican", "prep_minutes": 10, "cook_minutes": 0, "servings": 8, "source": "Grandma Alvarado's recipe box, card #1", "contributed_by": "Rosa Alvarado", "date_added": "2026-05-10" } },
|
|
78
|
+
{ key: "recipe-shakshuka", values: { "title": "Shakshuka", "category": "Breakfast", "cuisine": "Middle Eastern", "prep_minutes": 10, "cook_minutes": 25, "servings": 4, "source": "Ottolenghi's Jerusalem, adapted", "contributed_by": "Marco Alvarado", "date_added": "2026-05-18" } }
|
|
79
|
+
]
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
token: "ingredients",
|
|
83
|
+
name: "Ingredients",
|
|
84
|
+
labelSingular: "Ingredient",
|
|
85
|
+
labelPlural: "Ingredients",
|
|
86
|
+
type: "detail",
|
|
87
|
+
display: "list",
|
|
88
|
+
weight: "light",
|
|
89
|
+
ordered: true,
|
|
90
|
+
icon: "carrot",
|
|
91
|
+
titleField: "ingredient_name",
|
|
92
|
+
describes: "What goes into each recipe, in the amounts the recipe is written for.",
|
|
93
|
+
fields: [
|
|
94
|
+
{ key: "recipe", label: "Recipe", parityType: "relation", required: true, relationTarget: "recipes", relationMax: 1, sensitivity: "internal", contextPolicy: "include" },
|
|
95
|
+
{ key: "ingredient_name", label: "Ingredient", parityType: "text", required: true, sensitivity: "internal", contextPolicy: "include" },
|
|
96
|
+
{ key: "quantity", label: "Quantity", parityType: "integer", sensitivity: "internal", contextPolicy: "include" },
|
|
97
|
+
{ key: "unit", label: "Unit", parityType: "select", choices: ["cup", "tbsp", "tsp", "oz", "lb", "clove", "whole", "can", "pinch"], sensitivity: "internal", contextPolicy: "include" },
|
|
98
|
+
{ key: "notes", label: "Notes", parityType: "text", sensitivity: "internal", contextPolicy: "include" }
|
|
99
|
+
],
|
|
100
|
+
rows: [
|
|
101
|
+
{ key: "ingredient-corn-tortillas-cut-into-wedges-and-fried", values: { "recipe": "recipe-chilaquiles-verdes", "ingredient_name": "corn tortillas, cut into wedges and fried", "quantity": 12, "unit": "whole", "notes": "day-old tortillas fry crisper" } },
|
|
102
|
+
{ key: "ingredient-tomatillos", values: { "recipe": "recipe-chilaquiles-verdes", "ingredient_name": "tomatillos", "quantity": 1, "unit": "lb", "notes": "husked and rinsed" } },
|
|
103
|
+
{ key: "ingredient-serrano-peppers", values: { "recipe": "recipe-chilaquiles-verdes", "ingredient_name": "serrano peppers", "quantity": 2, "unit": "whole", "notes": "seeds removed for less heat" } },
|
|
104
|
+
{ key: "ingredient-queso-fresco", values: { "recipe": "recipe-chilaquiles-verdes", "ingredient_name": "queso fresco", "quantity": 4, "unit": "oz", "notes": "crumbled for topping" } },
|
|
105
|
+
{ key: "ingredient-chicken-thighs-diced", values: { "recipe": "recipe-kung-pao-chicken", "ingredient_name": "chicken thighs, diced", "quantity": 1.5, "unit": "lb", "notes": "boneless, skinless" } },
|
|
106
|
+
{ key: "ingredient-dried-red-chilies", values: { "recipe": "recipe-kung-pao-chicken", "ingredient_name": "dried red chilies", "quantity": 8, "unit": "whole", "notes": "adjust to taste" } },
|
|
107
|
+
{ key: "ingredient-roasted-peanuts", values: { "recipe": "recipe-kung-pao-chicken", "ingredient_name": "roasted peanuts", "quantity": 0.5, "unit": "cup", "notes": "" } },
|
|
108
|
+
{ key: "ingredient-sichuan-peppercorns", values: { "recipe": "recipe-kung-pao-chicken", "ingredient_name": "Sichuan peppercorns", "quantity": 1, "unit": "tsp", "notes": "toasted and cracked" } },
|
|
109
|
+
{ key: "ingredient-bone-in-short-ribs", values: { "recipe": "recipe-slow-braised-short-rib-ragu", "ingredient_name": "bone-in short ribs", "quantity": 3, "unit": "lb", "notes": "trimmed of excess fat" } },
|
|
110
|
+
{ key: "ingredient-san-marzano-tomatoes", values: { "recipe": "recipe-slow-braised-short-rib-ragu", "ingredient_name": "San Marzano tomatoes", "quantity": 1, "unit": "can", "notes": "28 oz can, crushed by hand" } },
|
|
111
|
+
{ key: "ingredient-red-wine", values: { "recipe": "recipe-slow-braised-short-rib-ragu", "ingredient_name": "red wine", "quantity": 1, "unit": "cup", "notes": "something drinkable" } },
|
|
112
|
+
{ key: "ingredient-soft-tofu-cubed", values: { "recipe": "recipe-mapo-tofu", "ingredient_name": "soft tofu, cubed", "quantity": 14, "unit": "oz", "notes": "one package" } },
|
|
113
|
+
{ key: "ingredient-doubanjiang-fermented-chili-bean-paste", values: { "recipe": "recipe-mapo-tofu", "ingredient_name": "doubanjiang (fermented chili bean paste)", "quantity": 2, "unit": "tbsp", "notes": "Pixian brand preferred" } },
|
|
114
|
+
{ key: "ingredient-ground-pork", values: { "recipe": "recipe-mapo-tofu", "ingredient_name": "ground pork", "quantity": 0.5, "unit": "lb", "notes": "" } },
|
|
115
|
+
{ key: "ingredient-corn-kernels-charred", values: { "recipe": "recipe-elote-street-corn-salad", "ingredient_name": "corn kernels, charred", "quantity": 4, "unit": "cup", "notes": "grilled or pan-charred" } },
|
|
116
|
+
{ key: "ingredient-cotija-cheese", values: { "recipe": "recipe-elote-street-corn-salad", "ingredient_name": "cotija cheese", "quantity": 0.5, "unit": "cup", "notes": "crumbled" } },
|
|
117
|
+
{ key: "ingredient-lime", values: { "recipe": "recipe-elote-street-corn-salad", "ingredient_name": "lime", "quantity": 2, "unit": "whole", "notes": "juiced" } },
|
|
118
|
+
{ key: "ingredient-pork-shoulder", values: { "recipe": "recipe-pozole-rojo", "ingredient_name": "pork shoulder", "quantity": 3, "unit": "lb", "notes": "cut into large chunks" } },
|
|
119
|
+
{ key: "ingredient-hominy", values: { "recipe": "recipe-pozole-rojo", "ingredient_name": "hominy", "quantity": 2, "unit": "can", "notes": "29 oz cans, drained" } },
|
|
120
|
+
{ key: "ingredient-guajillo-chilies", values: { "recipe": "recipe-pozole-rojo", "ingredient_name": "guajillo chilies", "quantity": 6, "unit": "whole", "notes": "stemmed and seeded" } },
|
|
121
|
+
{ key: "ingredient-wood-ear-mushrooms-dried", values: { "recipe": "recipe-hot-and-sour-soup", "ingredient_name": "wood ear mushrooms, dried", "quantity": 0.25, "unit": "cup", "notes": "rehydrated and sliced" } },
|
|
122
|
+
{ key: "ingredient-white-pepper", values: { "recipe": "recipe-hot-and-sour-soup", "ingredient_name": "white pepper", "quantity": 1, "unit": "tsp", "notes": "the 'hot' in hot and sour" } },
|
|
123
|
+
{ key: "ingredient-evaporated-milk", values: { "recipe": "recipe-tres-leches-cake", "ingredient_name": "evaporated milk", "quantity": 1, "unit": "can", "notes": "12 oz can" } },
|
|
124
|
+
{ key: "ingredient-sweetened-condensed-milk", values: { "recipe": "recipe-tres-leches-cake", "ingredient_name": "sweetened condensed milk", "quantity": 1, "unit": "can", "notes": "14 oz can" } },
|
|
125
|
+
{ key: "ingredient-pecorino-romano-grated", values: { "recipe": "recipe-cacio-e-pepe", "ingredient_name": "pecorino romano, grated", "quantity": 1.5, "unit": "cup", "notes": "finely grated, not shredded" } },
|
|
126
|
+
{ key: "ingredient-chickpeas", values: { "recipe": "recipe-chana-masala", "ingredient_name": "chickpeas", "quantity": 2, "unit": "can", "notes": "15 oz cans, drained" } },
|
|
127
|
+
{ key: "ingredient-garam-masala", values: { "recipe": "recipe-chana-masala", "ingredient_name": "garam masala", "quantity": 1, "unit": "tbsp", "notes": "" } },
|
|
128
|
+
{ key: "ingredient-tomatillos-raw", values: { "recipe": "recipe-salsa-verde-cruda", "ingredient_name": "tomatillos, raw", "quantity": 1, "unit": "lb", "notes": "quartered" } },
|
|
129
|
+
{ key: "ingredient-eggs", values: { "recipe": "recipe-shakshuka", "ingredient_name": "eggs", "quantity": 6, "unit": "whole", "notes": "cracked directly into sauce" } },
|
|
130
|
+
{ key: "ingredient-crushed-tomatoes", values: { "recipe": "recipe-shakshuka", "ingredient_name": "crushed tomatoes", "quantity": 1, "unit": "can", "notes": "28 oz can" } }
|
|
131
|
+
]
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
token: "shopping_lists",
|
|
135
|
+
name: "Shopping lists",
|
|
136
|
+
labelSingular: "Shopping list",
|
|
137
|
+
labelPlural: "Shopping lists",
|
|
138
|
+
type: "entity",
|
|
139
|
+
display: "board",
|
|
140
|
+
weight: "heavy",
|
|
141
|
+
ordered: false,
|
|
142
|
+
icon: "shopping-cart",
|
|
143
|
+
titleField: "list_name",
|
|
144
|
+
describes: "One list per shop per week, built from the recipes planned for that week.",
|
|
145
|
+
fields: [
|
|
146
|
+
{ key: "list_name", label: "List", parityType: "text", required: true, sensitivity: "internal", contextPolicy: "include" },
|
|
147
|
+
{ key: "week_of", label: "Week of", parityType: "datetime", format: "date", sensitivity: "internal", contextPolicy: "include" },
|
|
148
|
+
{ key: "store", label: "Shop", parityType: "select", choices: ["Fresh Market Co-op", "Lucky Star Asian Grocery", "Mercado Alvarado", "Costco"], sensitivity: "internal", contextPolicy: "include" },
|
|
149
|
+
{ key: "status", label: "Status", parityType: "select", choices: ["Planning", "Ready to Shop", "Shopping", "Done"], sensitivity: "internal", contextPolicy: "include" }
|
|
150
|
+
],
|
|
151
|
+
rows: [
|
|
152
|
+
{ key: "list-week-of-jun-1-mexican-night-weekday-soup", values: { "list_name": "Week of Jun 1 \u2014 Mexican night + weekday soup", "week_of": "2026-06-01", "store": "Mercado Alvarado", "status": "Done" } },
|
|
153
|
+
{ key: "list-week-of-jun-8-chinese-takeout-at-home", values: { "list_name": "Week of Jun 8 \u2014 Chinese takeout-at-home", "week_of": "2026-06-08", "store": "Lucky Star Asian Grocery", "status": "Done" } },
|
|
154
|
+
{ key: "list-week-of-jun-15-sunday-ragu-easy-weeknights", values: { "list_name": "Week of Jun 15 \u2014 Sunday ragu + easy weeknights", "week_of": "2026-06-15", "store": "Fresh Market Co-op", "status": "Done" } },
|
|
155
|
+
{ key: "list-week-of-jun-22-birthday-cake-week", values: { "list_name": "Week of Jun 22 \u2014 Birthday cake week", "week_of": "2026-06-22", "store": "Costco", "status": "Ready to Shop" } },
|
|
156
|
+
{ key: "list-week-of-jun-29-pozole-for-the-in-laws", values: { "list_name": "Week of Jun 29 \u2014 Pozole for the in-laws", "week_of": "2026-06-29", "store": "Mercado Alvarado", "status": "Planning" } }
|
|
157
|
+
]
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
token: "shopping_list_items",
|
|
161
|
+
name: "List items",
|
|
162
|
+
labelSingular: "List item",
|
|
163
|
+
labelPlural: "List items",
|
|
164
|
+
type: "detail",
|
|
165
|
+
display: "list",
|
|
166
|
+
weight: "light",
|
|
167
|
+
ordered: true,
|
|
168
|
+
icon: "list-checks",
|
|
169
|
+
titleField: "ingredient_name",
|
|
170
|
+
describes: "What is actually on a list, by aisle, and whether it is already in the trolley.",
|
|
171
|
+
fields: [
|
|
172
|
+
{ key: "shopping_list", label: "Shopping list", parityType: "relation", required: true, relationTarget: "shopping_lists", relationMax: 1, sensitivity: "internal", contextPolicy: "include" },
|
|
173
|
+
{ key: "ingredient_name", label: "Ingredient", parityType: "text", required: true, sensitivity: "internal", contextPolicy: "include" },
|
|
174
|
+
{ key: "quantity", label: "Quantity", parityType: "integer", sensitivity: "internal", contextPolicy: "include" },
|
|
175
|
+
{ key: "unit", label: "Unit", parityType: "select", choices: ["cup", "tbsp", "tsp", "oz", "lb", "clove", "whole", "can", "pinch"], sensitivity: "internal", contextPolicy: "include" },
|
|
176
|
+
{ key: "aisle", label: "Aisle", parityType: "text", sensitivity: "internal", contextPolicy: "include" },
|
|
177
|
+
{ key: "checked", label: "In the trolley", parityType: "select", choices: ["Yes", "No"], sensitivity: "internal", contextPolicy: "include" }
|
|
178
|
+
],
|
|
179
|
+
rows: [
|
|
180
|
+
{ key: "item-tomatillos", values: { "shopping_list": "list-week-of-jun-1-mexican-night-weekday-soup", "ingredient_name": "tomatillos", "quantity": 2, "unit": "lb", "aisle": "Produce", "checked": "Yes" } },
|
|
181
|
+
{ key: "item-corn-tortillas", values: { "shopping_list": "list-week-of-jun-1-mexican-night-weekday-soup", "ingredient_name": "corn tortillas", "quantity": 2, "unit": "whole", "aisle": "Bakery", "checked": "Yes" } },
|
|
182
|
+
{ key: "item-queso-fresco", values: { "shopping_list": "list-week-of-jun-1-mexican-night-weekday-soup", "ingredient_name": "queso fresco", "quantity": 8, "unit": "oz", "aisle": "Dairy", "checked": "Yes" } },
|
|
183
|
+
{ key: "item-chicken-thighs", values: { "shopping_list": "list-week-of-jun-8-chinese-takeout-at-home", "ingredient_name": "chicken thighs", "quantity": 1.5, "unit": "lb", "aisle": "Meat", "checked": "Yes" } },
|
|
184
|
+
{ key: "item-dried-red-chilies", values: { "shopping_list": "list-week-of-jun-8-chinese-takeout-at-home", "ingredient_name": "dried red chilies", "quantity": 1, "unit": "oz", "aisle": "International", "checked": "Yes" } },
|
|
185
|
+
{ key: "item-sichuan-peppercorns", values: { "shopping_list": "list-week-of-jun-8-chinese-takeout-at-home", "ingredient_name": "Sichuan peppercorns", "quantity": 1, "unit": "oz", "aisle": "International", "checked": "No" } },
|
|
186
|
+
{ key: "item-bone-in-short-ribs", values: { "shopping_list": "list-week-of-jun-15-sunday-ragu-easy-weeknights", "ingredient_name": "bone-in short ribs", "quantity": 3, "unit": "lb", "aisle": "Meat", "checked": "Yes" } },
|
|
187
|
+
{ key: "item-san-marzano-tomatoes", values: { "shopping_list": "list-week-of-jun-15-sunday-ragu-easy-weeknights", "ingredient_name": "San Marzano tomatoes", "quantity": 2, "unit": "can", "aisle": "Canned Goods", "checked": "Yes" } },
|
|
188
|
+
{ key: "item-pecorino-romano", values: { "shopping_list": "list-week-of-jun-15-sunday-ragu-easy-weeknights", "ingredient_name": "pecorino romano", "quantity": 1, "unit": "lb", "aisle": "Dairy", "checked": "No" } },
|
|
189
|
+
{ key: "item-evaporated-milk", values: { "shopping_list": "list-week-of-jun-22-birthday-cake-week", "ingredient_name": "evaporated milk", "quantity": 2, "unit": "can", "aisle": "Baking", "checked": "No" } },
|
|
190
|
+
{ key: "item-sweetened-condensed-milk", values: { "shopping_list": "list-week-of-jun-22-birthday-cake-week", "ingredient_name": "sweetened condensed milk", "quantity": 2, "unit": "can", "aisle": "Baking", "checked": "No" } },
|
|
191
|
+
{ key: "item-pork-shoulder", values: { "shopping_list": "list-week-of-jun-29-pozole-for-the-in-laws", "ingredient_name": "pork shoulder", "quantity": 3, "unit": "lb", "aisle": "Meat", "checked": "No" } },
|
|
192
|
+
{ key: "item-hominy", values: { "shopping_list": "list-week-of-jun-29-pozole-for-the-in-laws", "ingredient_name": "hominy", "quantity": 4, "unit": "can", "aisle": "Canned Goods", "checked": "No" } },
|
|
193
|
+
{ key: "item-guajillo-chilies", values: { "shopping_list": "list-week-of-jun-29-pozole-for-the-in-laws", "ingredient_name": "guajillo chilies", "quantity": 6, "unit": "oz", "aisle": "International", "checked": "No" } }
|
|
194
|
+
]
|
|
195
|
+
}
|
|
196
|
+
],
|
|
197
|
+
relationships: [
|
|
198
|
+
{
|
|
199
|
+
describes: "An ingredient belongs to the recipe it is part of and means nothing without it.",
|
|
200
|
+
fromTable: "ingredients",
|
|
201
|
+
fromField: "recipe",
|
|
202
|
+
toTable: "recipes",
|
|
203
|
+
flavor: "owned",
|
|
204
|
+
cardinality: "one",
|
|
205
|
+
onDelete: "cascade",
|
|
206
|
+
inverseKey: "ingredients"
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
describes: "A line on the shopping list belongs to the list it is written on.",
|
|
210
|
+
fromTable: "shopping_list_items",
|
|
211
|
+
fromField: "shopping_list",
|
|
212
|
+
toTable: "shopping_lists",
|
|
213
|
+
flavor: "owned",
|
|
214
|
+
cardinality: "one",
|
|
215
|
+
onDelete: "cascade",
|
|
216
|
+
inverseKey: "items"
|
|
217
|
+
}
|
|
218
|
+
],
|
|
219
|
+
form: {
|
|
220
|
+
token: "alvarado_chen_add_a_recipe",
|
|
221
|
+
name: "Add a recipe to the family collection",
|
|
222
|
+
describes: "What anyone in the family fills in when a dish is worth keeping \u2014 including the grandparents, which is why it asks who brought it in.",
|
|
223
|
+
audience: "member",
|
|
224
|
+
table: "recipes",
|
|
225
|
+
fields: [
|
|
226
|
+
{ fieldKey: "title", label: "What is it called?", required: true },
|
|
227
|
+
{ fieldKey: "category", label: "Course", required: true },
|
|
228
|
+
{ fieldKey: "cuisine", label: "Cuisine" },
|
|
229
|
+
{ fieldKey: "prep_minutes", label: "Prep time in minutes", help: "Chopping and mixing \u2014 everything before it goes on the heat." },
|
|
230
|
+
{ fieldKey: "cook_minutes", label: "Cook time in minutes" },
|
|
231
|
+
{ fieldKey: "servings", label: "How many does it serve?", required: true },
|
|
232
|
+
{ fieldKey: "source", label: "Where did it come from?", help: "A book, a website, or a person. We like knowing." },
|
|
233
|
+
{ fieldKey: "contributed_by", label: "Who brought it in?", required: true }
|
|
234
|
+
],
|
|
235
|
+
submitLabel: "Add it to the collection",
|
|
236
|
+
confirmation: "Added. Put the ingredients in next, and it will start showing up on the shopping list when you plan it for a week."
|
|
237
|
+
},
|
|
238
|
+
pipeline: {
|
|
239
|
+
token: "alvarado_chen_weekly_shop",
|
|
240
|
+
name: "The weekly shop",
|
|
241
|
+
describes: "A list's life is four days long and everybody in the house touches it. The stages exist so nobody buys the same bag of rice twice.",
|
|
242
|
+
table: "shopping_lists",
|
|
243
|
+
stageField: "status",
|
|
244
|
+
stages: [
|
|
245
|
+
{ key: "Planning", label: "Planning", describes: "Meals are still being chosen, so the list is still growing. Nobody shops from it yet.", typicalDurationDays: 3 },
|
|
246
|
+
{ key: "Ready to Shop", label: "Ready to shop", describes: "The meals are settled and the list is complete. This is the state it is in when somebody picks up their keys.", typicalDurationDays: 1 },
|
|
247
|
+
{ key: "Shopping", label: "Shopping", describes: "Somebody is in the shop ticking things off. Anything added now is a genuine omission, not a change of plan.", typicalDurationDays: 1 },
|
|
248
|
+
{ key: "Done", label: "Done", describes: "Everything is home. Unticked items roll onto next week rather than being lost." }
|
|
249
|
+
]
|
|
250
|
+
},
|
|
251
|
+
dashboardQuestion: {
|
|
252
|
+
question: "Which of our recipes can we actually cook on a Tuesday?",
|
|
253
|
+
whyItMatters: "Weeknight cooking fails on time, not on ideas. Knowing the average cook time by course is what stops a two-hour braise being planned for a school night, and it is the number that decides what goes on the list.",
|
|
254
|
+
table: "recipes",
|
|
255
|
+
aggregate: "avg",
|
|
256
|
+
of: "cook_minutes",
|
|
257
|
+
groupBy: "category",
|
|
258
|
+
answerUnit: "minutes"
|
|
259
|
+
},
|
|
260
|
+
documentTemplate: {
|
|
261
|
+
token: "alvarado_chen_recipe_card",
|
|
262
|
+
name: "Printable recipe card",
|
|
263
|
+
describes: "What gets printed and stuck to the fridge door, or sent to someone who asked for the recipe after dinner. It keeps the attribution, because half the collection came from somebody's mother.",
|
|
264
|
+
table: "recipes",
|
|
265
|
+
title: "{{recipe_title}} \u2014 serves {{servings}}",
|
|
266
|
+
body: [
|
|
267
|
+
"{{recipe_title}}",
|
|
268
|
+
"",
|
|
269
|
+
"{{course}} \xB7 {{cuisine}} \xB7 serves {{servings}}",
|
|
270
|
+
"Prep {{prep_time}} minutes, cook {{cook_time}} minutes.",
|
|
271
|
+
"",
|
|
272
|
+
"From {{source}}, brought into the family by {{contributed_by}}.",
|
|
273
|
+
"",
|
|
274
|
+
"Ingredients are on the back. If you halve it, do not halve the salt by the same amount \u2014 taste it instead.",
|
|
275
|
+
"",
|
|
276
|
+
"{{household}} \xB7 printed {{today}}"
|
|
277
|
+
].join("\n"),
|
|
278
|
+
mergeFields: [
|
|
279
|
+
{ key: "recipe_title", from: "title", describes: "The dish." },
|
|
280
|
+
{ key: "course", from: "category", describes: "Which part of the meal it is." },
|
|
281
|
+
{ key: "cuisine", from: "cuisine", describes: "Where it comes from." },
|
|
282
|
+
{ key: "servings", from: "servings", describes: "How many it feeds, so it can be scaled." },
|
|
283
|
+
{ key: "prep_time", from: "prep_minutes", describes: "Minutes before it goes on the heat." },
|
|
284
|
+
{ key: "cook_time", from: "cook_minutes", describes: "Minutes on the heat." },
|
|
285
|
+
{ key: "source", from: "source", describes: "The book, site or person it came from." },
|
|
286
|
+
{ key: "contributed_by", from: "contributed_by", describes: "Who brought it into the family." },
|
|
287
|
+
{ key: "household", from: "business", describes: "Whose kitchen this is." },
|
|
288
|
+
{ key: "today", from: "today", describes: "When the card was printed." }
|
|
289
|
+
]
|
|
290
|
+
},
|
|
291
|
+
notificationRule: {
|
|
292
|
+
token: "alvarado_chen_list_is_ready",
|
|
293
|
+
name: "The list is ready to shop",
|
|
294
|
+
describes: "The one message this household would genuinely set up: whoever is going to the shop needs to know the list stopped changing, because the whole failure mode is leaving with a list somebody was still editing.",
|
|
295
|
+
when: {
|
|
296
|
+
table: "shopping_lists",
|
|
297
|
+
event: "stage_entered",
|
|
298
|
+
stage: "Ready to Shop"
|
|
299
|
+
},
|
|
300
|
+
audience: "whoever is doing the shop this week",
|
|
301
|
+
channel: "in_app",
|
|
302
|
+
message: "{{list_name}} for the week of {{week_of}} is finished and ready \u2014 {{store}}. Tick things off as you go so nobody buys them twice."
|
|
303
|
+
},
|
|
304
|
+
provenance: {
|
|
305
|
+
kind: "synthesized",
|
|
306
|
+
authoredBy: "data crew (dataset) + lane REAL-DATA (business identity, relationships, form, pipeline, dashboard question, document, notification rule)",
|
|
307
|
+
authoredOn: "2026-09-21",
|
|
308
|
+
noRealPeople: true
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
alvarado_chen_kitchen_weekly_cooking_default = useCase;
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
// src/use-cases/birchwood-avenue-renovation-budget.ts
|
|
316
|
+
var birchwood_avenue_renovation_budget_exports = {};
|
|
317
|
+
__export(birchwood_avenue_renovation_budget_exports, {
|
|
318
|
+
default: () => birchwood_avenue_renovation_budget_default,
|
|
319
|
+
useCase: () => useCase2
|
|
320
|
+
});
|
|
321
|
+
var useCase2, birchwood_avenue_renovation_budget_default;
|
|
322
|
+
var init_birchwood_avenue_renovation_budget = __esm({
|
|
323
|
+
"src/use-cases/birchwood-avenue-renovation-budget.ts"() {
|
|
324
|
+
"use strict";
|
|
325
|
+
useCase2 = {
|
|
326
|
+
id: "birchwood-avenue-renovation-budget",
|
|
327
|
+
useCase: "Marguerite Oyelowo is renovating a 1920s house one room at a time, and she uses this to hold every contractor quote against the room it is for and every receipt against the budget she set, so that whether the job is over budget has an answer instead of an argument.",
|
|
328
|
+
industry: "Home renovation",
|
|
329
|
+
cleanupTag: "use-case:birchwood-avenue-renovation-budget",
|
|
330
|
+
business: {
|
|
331
|
+
name: "Birchwood Avenue Renovation",
|
|
332
|
+
describes: "A owner-managed whole-house renovation of a 1920s four-bedroom, run room by room over about a year.",
|
|
333
|
+
address: {
|
|
334
|
+
line1: "417 Birchwood Avenue",
|
|
335
|
+
city: "Providence",
|
|
336
|
+
region: "RI",
|
|
337
|
+
postalCode: "02906",
|
|
338
|
+
country: "US"
|
|
339
|
+
},
|
|
340
|
+
phone: "+1 401 555 0188",
|
|
341
|
+
email: "marguerite@birchwoodreno.net",
|
|
342
|
+
timezone: "America/New_York"
|
|
343
|
+
},
|
|
344
|
+
tables: [
|
|
345
|
+
{
|
|
346
|
+
token: "rooms",
|
|
347
|
+
name: "Rooms",
|
|
348
|
+
labelSingular: "Room",
|
|
349
|
+
labelPlural: "Rooms",
|
|
350
|
+
type: "entity",
|
|
351
|
+
display: "board",
|
|
352
|
+
weight: "heavy",
|
|
353
|
+
ordered: true,
|
|
354
|
+
icon: "door-open",
|
|
355
|
+
titleField: "room_name",
|
|
356
|
+
describes: "The house, room by room: what is being done to each one, when, and for how much.",
|
|
357
|
+
fields: [
|
|
358
|
+
{ key: "room_name", label: "Room", parityType: "text", required: true, sensitivity: "internal", contextPolicy: "include" },
|
|
359
|
+
{ key: "project_scope", label: "Scope of work", parityType: "long_text", sensitivity: "internal", contextPolicy: "include" },
|
|
360
|
+
{ key: "target_start", label: "Target start", parityType: "datetime", format: "date", sensitivity: "internal", contextPolicy: "include" },
|
|
361
|
+
{ key: "target_end", label: "Target finish", parityType: "datetime", format: "date", sensitivity: "internal", contextPolicy: "include" },
|
|
362
|
+
{ key: "status", label: "Status", parityType: "select", choices: ["Planning", "Quoting", "In Progress", "Complete", "On Hold"], sensitivity: "internal", contextPolicy: "include" },
|
|
363
|
+
{ key: "budget", label: "Budget", parityType: "currency", unit: "USD", format: "currency", sensitivity: "confidential", contextPolicy: "summarize" }
|
|
364
|
+
],
|
|
365
|
+
rows: [
|
|
366
|
+
{ key: "room-kitchen", values: { "room_name": "Kitchen", "project_scope": "Full gut renovation: new cabinets, quartz counters, relocate island, new appliances.", "target_start": "2026-04-01", "target_end": "2026-06-15", "status": "Complete", "budget": 48e3 } },
|
|
367
|
+
{ key: "room-primary-bathroom", values: { "room_name": "Primary Bathroom", "project_scope": "Replace tub with walk-in shower, new vanity, heated tile floor.", "target_start": "2026-06-20", "target_end": "2026-08-01", "status": "In Progress", "budget": 22500 } },
|
|
368
|
+
{ key: "room-basement", values: { "room_name": "Basement", "project_scope": "Finish unfinished basement into family room and home office, add egress window.", "target_start": "2026-08-10", "target_end": "2026-11-15", "status": "Quoting", "budget": 61e3 } },
|
|
369
|
+
{ key: "room-guest-bathroom", values: { "room_name": "Guest Bathroom", "project_scope": "Cosmetic refresh: new vanity, paint, light fixtures.", "target_start": "2026-09-01", "target_end": "2026-09-20", "status": "Planning", "budget": 6500 } },
|
|
370
|
+
{ key: "room-backyard-deck", values: { "room_name": "Backyard Deck", "project_scope": "Tear off old wood deck, build composite deck with pergola.", "target_start": "2026-05-01", "target_end": "2026-06-01", "status": "Complete", "budget": 18e3 } },
|
|
371
|
+
{ key: "room-garage", values: { "room_name": "Garage", "project_scope": "Epoxy floor, built-in storage, new insulated door.", "target_start": "2026-10-01", "target_end": "2026-10-20", "status": "On Hold", "budget": 9500 } }
|
|
372
|
+
]
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
token: "contractors",
|
|
376
|
+
name: "Contractors",
|
|
377
|
+
labelSingular: "Contractor",
|
|
378
|
+
labelPlural: "Contractors",
|
|
379
|
+
type: "entity",
|
|
380
|
+
display: "list",
|
|
381
|
+
weight: "heavy",
|
|
382
|
+
ordered: false,
|
|
383
|
+
icon: "hard-hat",
|
|
384
|
+
titleField: "company_name",
|
|
385
|
+
describes: "Everyone quoting or working on the job, with the licence and insurance details that matter if something goes wrong.",
|
|
386
|
+
fields: [
|
|
387
|
+
{ key: "company_name", label: "Company", parityType: "text", required: true, sensitivity: "internal", contextPolicy: "include" },
|
|
388
|
+
{ key: "trade", label: "Trade", parityType: "select", choices: ["General Contractor", "Plumbing", "Electrical", "Flooring", "Painting", "HVAC", "Carpentry"], sensitivity: "internal", contextPolicy: "include" },
|
|
389
|
+
{ key: "contact_name", label: "Contact", parityType: "text", sensitivity: "internal", contextPolicy: "include" },
|
|
390
|
+
{ key: "phone", label: "Phone", parityType: "phone", format: "phone", sensitivity: "confidential", contextPolicy: "exclude" },
|
|
391
|
+
{ key: "email", label: "Email", parityType: "email", format: "email", sensitivity: "confidential", contextPolicy: "exclude" },
|
|
392
|
+
{ key: "license_number", label: "Licence number", parityType: "text", sensitivity: "internal", contextPolicy: "include" },
|
|
393
|
+
{ key: "insured", label: "Insured", parityType: "select", choices: ["Yes", "No"], sensitivity: "internal", contextPolicy: "include" }
|
|
394
|
+
],
|
|
395
|
+
rows: [
|
|
396
|
+
{ key: "contractor-ferro-sons-construction", values: { "company_name": "Ferro & Sons Construction", "trade": "General Contractor", "contact_name": "Dominic Ferro", "phone": "555-330-1001", "email": "dominic@northshoremail.com", "license_number": "GC-88213-OH", "insured": "Yes" } },
|
|
397
|
+
{ key: "contractor-redline-plumbing-co", values: { "company_name": "Redline Plumbing Co.", "trade": "Plumbing", "contact_name": "Tanya Iversen", "phone": "555-330-1002", "email": "tanya@northshoremail.com", "license_number": "PL-44029-OH", "insured": "Yes" } },
|
|
398
|
+
{ key: "contractor-voltway-electric", values: { "company_name": "Voltway Electric", "trade": "Electrical", "contact_name": "Emeka Osayande", "phone": "555-330-1003", "email": "emeka@northshoremail.com", "license_number": "EL-90117-OH", "insured": "Yes" } },
|
|
399
|
+
{ key: "contractor-hearthstone-flooring", values: { "company_name": "Hearthstone Flooring", "trade": "Flooring", "contact_name": "Bianca Moretti", "phone": "555-330-1004", "email": "bianca@northshoremail.com", "license_number": "FL-22850-OH", "insured": "Yes" } },
|
|
400
|
+
{ key: "contractor-clearcoat-painting", values: { "company_name": "Clearcoat Painting", "trade": "Painting", "contact_name": "Sam Delacroix", "phone": "555-330-1005", "email": "sam@northshoremail.com", "license_number": "PT-10442-OH", "insured": "No" } },
|
|
401
|
+
{ key: "contractor-northgate-hvac", values: { "company_name": "Northgate HVAC", "trade": "HVAC", "contact_name": "Renata Kowalczyk", "phone": "555-330-1006", "email": "renata@northshoremail.com", "license_number": "HV-77302-OH", "insured": "Yes" } },
|
|
402
|
+
{ key: "contractor-millbrook-carpentry", values: { "company_name": "Millbrook Carpentry", "trade": "Carpentry", "contact_name": "Julius Wexford", "phone": "555-330-1007", "email": "julius@northshoremail.com", "license_number": "CP-55671-OH", "insured": "Yes" } }
|
|
403
|
+
]
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
token: "quotes",
|
|
407
|
+
name: "Quotes",
|
|
408
|
+
labelSingular: "Quote",
|
|
409
|
+
labelPlural: "Quotes",
|
|
410
|
+
type: "ledger",
|
|
411
|
+
display: "list",
|
|
412
|
+
weight: "heavy",
|
|
413
|
+
ordered: false,
|
|
414
|
+
icon: "file-text",
|
|
415
|
+
titleField: "quote_amount",
|
|
416
|
+
describes: "What each trade said each room would cost, and whether that price is still good.",
|
|
417
|
+
fields: [
|
|
418
|
+
{ key: "room", label: "Room", parityType: "relation", required: true, relationTarget: "rooms", relationMax: 1, sensitivity: "internal", contextPolicy: "include" },
|
|
419
|
+
{ key: "contractor", label: "Contractor", parityType: "relation", required: true, relationTarget: "contractors", relationMax: 1, sensitivity: "internal", contextPolicy: "include" },
|
|
420
|
+
{ key: "quote_amount", label: "Quote", parityType: "currency", unit: "USD", format: "currency", required: true, sensitivity: "confidential", contextPolicy: "summarize" },
|
|
421
|
+
{ key: "quote_date", label: "Quoted on", parityType: "datetime", format: "date", sensitivity: "internal", contextPolicy: "include" },
|
|
422
|
+
{ key: "status", label: "Status", parityType: "select", choices: ["Pending", "Accepted", "Rejected", "Expired"], sensitivity: "internal", contextPolicy: "include" },
|
|
423
|
+
{ key: "valid_until", label: "Valid until", parityType: "datetime", format: "date", sensitivity: "internal", contextPolicy: "include" }
|
|
424
|
+
],
|
|
425
|
+
rows: [
|
|
426
|
+
{ key: "quote-46500-0", values: { "room": "room-kitchen", "contractor": "contractor-ferro-sons-construction", "quote_amount": 46500, "quote_date": "2026-02-14", "status": "Accepted", "valid_until": "2026-03-14" } },
|
|
427
|
+
{ key: "quote-3200-0", values: { "room": "room-kitchen", "contractor": "contractor-redline-plumbing-co", "quote_amount": 3200, "quote_date": "2026-02-20", "status": "Accepted", "valid_until": "2026-03-20" } },
|
|
428
|
+
{ key: "quote-2800-0", values: { "room": "room-kitchen", "contractor": "contractor-voltway-electric", "quote_amount": 2800, "quote_date": "2026-02-20", "status": "Accepted", "valid_until": "2026-03-20" } },
|
|
429
|
+
{ key: "quote-21000-0", values: { "room": "room-primary-bathroom", "contractor": "contractor-ferro-sons-construction", "quote_amount": 21e3, "quote_date": "2026-05-10", "status": "Accepted", "valid_until": "2026-06-10" } },
|
|
430
|
+
{ key: "quote-4100-0", values: { "room": "room-primary-bathroom", "contractor": "contractor-redline-plumbing-co", "quote_amount": 4100, "quote_date": "2026-05-11", "status": "Accepted", "valid_until": "2026-06-11" } },
|
|
431
|
+
{ key: "quote-58000-0", values: { "room": "room-basement", "contractor": "contractor-ferro-sons-construction", "quote_amount": 58e3, "quote_date": "2026-07-20", "status": "Pending", "valid_until": "2026-08-20" } },
|
|
432
|
+
{ key: "quote-12500-0", values: { "room": "room-basement", "contractor": "contractor-millbrook-carpentry", "quote_amount": 12500, "quote_date": "2026-07-22", "status": "Pending", "valid_until": "2026-08-22" } },
|
|
433
|
+
{ key: "quote-6800-0", values: { "room": "room-basement", "contractor": "contractor-northgate-hvac", "quote_amount": 6800, "quote_date": "2026-07-25", "status": "Pending", "valid_until": "2026-08-25" } },
|
|
434
|
+
{ key: "quote-1800-0", values: { "room": "room-guest-bathroom", "contractor": "contractor-hearthstone-flooring", "quote_amount": 1800, "quote_date": "2026-07-28", "status": "Pending", "valid_until": "2026-08-28" } },
|
|
435
|
+
{ key: "quote-17200-0", values: { "room": "room-backyard-deck", "contractor": "contractor-millbrook-carpentry", "quote_amount": 17200, "quote_date": "2026-03-05", "status": "Accepted", "valid_until": "2026-04-05" } },
|
|
436
|
+
{ key: "quote-19800-0", values: { "room": "room-backyard-deck", "contractor": "contractor-ferro-sons-construction", "quote_amount": 19800, "quote_date": "2026-03-02", "status": "Rejected", "valid_until": "2026-04-02" } },
|
|
437
|
+
{ key: "quote-2100-0", values: { "room": "room-garage", "contractor": "contractor-clearcoat-painting", "quote_amount": 2100, "quote_date": "2026-01-15", "status": "Expired", "valid_until": "2026-02-15" } }
|
|
438
|
+
]
|
|
439
|
+
},
|
|
440
|
+
{
|
|
441
|
+
token: "purchases",
|
|
442
|
+
name: "Purchases",
|
|
443
|
+
labelSingular: "Purchase",
|
|
444
|
+
labelPlural: "Purchases",
|
|
445
|
+
type: "ledger",
|
|
446
|
+
display: "list",
|
|
447
|
+
weight: "heavy",
|
|
448
|
+
ordered: false,
|
|
449
|
+
icon: "receipt",
|
|
450
|
+
titleField: "item_description",
|
|
451
|
+
describes: "Every pound spent against the project, so the budget is a fact rather than a feeling.",
|
|
452
|
+
fields: [
|
|
453
|
+
{ key: "room", label: "Room", parityType: "relation", required: true, relationTarget: "rooms", relationMax: 1, sensitivity: "internal", contextPolicy: "include" },
|
|
454
|
+
{ key: "item_description", label: "What was bought", parityType: "text", required: true, sensitivity: "internal", contextPolicy: "include" },
|
|
455
|
+
{ key: "vendor", label: "Vendor", parityType: "text", sensitivity: "internal", contextPolicy: "include" },
|
|
456
|
+
{ key: "purchase_date", label: "Bought on", parityType: "datetime", format: "date", sensitivity: "internal", contextPolicy: "include" },
|
|
457
|
+
{ key: "amount", label: "Amount", parityType: "currency", unit: "USD", format: "currency", sensitivity: "confidential", contextPolicy: "summarize" },
|
|
458
|
+
{ key: "category", label: "Category", parityType: "select", choices: ["Materials", "Fixtures", "Labor", "Permits", "Appliances", "Design/Design Fees"], sensitivity: "internal", contextPolicy: "include" },
|
|
459
|
+
{ key: "receipt_number", label: "Receipt", parityType: "text", sensitivity: "internal", contextPolicy: "include" }
|
|
460
|
+
],
|
|
461
|
+
rows: [
|
|
462
|
+
{ key: "purchase-custom-shaker-cabinets-painted-alabaster", values: { "room": "room-kitchen", "item_description": "Custom shaker cabinets, painted 'Alabaster'", "vendor": "Millbrook Cabinetry Supply", "purchase_date": "2026-04-05", "amount": 14200, "category": "Materials", "receipt_number": "RCT-10021" } },
|
|
463
|
+
{ key: "purchase-quartz-countertop-calacatta-gold-42-sq-ft", values: { "room": "room-kitchen", "item_description": "Quartz countertop, 'Calacatta Gold' 42 sq ft", "vendor": "Stone Depot", "purchase_date": "2026-04-18", "amount": 5900, "category": "Materials", "receipt_number": "RCT-10022" } },
|
|
464
|
+
{ key: "purchase-range-refrigerator-dishwasher-package", values: { "room": "room-kitchen", "item_description": "Range, refrigerator, dishwasher package", "vendor": "Coldstream Appliance Center", "purchase_date": "2026-04-22", "amount": 8700, "category": "Appliances", "receipt_number": "RCT-10023" } },
|
|
465
|
+
{ key: "purchase-building-permit-kitchen-remodel", values: { "room": "room-kitchen", "item_description": "Building permit \u2014 kitchen remodel", "vendor": "City of Fairmont Permits Office", "purchase_date": "2026-03-28", "amount": 450, "category": "Permits", "receipt_number": "RCT-10024" } },
|
|
466
|
+
{ key: "purchase-ferro-sons-final-labor-invoice", values: { "room": "room-kitchen", "item_description": "Ferro & Sons \u2014 final labor invoice", "vendor": "Ferro & Sons Construction", "purchase_date": "2026-06-15", "amount": 15800, "category": "Labor", "receipt_number": "RCT-10025" } },
|
|
467
|
+
{ key: "purchase-walk-in-shower-kit-with-frameless-glass", values: { "room": "room-primary-bathroom", "item_description": "Walk-in shower kit with frameless glass", "vendor": "Stone Depot", "purchase_date": "2026-06-25", "amount": 4300, "category": "Fixtures", "receipt_number": "RCT-10026" } },
|
|
468
|
+
{ key: "purchase-heated-floor-mat-system-45-sq-ft", values: { "room": "room-primary-bathroom", "item_description": "Heated floor mat system, 45 sq ft", "vendor": "WarmFloor Direct", "purchase_date": "2026-06-28", "amount": 1650, "category": "Materials", "receipt_number": "RCT-10027" } },
|
|
469
|
+
{ key: "purchase-floating-double-vanity-60-inch", values: { "room": "room-primary-bathroom", "item_description": "Floating double vanity, 60 inch", "vendor": "Millbrook Cabinetry Supply", "purchase_date": "2026-07-02", "amount": 2200, "category": "Fixtures", "receipt_number": "RCT-10028" } },
|
|
470
|
+
{ key: "purchase-composite-decking-600-sq-ft-weathered-teak", values: { "room": "room-backyard-deck", "item_description": "Composite decking, 600 sq ft, 'Weathered Teak'", "vendor": "Deckmaster Supply", "purchase_date": "2026-05-05", "amount": 8900, "category": "Materials", "receipt_number": "RCT-10029" } },
|
|
471
|
+
{ key: "purchase-cedar-pergola-kit-12x14", values: { "room": "room-backyard-deck", "item_description": "Cedar pergola kit, 12x14", "vendor": "Deckmaster Supply", "purchase_date": "2026-05-08", "amount": 3200, "category": "Materials", "receipt_number": "RCT-10030" } },
|
|
472
|
+
{ key: "purchase-millbrook-carpentry-labor-and-install", values: { "room": "room-backyard-deck", "item_description": "Millbrook Carpentry \u2014 labor and install", "vendor": "Millbrook Carpentry", "purchase_date": "2026-06-01", "amount": 4900, "category": "Labor", "receipt_number": "RCT-10031" } },
|
|
473
|
+
{ key: "purchase-design-consultation-fixture-layout", values: { "room": "room-guest-bathroom", "item_description": "Design consultation \u2014 fixture layout", "vendor": "Bianca Moretti Interiors", "purchase_date": "2026-07-30", "amount": 350, "category": "Design/Design Fees", "receipt_number": "RCT-10032" } }
|
|
474
|
+
]
|
|
475
|
+
}
|
|
476
|
+
],
|
|
477
|
+
relationships: [
|
|
478
|
+
{
|
|
479
|
+
describes: "A quote is for exactly one room, and it is meaningless once that room is out of scope.",
|
|
480
|
+
fromTable: "quotes",
|
|
481
|
+
fromField: "room",
|
|
482
|
+
toTable: "rooms",
|
|
483
|
+
flavor: "owned",
|
|
484
|
+
cardinality: "one",
|
|
485
|
+
onDelete: "cascade",
|
|
486
|
+
inverseKey: "quotes"
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
describes: "A quote comes from one contractor, who goes on existing after the quote is rejected.",
|
|
490
|
+
fromTable: "quotes",
|
|
491
|
+
fromField: "contractor",
|
|
492
|
+
toTable: "contractors",
|
|
493
|
+
flavor: "referenced",
|
|
494
|
+
cardinality: "one",
|
|
495
|
+
onDelete: "restrict",
|
|
496
|
+
inverseKey: "quotes_given"
|
|
497
|
+
},
|
|
498
|
+
{
|
|
499
|
+
describes: "A purchase is charged against the room it was bought for, which is how the budget stays honest.",
|
|
500
|
+
fromTable: "purchases",
|
|
501
|
+
fromField: "room",
|
|
502
|
+
toTable: "rooms",
|
|
503
|
+
flavor: "owned",
|
|
504
|
+
cardinality: "one",
|
|
505
|
+
onDelete: "cascade",
|
|
506
|
+
inverseKey: "purchases"
|
|
507
|
+
}
|
|
508
|
+
],
|
|
509
|
+
form: {
|
|
510
|
+
token: "birchwood_contractor_details",
|
|
511
|
+
name: "Contractor details and insurance",
|
|
512
|
+
describes: "What a trade fills in before they are allowed to quote. It asks for the licence number and the insurance because those are the two things nobody can produce after something goes wrong.",
|
|
513
|
+
audience: "public",
|
|
514
|
+
table: "contractors",
|
|
515
|
+
fields: [
|
|
516
|
+
{ fieldKey: "company_name", label: "Company name", required: true },
|
|
517
|
+
{ fieldKey: "trade", label: "Trade", required: true },
|
|
518
|
+
{ fieldKey: "contact_name", label: "Who should I ask for?", required: true },
|
|
519
|
+
{ fieldKey: "phone", label: "Best number", required: true },
|
|
520
|
+
{ fieldKey: "email", label: "Email", required: true },
|
|
521
|
+
{ fieldKey: "license_number", label: "Licence number", required: true, help: "I check this with the state board before accepting a quote." },
|
|
522
|
+
{ fieldKey: "insured", label: "Do you carry liability insurance?", required: true, help: "I will ask for the certificate before work starts." }
|
|
523
|
+
],
|
|
524
|
+
submitLabel: "Send my details",
|
|
525
|
+
confirmation: "Thank you. I will check the licence and come back to you about which rooms I would like quoted, usually within a few days."
|
|
526
|
+
},
|
|
527
|
+
pipeline: {
|
|
528
|
+
token: "birchwood_room_progress",
|
|
529
|
+
name: "Room by room",
|
|
530
|
+
describes: "Where each room stands. The board exists because a whole-house renovation is really five small projects at different stages, and the only way to stay sane is to look at them side by side.",
|
|
531
|
+
table: "rooms",
|
|
532
|
+
stageField: "status",
|
|
533
|
+
stages: [
|
|
534
|
+
{ key: "Planning", label: "Planning", describes: "Scope is still being decided. Nothing has been priced, so the budget figure is a guess.", typicalDurationDays: 21 },
|
|
535
|
+
{ key: "Quoting", label: "Quoting", describes: "Trades are pricing it. Leaves when a quote is accepted \u2014 or when every quote comes back over budget and the scope goes back to Planning.", typicalDurationDays: 21 },
|
|
536
|
+
{ key: "In Progress", label: "In progress", describes: "Work has started and receipts are landing against this room. This is where the budget is actually won or lost.", typicalDurationDays: 45 },
|
|
537
|
+
{ key: "On Hold", label: "On hold", describes: "Stopped for money, a permit or a lead time. Named honestly so it is not mistaken for progress.", typicalDurationDays: 30 },
|
|
538
|
+
{ key: "Complete", label: "Complete", describes: "Finished, paid and signed off. The room's spend is final and can be compared against what was budgeted." }
|
|
539
|
+
]
|
|
540
|
+
},
|
|
541
|
+
dashboardQuestion: {
|
|
542
|
+
question: "What have I actually spent on each room so far?",
|
|
543
|
+
whyItMatters: "The budget was set room by room, so the only useful comparison is room by room. This is the number that decides whether the next room starts on schedule or waits, and it is the one thing a spreadsheet stops being trusted for once there are more than about thirty receipts.",
|
|
544
|
+
table: "purchases",
|
|
545
|
+
aggregate: "sum",
|
|
546
|
+
of: "amount",
|
|
547
|
+
groupBy: "room",
|
|
548
|
+
answerUnit: "USD"
|
|
549
|
+
},
|
|
550
|
+
documentTemplate: {
|
|
551
|
+
token: "birchwood_quote_acceptance",
|
|
552
|
+
name: "Quote acceptance",
|
|
553
|
+
describes: "Sent to a contractor when their price is accepted. It restates the number, the room and the date the quote was given, because a renovation dispute is almost always about which version of the price was agreed.",
|
|
554
|
+
table: "quotes",
|
|
555
|
+
title: "Accepting your quote of {{amount}}",
|
|
556
|
+
body: [
|
|
557
|
+
"Thank you for quoting.",
|
|
558
|
+
"",
|
|
559
|
+
"I am accepting your price of {{amount}}, quoted on {{quoted_on}} and valid until {{valid_until}}, for the work we discussed.",
|
|
560
|
+
"",
|
|
561
|
+
"Before anything starts I will need a copy of your certificate of insurance. Materials I have bought myself are already on site; anything else is yours to supply and appears on your invoice, not on my receipts.",
|
|
562
|
+
"",
|
|
563
|
+
"If the scope changes once the wall is open \u2014 and on a house this age it usually does \u2014 please price the change and send it to me before carrying it out. I would rather approve a second number than argue about a bigger one later.",
|
|
564
|
+
"",
|
|
565
|
+
"{{project}}",
|
|
566
|
+
"{{project_phone}}",
|
|
567
|
+
"{{today}}"
|
|
568
|
+
].join("\n"),
|
|
569
|
+
mergeFields: [
|
|
570
|
+
{ key: "amount", from: "quote_amount", describes: "The accepted price, restated so there is one version of it." },
|
|
571
|
+
{ key: "quoted_on", from: "quote_date", describes: "Which quote this is, when a trade has given several." },
|
|
572
|
+
{ key: "valid_until", from: "valid_until", describes: "The date the price was good until." },
|
|
573
|
+
{ key: "project", from: "business", describes: "The project name." },
|
|
574
|
+
{ key: "project_phone", from: "business", describes: "The number to call back on." },
|
|
575
|
+
{ key: "today", from: "today", describes: "The date of acceptance." }
|
|
576
|
+
]
|
|
577
|
+
},
|
|
578
|
+
notificationRule: {
|
|
579
|
+
token: "birchwood_quote_expiring",
|
|
580
|
+
name: "A quote is about to expire",
|
|
581
|
+
describes: "Quotes are good for thirty days and a renovation moves slower than that, so the default outcome is re-pricing everything at a worse number. A week's warning is what prevents it, and it is the first thing any homeowner would automate.",
|
|
582
|
+
when: {
|
|
583
|
+
table: "quotes",
|
|
584
|
+
event: "due",
|
|
585
|
+
field: "valid_until",
|
|
586
|
+
daysBefore: 7
|
|
587
|
+
},
|
|
588
|
+
audience: "the homeowner",
|
|
589
|
+
channel: "email",
|
|
590
|
+
message: "The quote of {{quote_amount}} expires on {{valid_until}} \u2014 about a week from now. Accept it, or ask for it to be held, before it has to be re-priced."
|
|
591
|
+
},
|
|
592
|
+
provenance: {
|
|
593
|
+
kind: "synthesized",
|
|
594
|
+
authoredBy: "data crew (dataset) + lane REAL-DATA (business identity, relationships, form, pipeline, dashboard question, document, notification rule)",
|
|
595
|
+
authoredOn: "2026-09-21",
|
|
596
|
+
noRealPeople: true
|
|
597
|
+
}
|
|
598
|
+
};
|
|
599
|
+
birchwood_avenue_renovation_budget_default = useCase2;
|
|
600
|
+
}
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
// src/use-cases/harbor-dental-new-patient-intake.ts
|
|
604
|
+
var harbor_dental_new_patient_intake_exports = {};
|
|
605
|
+
__export(harbor_dental_new_patient_intake_exports, {
|
|
606
|
+
default: () => harbor_dental_new_patient_intake_default,
|
|
607
|
+
useCase: () => useCase3
|
|
608
|
+
});
|
|
609
|
+
var useCase3, harbor_dental_new_patient_intake_default;
|
|
610
|
+
var init_harbor_dental_new_patient_intake = __esm({
|
|
611
|
+
"src/use-cases/harbor-dental-new-patient-intake.ts"() {
|
|
612
|
+
"use strict";
|
|
613
|
+
useCase3 = {
|
|
614
|
+
id: "harbor-dental-new-patient-intake",
|
|
615
|
+
useCase: "Renata Okonkwo runs the front desk at Harbor Dental Group, a six-chair family dental practice, and she uses this to take a new patient from the first phone call through forms, insurance verification and a booked first visit without anything falling between the cracks.",
|
|
616
|
+
industry: "Dentistry",
|
|
617
|
+
cleanupTag: "use-case:harbor-dental-new-patient-intake",
|
|
618
|
+
business: {
|
|
619
|
+
name: "Harbor Dental Group",
|
|
620
|
+
legalName: "Harbor Dental Group, PLLC",
|
|
621
|
+
describes: "A six-chair family dental practice doing general dentistry, hygiene and same-day crowns.",
|
|
622
|
+
address: {
|
|
623
|
+
line1: "1840 Waterfront Parkway",
|
|
624
|
+
line2: "Suite 210",
|
|
625
|
+
city: "Bellingham",
|
|
626
|
+
region: "WA",
|
|
627
|
+
postalCode: "98225",
|
|
628
|
+
country: "US"
|
|
629
|
+
},
|
|
630
|
+
phone: "+1 360 555 0142",
|
|
631
|
+
website: "https://harbordentalgroup.com",
|
|
632
|
+
email: "frontdesk@harbordentalgroup.com",
|
|
633
|
+
timezone: "America/Los_Angeles"
|
|
634
|
+
},
|
|
635
|
+
tables: [
|
|
636
|
+
{
|
|
637
|
+
token: "patient",
|
|
638
|
+
name: "Patients",
|
|
639
|
+
labelSingular: "Patient",
|
|
640
|
+
labelPlural: "Patients",
|
|
641
|
+
type: "entity",
|
|
642
|
+
display: "list",
|
|
643
|
+
weight: "heavy",
|
|
644
|
+
ordered: false,
|
|
645
|
+
icon: "user-round",
|
|
646
|
+
titleField: "full_name",
|
|
647
|
+
describes: "Everyone the practice treats, from the first enquiry through to an active chart.",
|
|
648
|
+
fields: [
|
|
649
|
+
{
|
|
650
|
+
key: "full_name",
|
|
651
|
+
label: "Patient name",
|
|
652
|
+
parityType: "text",
|
|
653
|
+
required: true,
|
|
654
|
+
sensitivity: "confidential",
|
|
655
|
+
contextPolicy: "summarize"
|
|
656
|
+
},
|
|
657
|
+
{
|
|
658
|
+
key: "chart_number",
|
|
659
|
+
label: "Chart number",
|
|
660
|
+
parityType: "text",
|
|
661
|
+
required: true,
|
|
662
|
+
sensitivity: "internal",
|
|
663
|
+
contextPolicy: "include",
|
|
664
|
+
help: "Assigned when the chart is opened. Printed on every claim and referral."
|
|
665
|
+
},
|
|
666
|
+
{
|
|
667
|
+
key: "date_of_birth",
|
|
668
|
+
label: "Date of birth",
|
|
669
|
+
parityType: "datetime",
|
|
670
|
+
format: "date",
|
|
671
|
+
sensitivity: "confidential",
|
|
672
|
+
contextPolicy: "exclude",
|
|
673
|
+
help: "Carriers verify eligibility on name plus date of birth, so it has to be exact."
|
|
674
|
+
},
|
|
675
|
+
{
|
|
676
|
+
key: "phone",
|
|
677
|
+
label: "Mobile phone",
|
|
678
|
+
parityType: "phone",
|
|
679
|
+
format: "phone",
|
|
680
|
+
sensitivity: "confidential",
|
|
681
|
+
contextPolicy: "exclude"
|
|
682
|
+
},
|
|
683
|
+
{
|
|
684
|
+
key: "email",
|
|
685
|
+
label: "Email",
|
|
686
|
+
parityType: "email",
|
|
687
|
+
format: "email",
|
|
688
|
+
sensitivity: "confidential",
|
|
689
|
+
contextPolicy: "exclude"
|
|
690
|
+
},
|
|
691
|
+
{
|
|
692
|
+
key: "street",
|
|
693
|
+
label: "Street address",
|
|
694
|
+
parityType: "text",
|
|
695
|
+
sensitivity: "confidential",
|
|
696
|
+
contextPolicy: "exclude"
|
|
697
|
+
},
|
|
698
|
+
{
|
|
699
|
+
key: "city",
|
|
700
|
+
label: "City",
|
|
701
|
+
parityType: "text",
|
|
702
|
+
sensitivity: "internal",
|
|
703
|
+
contextPolicy: "include"
|
|
704
|
+
},
|
|
705
|
+
{
|
|
706
|
+
key: "region",
|
|
707
|
+
label: "State",
|
|
708
|
+
parityType: "text",
|
|
709
|
+
sensitivity: "internal",
|
|
710
|
+
contextPolicy: "include"
|
|
711
|
+
},
|
|
712
|
+
{
|
|
713
|
+
key: "postal_code",
|
|
714
|
+
label: "ZIP",
|
|
715
|
+
parityType: "text",
|
|
716
|
+
sensitivity: "internal",
|
|
717
|
+
contextPolicy: "include"
|
|
718
|
+
},
|
|
719
|
+
{
|
|
720
|
+
key: "intake_stage",
|
|
721
|
+
label: "Intake stage",
|
|
722
|
+
parityType: "select",
|
|
723
|
+
required: true,
|
|
724
|
+
sensitivity: "internal",
|
|
725
|
+
contextPolicy: "include",
|
|
726
|
+
choices: [
|
|
727
|
+
"Enquiry",
|
|
728
|
+
"Forms sent",
|
|
729
|
+
"Forms received",
|
|
730
|
+
"Insurance verified",
|
|
731
|
+
"First visit booked",
|
|
732
|
+
"Active patient"
|
|
733
|
+
],
|
|
734
|
+
help: "Where this person is between the first call and a chart the hygienist can work from."
|
|
735
|
+
},
|
|
736
|
+
{
|
|
737
|
+
key: "insurance_carrier",
|
|
738
|
+
label: "Insurance carrier",
|
|
739
|
+
parityType: "select",
|
|
740
|
+
sensitivity: "confidential",
|
|
741
|
+
contextPolicy: "summarize",
|
|
742
|
+
choices: ["Delta Dental", "Cigna Dental", "MetLife", "Guardian", "Aetna", "Self-pay"]
|
|
743
|
+
},
|
|
744
|
+
{
|
|
745
|
+
key: "member_id",
|
|
746
|
+
label: "Member ID",
|
|
747
|
+
parityType: "text",
|
|
748
|
+
sensitivity: "restricted",
|
|
749
|
+
contextPolicy: "exclude",
|
|
750
|
+
help: "Never leaves the practice. Needed to verify eligibility before the first visit."
|
|
751
|
+
},
|
|
752
|
+
{
|
|
753
|
+
key: "primary_dentist",
|
|
754
|
+
label: "Primary dentist",
|
|
755
|
+
parityType: "select",
|
|
756
|
+
sensitivity: "internal",
|
|
757
|
+
contextPolicy: "include",
|
|
758
|
+
choices: ["Dr. Alina Reyes", "Dr. Marcus Webb"]
|
|
759
|
+
},
|
|
760
|
+
{
|
|
761
|
+
key: "allergies",
|
|
762
|
+
label: "Known allergies",
|
|
763
|
+
parityType: "multi_select",
|
|
764
|
+
multi: true,
|
|
765
|
+
sensitivity: "confidential",
|
|
766
|
+
contextPolicy: "summarize",
|
|
767
|
+
choices: [
|
|
768
|
+
"Penicillin",
|
|
769
|
+
"Latex",
|
|
770
|
+
"Codeine",
|
|
771
|
+
"Sulfa drugs",
|
|
772
|
+
"Local anaesthetic",
|
|
773
|
+
"None reported"
|
|
774
|
+
],
|
|
775
|
+
help: "Read out loud at chairside before any injection."
|
|
776
|
+
},
|
|
777
|
+
{
|
|
778
|
+
key: "balance_due",
|
|
779
|
+
label: "Balance due",
|
|
780
|
+
parityType: "currency",
|
|
781
|
+
unit: "USD",
|
|
782
|
+
format: "currency",
|
|
783
|
+
sensitivity: "confidential",
|
|
784
|
+
contextPolicy: "summarize"
|
|
785
|
+
},
|
|
786
|
+
{
|
|
787
|
+
key: "referred_by",
|
|
788
|
+
label: "How they found us",
|
|
789
|
+
parityType: "select",
|
|
790
|
+
sensitivity: "internal",
|
|
791
|
+
contextPolicy: "include",
|
|
792
|
+
choices: [
|
|
793
|
+
"Existing patient referral",
|
|
794
|
+
"Insurance directory",
|
|
795
|
+
"Web search",
|
|
796
|
+
"Walk-in",
|
|
797
|
+
"Employer benefits fair"
|
|
798
|
+
]
|
|
799
|
+
},
|
|
800
|
+
{
|
|
801
|
+
key: "front_desk_notes",
|
|
802
|
+
label: "Front desk notes",
|
|
803
|
+
parityType: "long_text",
|
|
804
|
+
sensitivity: "confidential",
|
|
805
|
+
contextPolicy: "on_request"
|
|
806
|
+
}
|
|
807
|
+
],
|
|
808
|
+
rows: [
|
|
809
|
+
{
|
|
810
|
+
key: "patient-rivera-marisol",
|
|
811
|
+
values: {
|
|
812
|
+
full_name: "Marisol Rivera",
|
|
813
|
+
chart_number: "HD-10428",
|
|
814
|
+
date_of_birth: "1988-03-17",
|
|
815
|
+
phone: "+1 360 555 0184",
|
|
816
|
+
email: "m.rivera@northshoremail.com",
|
|
817
|
+
street: "4417 Chuckanut Ridge Road",
|
|
818
|
+
city: "Bellingham",
|
|
819
|
+
region: "WA",
|
|
820
|
+
postal_code: "98229",
|
|
821
|
+
intake_stage: "Active patient",
|
|
822
|
+
insurance_carrier: "Delta Dental",
|
|
823
|
+
member_id: "DD-884201773",
|
|
824
|
+
primary_dentist: "Dr. Alina Reyes",
|
|
825
|
+
allergies: ["Penicillin"],
|
|
826
|
+
balance_due: 0,
|
|
827
|
+
referred_by: "Existing patient referral",
|
|
828
|
+
front_desk_notes: "Prefers early morning. Two children also seen here."
|
|
829
|
+
}
|
|
830
|
+
},
|
|
831
|
+
{
|
|
832
|
+
key: "patient-oyelaran-tunde",
|
|
833
|
+
values: {
|
|
834
|
+
full_name: "Tunde Oyelaran",
|
|
835
|
+
chart_number: "HD-10431",
|
|
836
|
+
date_of_birth: "1975-11-02",
|
|
837
|
+
phone: "+1 360 555 0219",
|
|
838
|
+
email: "toyelaran@baysidedesignco.com",
|
|
839
|
+
street: "902 Eldridge Avenue",
|
|
840
|
+
city: "Bellingham",
|
|
841
|
+
region: "WA",
|
|
842
|
+
postal_code: "98225",
|
|
843
|
+
intake_stage: "Active patient",
|
|
844
|
+
insurance_carrier: "Cigna Dental",
|
|
845
|
+
member_id: "CG-4471209",
|
|
846
|
+
primary_dentist: "Dr. Marcus Webb",
|
|
847
|
+
allergies: ["None reported"],
|
|
848
|
+
balance_due: 142.5,
|
|
849
|
+
referred_by: "Insurance directory",
|
|
850
|
+
front_desk_notes: "Travels for work; wants visits batched into one afternoon."
|
|
851
|
+
}
|
|
852
|
+
},
|
|
853
|
+
{
|
|
854
|
+
key: "patient-halvorsen-britt",
|
|
855
|
+
values: {
|
|
856
|
+
full_name: "Britt Halvorsen",
|
|
857
|
+
chart_number: "HD-10455",
|
|
858
|
+
date_of_birth: "1992-07-26",
|
|
859
|
+
phone: "+1 360 555 0177",
|
|
860
|
+
email: "britt.halvorsen@cascadiaoutfitters.com",
|
|
861
|
+
street: "215 Harris Avenue",
|
|
862
|
+
city: "Bellingham",
|
|
863
|
+
region: "WA",
|
|
864
|
+
postal_code: "98225",
|
|
865
|
+
intake_stage: "First visit booked",
|
|
866
|
+
insurance_carrier: "MetLife",
|
|
867
|
+
member_id: "ML-63902118",
|
|
868
|
+
primary_dentist: "Dr. Alina Reyes",
|
|
869
|
+
allergies: ["Latex"],
|
|
870
|
+
balance_due: 0,
|
|
871
|
+
referred_by: "Web search",
|
|
872
|
+
front_desk_notes: "Latex allergy flagged to the back office; nitrile only."
|
|
873
|
+
}
|
|
874
|
+
},
|
|
875
|
+
{
|
|
876
|
+
key: "patient-nakamura-kenji",
|
|
877
|
+
values: {
|
|
878
|
+
full_name: "Kenji Nakamura",
|
|
879
|
+
chart_number: "HD-10460",
|
|
880
|
+
date_of_birth: "1964-01-09",
|
|
881
|
+
phone: "+1 360 555 0263",
|
|
882
|
+
email: "k.nakamura@harborviewcpa.com",
|
|
883
|
+
street: "1130 Yew Street",
|
|
884
|
+
city: "Bellingham",
|
|
885
|
+
region: "WA",
|
|
886
|
+
postal_code: "98229",
|
|
887
|
+
intake_stage: "Insurance verified",
|
|
888
|
+
insurance_carrier: "Guardian",
|
|
889
|
+
member_id: "GD-20117744",
|
|
890
|
+
primary_dentist: "Dr. Marcus Webb",
|
|
891
|
+
allergies: ["Codeine"],
|
|
892
|
+
balance_due: 0,
|
|
893
|
+
referred_by: "Employer benefits fair",
|
|
894
|
+
front_desk_notes: "Eligibility confirmed through December. Waiting on his schedule to book."
|
|
895
|
+
}
|
|
896
|
+
},
|
|
897
|
+
{
|
|
898
|
+
key: "patient-abadi-leila",
|
|
899
|
+
values: {
|
|
900
|
+
full_name: "Leila Abadi",
|
|
901
|
+
chart_number: "HD-10462",
|
|
902
|
+
date_of_birth: "1997-05-30",
|
|
903
|
+
phone: "+1 360 555 0308",
|
|
904
|
+
email: "leila.abadi@westwindstudio.com",
|
|
905
|
+
street: "77 Fairhaven Parkway",
|
|
906
|
+
city: "Bellingham",
|
|
907
|
+
region: "WA",
|
|
908
|
+
postal_code: "98225",
|
|
909
|
+
intake_stage: "Forms received",
|
|
910
|
+
insurance_carrier: "Aetna",
|
|
911
|
+
member_id: "AE-55823094",
|
|
912
|
+
primary_dentist: "Dr. Alina Reyes",
|
|
913
|
+
allergies: ["None reported"],
|
|
914
|
+
balance_due: 0,
|
|
915
|
+
referred_by: "Existing patient referral",
|
|
916
|
+
front_desk_notes: "Forms in. Needs eligibility checked before we offer a slot."
|
|
917
|
+
}
|
|
918
|
+
},
|
|
919
|
+
{
|
|
920
|
+
key: "patient-delacroix-yvon",
|
|
921
|
+
values: {
|
|
922
|
+
full_name: "Yvon Delacroix",
|
|
923
|
+
chart_number: "HD-10466",
|
|
924
|
+
date_of_birth: "1981-09-14",
|
|
925
|
+
phone: "+1 360 555 0341",
|
|
926
|
+
email: "yvon.delacroix@pugetsoundfreight.com",
|
|
927
|
+
street: "3320 Northwest Avenue",
|
|
928
|
+
city: "Bellingham",
|
|
929
|
+
region: "WA",
|
|
930
|
+
postal_code: "98225",
|
|
931
|
+
intake_stage: "Forms sent",
|
|
932
|
+
insurance_carrier: "Delta Dental",
|
|
933
|
+
member_id: "DD-884977120",
|
|
934
|
+
primary_dentist: "Dr. Marcus Webb",
|
|
935
|
+
allergies: ["None reported"],
|
|
936
|
+
balance_due: 0,
|
|
937
|
+
referred_by: "Insurance directory",
|
|
938
|
+
front_desk_notes: "Packet emailed Tuesday. Follow up if nothing back by Friday."
|
|
939
|
+
}
|
|
940
|
+
},
|
|
941
|
+
{
|
|
942
|
+
key: "patient-strand-ingrid",
|
|
943
|
+
values: {
|
|
944
|
+
full_name: "Ingrid Strand",
|
|
945
|
+
chart_number: "HD-10470",
|
|
946
|
+
date_of_birth: "1955-12-04",
|
|
947
|
+
phone: "+1 360 555 0392",
|
|
948
|
+
email: "ingrid.strand@northshoremail.com",
|
|
949
|
+
street: "618 Alabama Street",
|
|
950
|
+
city: "Bellingham",
|
|
951
|
+
region: "WA",
|
|
952
|
+
postal_code: "98225",
|
|
953
|
+
intake_stage: "Active patient",
|
|
954
|
+
insurance_carrier: "Self-pay",
|
|
955
|
+
member_id: "",
|
|
956
|
+
primary_dentist: "Dr. Alina Reyes",
|
|
957
|
+
allergies: ["Sulfa drugs", "Local anaesthetic"],
|
|
958
|
+
balance_due: 880,
|
|
959
|
+
referred_by: "Walk-in",
|
|
960
|
+
front_desk_notes: "On a payment plan for the crown. Anaesthetic sensitivity \u2014 Dr. Reyes is aware."
|
|
961
|
+
}
|
|
962
|
+
},
|
|
963
|
+
{
|
|
964
|
+
key: "patient-mbeki-sipho",
|
|
965
|
+
values: {
|
|
966
|
+
full_name: "Sipho Mbeki",
|
|
967
|
+
chart_number: "HD-10473",
|
|
968
|
+
date_of_birth: "2001-02-21",
|
|
969
|
+
phone: "+1 360 555 0415",
|
|
970
|
+
email: "sipho.mbeki@wwu-alumni.com",
|
|
971
|
+
street: "1502 Indian Street",
|
|
972
|
+
city: "Bellingham",
|
|
973
|
+
region: "WA",
|
|
974
|
+
postal_code: "98225",
|
|
975
|
+
intake_stage: "Enquiry",
|
|
976
|
+
insurance_carrier: "Self-pay",
|
|
977
|
+
member_id: "",
|
|
978
|
+
primary_dentist: "Dr. Marcus Webb",
|
|
979
|
+
allergies: ["None reported"],
|
|
980
|
+
balance_due: 0,
|
|
981
|
+
referred_by: "Web search",
|
|
982
|
+
front_desk_notes: "Called about a chipped incisor. Quoted the emergency exam fee."
|
|
983
|
+
}
|
|
984
|
+
},
|
|
985
|
+
{
|
|
986
|
+
key: "patient-kowalczyk-agata",
|
|
987
|
+
values: {
|
|
988
|
+
full_name: "Agata Kowalczyk",
|
|
989
|
+
chart_number: "HD-10477",
|
|
990
|
+
date_of_birth: "1986-06-11",
|
|
991
|
+
phone: "+1 360 555 0448",
|
|
992
|
+
email: "a.kowalczyk@evergreenlabsupply.com",
|
|
993
|
+
street: "2245 Cornwall Avenue",
|
|
994
|
+
city: "Bellingham",
|
|
995
|
+
region: "WA",
|
|
996
|
+
postal_code: "98225",
|
|
997
|
+
intake_stage: "Active patient",
|
|
998
|
+
insurance_carrier: "Cigna Dental",
|
|
999
|
+
member_id: "CG-4488317",
|
|
1000
|
+
primary_dentist: "Dr. Alina Reyes",
|
|
1001
|
+
allergies: ["None reported"],
|
|
1002
|
+
balance_due: 64,
|
|
1003
|
+
referred_by: "Existing patient referral",
|
|
1004
|
+
front_desk_notes: "Night guard impressions taken; lab case out."
|
|
1005
|
+
}
|
|
1006
|
+
},
|
|
1007
|
+
{
|
|
1008
|
+
key: "patient-ferreira-joao",
|
|
1009
|
+
values: {
|
|
1010
|
+
full_name: "Jo\xE3o Ferreira",
|
|
1011
|
+
chart_number: "HD-10481",
|
|
1012
|
+
date_of_birth: "1970-08-19",
|
|
1013
|
+
phone: "+1 360 555 0472",
|
|
1014
|
+
email: "joao.ferreira@harborlinemarine.com",
|
|
1015
|
+
street: "840 Marine Drive",
|
|
1016
|
+
city: "Bellingham",
|
|
1017
|
+
region: "WA",
|
|
1018
|
+
postal_code: "98225",
|
|
1019
|
+
intake_stage: "Insurance verified",
|
|
1020
|
+
insurance_carrier: "MetLife",
|
|
1021
|
+
member_id: "ML-63988402",
|
|
1022
|
+
primary_dentist: "Dr. Marcus Webb",
|
|
1023
|
+
allergies: ["Penicillin", "Latex"],
|
|
1024
|
+
balance_due: 0,
|
|
1025
|
+
referred_by: "Employer benefits fair",
|
|
1026
|
+
front_desk_notes: "Two allergies on file. Wants the first available Thursday."
|
|
1027
|
+
}
|
|
1028
|
+
},
|
|
1029
|
+
{
|
|
1030
|
+
key: "patient-whitehorse-dara",
|
|
1031
|
+
values: {
|
|
1032
|
+
full_name: "Dara Whitehorse",
|
|
1033
|
+
chart_number: "HD-10484",
|
|
1034
|
+
date_of_birth: "1994-04-07",
|
|
1035
|
+
phone: "+1 360 555 0501",
|
|
1036
|
+
email: "dara.whitehorse@salishseaarts.com",
|
|
1037
|
+
street: "506 Girard Street",
|
|
1038
|
+
city: "Bellingham",
|
|
1039
|
+
region: "WA",
|
|
1040
|
+
postal_code: "98225",
|
|
1041
|
+
intake_stage: "First visit booked",
|
|
1042
|
+
insurance_carrier: "Guardian",
|
|
1043
|
+
member_id: "GD-20166018",
|
|
1044
|
+
primary_dentist: "Dr. Alina Reyes",
|
|
1045
|
+
allergies: ["None reported"],
|
|
1046
|
+
balance_due: 0,
|
|
1047
|
+
referred_by: "Web search",
|
|
1048
|
+
front_desk_notes: "Booked for the new patient exam and a cleaning back to back."
|
|
1049
|
+
}
|
|
1050
|
+
},
|
|
1051
|
+
{
|
|
1052
|
+
key: "patient-oconnell-brigid",
|
|
1053
|
+
values: {
|
|
1054
|
+
full_name: "Brigid O'Connell",
|
|
1055
|
+
chart_number: "HD-10489",
|
|
1056
|
+
date_of_birth: "1959-10-23",
|
|
1057
|
+
phone: "+1 360 555 0533",
|
|
1058
|
+
email: "brigid.oconnell@northshoremail.com",
|
|
1059
|
+
street: "3901 Sunset Drive",
|
|
1060
|
+
city: "Bellingham",
|
|
1061
|
+
region: "WA",
|
|
1062
|
+
postal_code: "98229",
|
|
1063
|
+
intake_stage: "Active patient",
|
|
1064
|
+
insurance_carrier: "Delta Dental",
|
|
1065
|
+
member_id: "DD-885013366",
|
|
1066
|
+
primary_dentist: "Dr. Marcus Webb",
|
|
1067
|
+
allergies: ["Codeine"],
|
|
1068
|
+
balance_due: 310.75,
|
|
1069
|
+
referred_by: "Existing patient referral",
|
|
1070
|
+
front_desk_notes: "Crown seat next month. Balance is the patient portion from the last claim."
|
|
1071
|
+
}
|
|
1072
|
+
},
|
|
1073
|
+
{
|
|
1074
|
+
key: "patient-tran-hieu",
|
|
1075
|
+
values: {
|
|
1076
|
+
full_name: "Hieu Tran",
|
|
1077
|
+
chart_number: "HD-10492",
|
|
1078
|
+
date_of_birth: "1990-12-15",
|
|
1079
|
+
phone: "+1 360 555 0566",
|
|
1080
|
+
email: "hieu.tran@baysidedesignco.com",
|
|
1081
|
+
street: "1215 Lakeway Drive",
|
|
1082
|
+
city: "Bellingham",
|
|
1083
|
+
region: "WA",
|
|
1084
|
+
postal_code: "98229",
|
|
1085
|
+
intake_stage: "Forms received",
|
|
1086
|
+
insurance_carrier: "Aetna",
|
|
1087
|
+
member_id: "AE-55901287",
|
|
1088
|
+
primary_dentist: "Dr. Alina Reyes",
|
|
1089
|
+
allergies: ["None reported"],
|
|
1090
|
+
balance_due: 0,
|
|
1091
|
+
referred_by: "Insurance directory",
|
|
1092
|
+
front_desk_notes: "Medical history mentions a heart murmur \u2014 confirm premedication with Dr. Reyes."
|
|
1093
|
+
}
|
|
1094
|
+
},
|
|
1095
|
+
{
|
|
1096
|
+
key: "patient-bergstrom-annika",
|
|
1097
|
+
values: {
|
|
1098
|
+
full_name: "Annika Bergstr\xF6m",
|
|
1099
|
+
chart_number: "HD-10496",
|
|
1100
|
+
date_of_birth: "1983-02-08",
|
|
1101
|
+
phone: "+1 360 555 0590",
|
|
1102
|
+
email: "annika.bergstrom@cascadiaoutfitters.com",
|
|
1103
|
+
street: "705 Samish Way",
|
|
1104
|
+
city: "Bellingham",
|
|
1105
|
+
region: "WA",
|
|
1106
|
+
postal_code: "98225",
|
|
1107
|
+
intake_stage: "Enquiry",
|
|
1108
|
+
insurance_carrier: "Cigna Dental",
|
|
1109
|
+
member_id: "CG-4491550",
|
|
1110
|
+
primary_dentist: "Dr. Marcus Webb",
|
|
1111
|
+
allergies: ["None reported"],
|
|
1112
|
+
balance_due: 0,
|
|
1113
|
+
referred_by: "Walk-in",
|
|
1114
|
+
front_desk_notes: "Came in over lunch asking about whitening. Packet not sent yet."
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
]
|
|
1118
|
+
},
|
|
1119
|
+
{
|
|
1120
|
+
token: "visit",
|
|
1121
|
+
name: "Visits",
|
|
1122
|
+
labelSingular: "Visit",
|
|
1123
|
+
labelPlural: "Visits",
|
|
1124
|
+
type: "entity",
|
|
1125
|
+
display: "calendar",
|
|
1126
|
+
weight: "heavy",
|
|
1127
|
+
ordered: true,
|
|
1128
|
+
icon: "calendar-clock",
|
|
1129
|
+
titleField: "summary",
|
|
1130
|
+
describes: "Every booked chair appointment, what it is for, who is in the chair and who is treating.",
|
|
1131
|
+
fields: [
|
|
1132
|
+
{
|
|
1133
|
+
key: "summary",
|
|
1134
|
+
label: "Appointment",
|
|
1135
|
+
parityType: "text",
|
|
1136
|
+
required: true,
|
|
1137
|
+
sensitivity: "internal",
|
|
1138
|
+
contextPolicy: "include"
|
|
1139
|
+
},
|
|
1140
|
+
{
|
|
1141
|
+
key: "patient",
|
|
1142
|
+
label: "Patient",
|
|
1143
|
+
parityType: "relation",
|
|
1144
|
+
required: true,
|
|
1145
|
+
relationTarget: "patient",
|
|
1146
|
+
relationMax: 1,
|
|
1147
|
+
sensitivity: "confidential",
|
|
1148
|
+
contextPolicy: "summarize"
|
|
1149
|
+
},
|
|
1150
|
+
{
|
|
1151
|
+
key: "appointment_at",
|
|
1152
|
+
label: "Date and time",
|
|
1153
|
+
parityType: "datetime",
|
|
1154
|
+
required: true,
|
|
1155
|
+
sensitivity: "internal",
|
|
1156
|
+
contextPolicy: "include"
|
|
1157
|
+
},
|
|
1158
|
+
{
|
|
1159
|
+
key: "duration_minutes",
|
|
1160
|
+
label: "Chair time",
|
|
1161
|
+
parityType: "integer",
|
|
1162
|
+
unit: "min",
|
|
1163
|
+
sensitivity: "internal",
|
|
1164
|
+
contextPolicy: "include"
|
|
1165
|
+
},
|
|
1166
|
+
{
|
|
1167
|
+
key: "procedure",
|
|
1168
|
+
label: "Procedure",
|
|
1169
|
+
parityType: "select",
|
|
1170
|
+
sensitivity: "confidential",
|
|
1171
|
+
contextPolicy: "summarize",
|
|
1172
|
+
choices: [
|
|
1173
|
+
"New patient exam",
|
|
1174
|
+
"Adult prophylaxis",
|
|
1175
|
+
"Child prophylaxis",
|
|
1176
|
+
"Composite filling",
|
|
1177
|
+
"Crown preparation",
|
|
1178
|
+
"Crown seat",
|
|
1179
|
+
"Root canal",
|
|
1180
|
+
"Extraction",
|
|
1181
|
+
"Emergency exam"
|
|
1182
|
+
]
|
|
1183
|
+
},
|
|
1184
|
+
{
|
|
1185
|
+
key: "provider",
|
|
1186
|
+
label: "Provider",
|
|
1187
|
+
parityType: "select",
|
|
1188
|
+
sensitivity: "internal",
|
|
1189
|
+
contextPolicy: "include",
|
|
1190
|
+
choices: [
|
|
1191
|
+
"Dr. Alina Reyes",
|
|
1192
|
+
"Dr. Marcus Webb",
|
|
1193
|
+
"Priya Chandra, RDH",
|
|
1194
|
+
"Tomas Lindgren, RDH"
|
|
1195
|
+
]
|
|
1196
|
+
},
|
|
1197
|
+
{
|
|
1198
|
+
key: "operatory",
|
|
1199
|
+
label: "Operatory",
|
|
1200
|
+
parityType: "select",
|
|
1201
|
+
sensitivity: "internal",
|
|
1202
|
+
contextPolicy: "include",
|
|
1203
|
+
choices: ["Op A", "Op B", "Op C", "Op D", "Op E", "Op F"]
|
|
1204
|
+
},
|
|
1205
|
+
{
|
|
1206
|
+
key: "visit_status",
|
|
1207
|
+
label: "Status",
|
|
1208
|
+
parityType: "select",
|
|
1209
|
+
required: true,
|
|
1210
|
+
sensitivity: "internal",
|
|
1211
|
+
contextPolicy: "include",
|
|
1212
|
+
choices: ["Scheduled", "Confirmed", "Checked in", "Completed", "No-show", "Cancelled"]
|
|
1213
|
+
},
|
|
1214
|
+
{
|
|
1215
|
+
key: "fee",
|
|
1216
|
+
label: "Fee",
|
|
1217
|
+
parityType: "currency",
|
|
1218
|
+
unit: "USD",
|
|
1219
|
+
format: "currency",
|
|
1220
|
+
sensitivity: "confidential",
|
|
1221
|
+
contextPolicy: "summarize"
|
|
1222
|
+
}
|
|
1223
|
+
],
|
|
1224
|
+
rows: [
|
|
1225
|
+
{
|
|
1226
|
+
key: "visit-rivera-prophy-sep",
|
|
1227
|
+
values: {
|
|
1228
|
+
summary: "Adult cleaning \u2014 M. Rivera",
|
|
1229
|
+
patient: "patient-rivera-marisol",
|
|
1230
|
+
appointment_at: "2026-09-08T08:00:00-07:00",
|
|
1231
|
+
duration_minutes: 50,
|
|
1232
|
+
procedure: "Adult prophylaxis",
|
|
1233
|
+
provider: "Priya Chandra, RDH",
|
|
1234
|
+
operatory: "Op B",
|
|
1235
|
+
visit_status: "Completed",
|
|
1236
|
+
fee: 138
|
|
1237
|
+
}
|
|
1238
|
+
},
|
|
1239
|
+
{
|
|
1240
|
+
key: "visit-oyelaran-crown-prep",
|
|
1241
|
+
values: {
|
|
1242
|
+
summary: "Crown prep, lower right \u2014 T. Oyelaran",
|
|
1243
|
+
patient: "patient-oyelaran-tunde",
|
|
1244
|
+
appointment_at: "2026-09-10T13:30:00-07:00",
|
|
1245
|
+
duration_minutes: 90,
|
|
1246
|
+
procedure: "Crown preparation",
|
|
1247
|
+
provider: "Dr. Marcus Webb",
|
|
1248
|
+
operatory: "Op D",
|
|
1249
|
+
visit_status: "Completed",
|
|
1250
|
+
fee: 1240
|
|
1251
|
+
}
|
|
1252
|
+
},
|
|
1253
|
+
{
|
|
1254
|
+
key: "visit-strand-crown-seat",
|
|
1255
|
+
values: {
|
|
1256
|
+
summary: "Crown seat \u2014 I. Strand",
|
|
1257
|
+
patient: "patient-strand-ingrid",
|
|
1258
|
+
appointment_at: "2026-09-14T10:00:00-07:00",
|
|
1259
|
+
duration_minutes: 60,
|
|
1260
|
+
procedure: "Crown seat",
|
|
1261
|
+
provider: "Dr. Alina Reyes",
|
|
1262
|
+
operatory: "Op A",
|
|
1263
|
+
visit_status: "Completed",
|
|
1264
|
+
fee: 880
|
|
1265
|
+
}
|
|
1266
|
+
},
|
|
1267
|
+
{
|
|
1268
|
+
key: "visit-kowalczyk-prophy",
|
|
1269
|
+
values: {
|
|
1270
|
+
summary: "Adult cleaning \u2014 A. Kowalczyk",
|
|
1271
|
+
patient: "patient-kowalczyk-agata",
|
|
1272
|
+
appointment_at: "2026-09-15T09:00:00-07:00",
|
|
1273
|
+
duration_minutes: 50,
|
|
1274
|
+
procedure: "Adult prophylaxis",
|
|
1275
|
+
provider: "Tomas Lindgren, RDH",
|
|
1276
|
+
operatory: "Op C",
|
|
1277
|
+
visit_status: "Completed",
|
|
1278
|
+
fee: 138
|
|
1279
|
+
}
|
|
1280
|
+
},
|
|
1281
|
+
{
|
|
1282
|
+
key: "visit-oconnell-filling",
|
|
1283
|
+
values: {
|
|
1284
|
+
summary: "Composite filling, upper left \u2014 B. O'Connell",
|
|
1285
|
+
patient: "patient-oconnell-brigid",
|
|
1286
|
+
appointment_at: "2026-09-16T14:00:00-07:00",
|
|
1287
|
+
duration_minutes: 60,
|
|
1288
|
+
procedure: "Composite filling",
|
|
1289
|
+
provider: "Dr. Marcus Webb",
|
|
1290
|
+
operatory: "Op D",
|
|
1291
|
+
visit_status: "Completed",
|
|
1292
|
+
fee: 412
|
|
1293
|
+
}
|
|
1294
|
+
},
|
|
1295
|
+
{
|
|
1296
|
+
key: "visit-mbeki-emergency",
|
|
1297
|
+
values: {
|
|
1298
|
+
summary: "Emergency exam, chipped incisor \u2014 S. Mbeki",
|
|
1299
|
+
patient: "patient-mbeki-sipho",
|
|
1300
|
+
appointment_at: "2026-09-17T16:30:00-07:00",
|
|
1301
|
+
duration_minutes: 30,
|
|
1302
|
+
procedure: "Emergency exam",
|
|
1303
|
+
provider: "Dr. Marcus Webb",
|
|
1304
|
+
operatory: "Op E",
|
|
1305
|
+
visit_status: "No-show",
|
|
1306
|
+
fee: 95
|
|
1307
|
+
}
|
|
1308
|
+
},
|
|
1309
|
+
{
|
|
1310
|
+
key: "visit-rivera-filling",
|
|
1311
|
+
values: {
|
|
1312
|
+
summary: "Composite filling, lower left \u2014 M. Rivera",
|
|
1313
|
+
patient: "patient-rivera-marisol",
|
|
1314
|
+
appointment_at: "2026-09-18T08:30:00-07:00",
|
|
1315
|
+
duration_minutes: 60,
|
|
1316
|
+
procedure: "Composite filling",
|
|
1317
|
+
provider: "Dr. Alina Reyes",
|
|
1318
|
+
operatory: "Op A",
|
|
1319
|
+
visit_status: "Completed",
|
|
1320
|
+
fee: 386
|
|
1321
|
+
}
|
|
1322
|
+
},
|
|
1323
|
+
{
|
|
1324
|
+
key: "visit-halvorsen-new-patient",
|
|
1325
|
+
values: {
|
|
1326
|
+
summary: "New patient exam \u2014 B. Halvorsen",
|
|
1327
|
+
patient: "patient-halvorsen-britt",
|
|
1328
|
+
appointment_at: "2026-09-23T09:00:00-07:00",
|
|
1329
|
+
duration_minutes: 60,
|
|
1330
|
+
procedure: "New patient exam",
|
|
1331
|
+
provider: "Dr. Alina Reyes",
|
|
1332
|
+
operatory: "Op A",
|
|
1333
|
+
visit_status: "Confirmed",
|
|
1334
|
+
fee: 215
|
|
1335
|
+
}
|
|
1336
|
+
},
|
|
1337
|
+
{
|
|
1338
|
+
key: "visit-halvorsen-prophy",
|
|
1339
|
+
values: {
|
|
1340
|
+
summary: "Adult cleaning \u2014 B. Halvorsen",
|
|
1341
|
+
patient: "patient-halvorsen-britt",
|
|
1342
|
+
appointment_at: "2026-09-23T10:00:00-07:00",
|
|
1343
|
+
duration_minutes: 50,
|
|
1344
|
+
procedure: "Adult prophylaxis",
|
|
1345
|
+
provider: "Priya Chandra, RDH",
|
|
1346
|
+
operatory: "Op B",
|
|
1347
|
+
visit_status: "Confirmed",
|
|
1348
|
+
fee: 138
|
|
1349
|
+
}
|
|
1350
|
+
},
|
|
1351
|
+
{
|
|
1352
|
+
key: "visit-whitehorse-new-patient",
|
|
1353
|
+
values: {
|
|
1354
|
+
summary: "New patient exam \u2014 D. Whitehorse",
|
|
1355
|
+
patient: "patient-whitehorse-dara",
|
|
1356
|
+
appointment_at: "2026-09-24T11:00:00-07:00",
|
|
1357
|
+
duration_minutes: 60,
|
|
1358
|
+
procedure: "New patient exam",
|
|
1359
|
+
provider: "Dr. Alina Reyes",
|
|
1360
|
+
operatory: "Op A",
|
|
1361
|
+
visit_status: "Scheduled",
|
|
1362
|
+
fee: 215
|
|
1363
|
+
}
|
|
1364
|
+
},
|
|
1365
|
+
{
|
|
1366
|
+
key: "visit-whitehorse-prophy",
|
|
1367
|
+
values: {
|
|
1368
|
+
summary: "Adult cleaning \u2014 D. Whitehorse",
|
|
1369
|
+
patient: "patient-whitehorse-dara",
|
|
1370
|
+
appointment_at: "2026-09-24T12:00:00-07:00",
|
|
1371
|
+
duration_minutes: 50,
|
|
1372
|
+
procedure: "Adult prophylaxis",
|
|
1373
|
+
provider: "Tomas Lindgren, RDH",
|
|
1374
|
+
operatory: "Op C",
|
|
1375
|
+
visit_status: "Scheduled",
|
|
1376
|
+
fee: 138
|
|
1377
|
+
}
|
|
1378
|
+
},
|
|
1379
|
+
{
|
|
1380
|
+
key: "visit-oconnell-crown-seat",
|
|
1381
|
+
values: {
|
|
1382
|
+
summary: "Crown seat \u2014 B. O'Connell",
|
|
1383
|
+
patient: "patient-oconnell-brigid",
|
|
1384
|
+
appointment_at: "2026-10-06T14:30:00-07:00",
|
|
1385
|
+
duration_minutes: 60,
|
|
1386
|
+
procedure: "Crown seat",
|
|
1387
|
+
provider: "Dr. Marcus Webb",
|
|
1388
|
+
operatory: "Op D",
|
|
1389
|
+
visit_status: "Scheduled",
|
|
1390
|
+
fee: 1180
|
|
1391
|
+
}
|
|
1392
|
+
},
|
|
1393
|
+
{
|
|
1394
|
+
key: "visit-ferreira-new-patient",
|
|
1395
|
+
values: {
|
|
1396
|
+
summary: "New patient exam \u2014 J. Ferreira",
|
|
1397
|
+
patient: "patient-ferreira-joao",
|
|
1398
|
+
appointment_at: "2026-10-08T15:00:00-07:00",
|
|
1399
|
+
duration_minutes: 60,
|
|
1400
|
+
procedure: "New patient exam",
|
|
1401
|
+
provider: "Dr. Marcus Webb",
|
|
1402
|
+
operatory: "Op E",
|
|
1403
|
+
visit_status: "Scheduled",
|
|
1404
|
+
fee: 215
|
|
1405
|
+
}
|
|
1406
|
+
},
|
|
1407
|
+
{
|
|
1408
|
+
key: "visit-nakamura-new-patient",
|
|
1409
|
+
values: {
|
|
1410
|
+
summary: "New patient exam \u2014 K. Nakamura",
|
|
1411
|
+
patient: "patient-nakamura-kenji",
|
|
1412
|
+
appointment_at: "2026-10-09T08:30:00-07:00",
|
|
1413
|
+
duration_minutes: 60,
|
|
1414
|
+
procedure: "New patient exam",
|
|
1415
|
+
provider: "Dr. Marcus Webb",
|
|
1416
|
+
operatory: "Op D",
|
|
1417
|
+
visit_status: "Scheduled",
|
|
1418
|
+
fee: 215
|
|
1419
|
+
}
|
|
1420
|
+
},
|
|
1421
|
+
{
|
|
1422
|
+
key: "visit-tran-child-prophy",
|
|
1423
|
+
values: {
|
|
1424
|
+
summary: "Child cleaning \u2014 H. Tran, daughter",
|
|
1425
|
+
patient: "patient-tran-hieu",
|
|
1426
|
+
appointment_at: "2026-10-13T16:00:00-07:00",
|
|
1427
|
+
duration_minutes: 40,
|
|
1428
|
+
procedure: "Child prophylaxis",
|
|
1429
|
+
provider: "Priya Chandra, RDH",
|
|
1430
|
+
operatory: "Op B",
|
|
1431
|
+
visit_status: "Scheduled",
|
|
1432
|
+
fee: 112
|
|
1433
|
+
}
|
|
1434
|
+
},
|
|
1435
|
+
{
|
|
1436
|
+
key: "visit-kowalczyk-cancelled",
|
|
1437
|
+
values: {
|
|
1438
|
+
summary: "Night guard delivery \u2014 A. Kowalczyk",
|
|
1439
|
+
patient: "patient-kowalczyk-agata",
|
|
1440
|
+
appointment_at: "2026-09-19T11:30:00-07:00",
|
|
1441
|
+
duration_minutes: 30,
|
|
1442
|
+
procedure: "Adult prophylaxis",
|
|
1443
|
+
provider: "Tomas Lindgren, RDH",
|
|
1444
|
+
operatory: "Op C",
|
|
1445
|
+
visit_status: "Cancelled",
|
|
1446
|
+
fee: 0
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
]
|
|
1450
|
+
},
|
|
1451
|
+
{
|
|
1452
|
+
token: "insurance_claim",
|
|
1453
|
+
name: "Insurance claims",
|
|
1454
|
+
labelSingular: "Claim",
|
|
1455
|
+
labelPlural: "Claims",
|
|
1456
|
+
type: "ledger",
|
|
1457
|
+
display: "list",
|
|
1458
|
+
weight: "heavy",
|
|
1459
|
+
ordered: false,
|
|
1460
|
+
icon: "file-text",
|
|
1461
|
+
titleField: "claim_number",
|
|
1462
|
+
describes: "What was billed to a carrier for a completed visit, and what came back.",
|
|
1463
|
+
fields: [
|
|
1464
|
+
{
|
|
1465
|
+
key: "claim_number",
|
|
1466
|
+
label: "Claim number",
|
|
1467
|
+
parityType: "text",
|
|
1468
|
+
required: true,
|
|
1469
|
+
sensitivity: "internal",
|
|
1470
|
+
contextPolicy: "include"
|
|
1471
|
+
},
|
|
1472
|
+
{
|
|
1473
|
+
key: "visit",
|
|
1474
|
+
label: "Visit",
|
|
1475
|
+
parityType: "relation",
|
|
1476
|
+
required: true,
|
|
1477
|
+
relationTarget: "visit",
|
|
1478
|
+
relationMax: 1,
|
|
1479
|
+
sensitivity: "confidential",
|
|
1480
|
+
contextPolicy: "summarize"
|
|
1481
|
+
},
|
|
1482
|
+
{
|
|
1483
|
+
key: "carrier",
|
|
1484
|
+
label: "Carrier",
|
|
1485
|
+
parityType: "select",
|
|
1486
|
+
sensitivity: "internal",
|
|
1487
|
+
contextPolicy: "include",
|
|
1488
|
+
choices: ["Delta Dental", "Cigna Dental", "MetLife", "Guardian", "Aetna"]
|
|
1489
|
+
},
|
|
1490
|
+
{
|
|
1491
|
+
key: "submitted_on",
|
|
1492
|
+
label: "Submitted",
|
|
1493
|
+
parityType: "datetime",
|
|
1494
|
+
format: "date",
|
|
1495
|
+
sensitivity: "internal",
|
|
1496
|
+
contextPolicy: "include"
|
|
1497
|
+
},
|
|
1498
|
+
{
|
|
1499
|
+
key: "billed_amount",
|
|
1500
|
+
label: "Billed",
|
|
1501
|
+
parityType: "currency",
|
|
1502
|
+
unit: "USD",
|
|
1503
|
+
format: "currency",
|
|
1504
|
+
sensitivity: "confidential",
|
|
1505
|
+
contextPolicy: "summarize"
|
|
1506
|
+
},
|
|
1507
|
+
{
|
|
1508
|
+
key: "allowed_amount",
|
|
1509
|
+
label: "Carrier allowed",
|
|
1510
|
+
parityType: "currency",
|
|
1511
|
+
unit: "USD",
|
|
1512
|
+
format: "currency",
|
|
1513
|
+
sensitivity: "confidential",
|
|
1514
|
+
contextPolicy: "summarize"
|
|
1515
|
+
},
|
|
1516
|
+
{
|
|
1517
|
+
key: "patient_portion",
|
|
1518
|
+
label: "Patient portion",
|
|
1519
|
+
parityType: "currency",
|
|
1520
|
+
unit: "USD",
|
|
1521
|
+
format: "currency",
|
|
1522
|
+
sensitivity: "confidential",
|
|
1523
|
+
contextPolicy: "summarize"
|
|
1524
|
+
},
|
|
1525
|
+
{
|
|
1526
|
+
key: "claim_status",
|
|
1527
|
+
label: "Claim status",
|
|
1528
|
+
parityType: "select",
|
|
1529
|
+
required: true,
|
|
1530
|
+
sensitivity: "internal",
|
|
1531
|
+
contextPolicy: "include",
|
|
1532
|
+
choices: ["Prepared", "Submitted", "In review", "Paid", "Denied", "Appealed"]
|
|
1533
|
+
}
|
|
1534
|
+
],
|
|
1535
|
+
rows: [
|
|
1536
|
+
{
|
|
1537
|
+
key: "claim-rivera-prophy",
|
|
1538
|
+
values: {
|
|
1539
|
+
claim_number: "HD-CLM-24118",
|
|
1540
|
+
visit: "visit-rivera-prophy-sep",
|
|
1541
|
+
carrier: "Delta Dental",
|
|
1542
|
+
submitted_on: "2026-09-09",
|
|
1543
|
+
billed_amount: 138,
|
|
1544
|
+
allowed_amount: 138,
|
|
1545
|
+
patient_portion: 0,
|
|
1546
|
+
claim_status: "Paid"
|
|
1547
|
+
}
|
|
1548
|
+
},
|
|
1549
|
+
{
|
|
1550
|
+
key: "claim-oyelaran-crown-prep",
|
|
1551
|
+
values: {
|
|
1552
|
+
claim_number: "HD-CLM-24123",
|
|
1553
|
+
visit: "visit-oyelaran-crown-prep",
|
|
1554
|
+
carrier: "Cigna Dental",
|
|
1555
|
+
submitted_on: "2026-09-11",
|
|
1556
|
+
billed_amount: 1240,
|
|
1557
|
+
allowed_amount: 1097.5,
|
|
1558
|
+
patient_portion: 142.5,
|
|
1559
|
+
claim_status: "Paid"
|
|
1560
|
+
}
|
|
1561
|
+
},
|
|
1562
|
+
{
|
|
1563
|
+
key: "claim-kowalczyk-prophy",
|
|
1564
|
+
values: {
|
|
1565
|
+
claim_number: "HD-CLM-24131",
|
|
1566
|
+
visit: "visit-kowalczyk-prophy",
|
|
1567
|
+
carrier: "Cigna Dental",
|
|
1568
|
+
submitted_on: "2026-09-16",
|
|
1569
|
+
billed_amount: 138,
|
|
1570
|
+
allowed_amount: 74,
|
|
1571
|
+
patient_portion: 64,
|
|
1572
|
+
claim_status: "Paid"
|
|
1573
|
+
}
|
|
1574
|
+
},
|
|
1575
|
+
{
|
|
1576
|
+
key: "claim-oconnell-filling",
|
|
1577
|
+
values: {
|
|
1578
|
+
claim_number: "HD-CLM-24136",
|
|
1579
|
+
visit: "visit-oconnell-filling",
|
|
1580
|
+
carrier: "Delta Dental",
|
|
1581
|
+
submitted_on: "2026-09-17",
|
|
1582
|
+
billed_amount: 412,
|
|
1583
|
+
allowed_amount: 310.75,
|
|
1584
|
+
patient_portion: 310.75,
|
|
1585
|
+
claim_status: "In review"
|
|
1586
|
+
}
|
|
1587
|
+
},
|
|
1588
|
+
{
|
|
1589
|
+
key: "claim-rivera-filling",
|
|
1590
|
+
values: {
|
|
1591
|
+
claim_number: "HD-CLM-24140",
|
|
1592
|
+
visit: "visit-rivera-filling",
|
|
1593
|
+
carrier: "Delta Dental",
|
|
1594
|
+
submitted_on: "2026-09-19",
|
|
1595
|
+
billed_amount: 386,
|
|
1596
|
+
allowed_amount: 386,
|
|
1597
|
+
patient_portion: 0,
|
|
1598
|
+
claim_status: "Submitted"
|
|
1599
|
+
}
|
|
1600
|
+
},
|
|
1601
|
+
{
|
|
1602
|
+
key: "claim-strand-crown-seat",
|
|
1603
|
+
values: {
|
|
1604
|
+
claim_number: "HD-CLM-24127",
|
|
1605
|
+
visit: "visit-strand-crown-seat",
|
|
1606
|
+
carrier: "Delta Dental",
|
|
1607
|
+
submitted_on: "2026-09-15",
|
|
1608
|
+
billed_amount: 880,
|
|
1609
|
+
allowed_amount: 0,
|
|
1610
|
+
patient_portion: 880,
|
|
1611
|
+
claim_status: "Denied"
|
|
1612
|
+
}
|
|
1613
|
+
},
|
|
1614
|
+
{
|
|
1615
|
+
key: "claim-oyelaran-resubmit",
|
|
1616
|
+
values: {
|
|
1617
|
+
claim_number: "HD-CLM-24144",
|
|
1618
|
+
visit: "visit-oyelaran-crown-prep",
|
|
1619
|
+
carrier: "Cigna Dental",
|
|
1620
|
+
submitted_on: "2026-09-20",
|
|
1621
|
+
billed_amount: 142.5,
|
|
1622
|
+
allowed_amount: 0,
|
|
1623
|
+
patient_portion: 142.5,
|
|
1624
|
+
claim_status: "Appealed"
|
|
1625
|
+
}
|
|
1626
|
+
},
|
|
1627
|
+
{
|
|
1628
|
+
key: "claim-oconnell-crown-predetermination",
|
|
1629
|
+
values: {
|
|
1630
|
+
claim_number: "HD-CLM-24149",
|
|
1631
|
+
visit: "visit-oconnell-crown-seat",
|
|
1632
|
+
carrier: "Delta Dental",
|
|
1633
|
+
submitted_on: "2026-09-21",
|
|
1634
|
+
billed_amount: 1180,
|
|
1635
|
+
allowed_amount: 0,
|
|
1636
|
+
patient_portion: 0,
|
|
1637
|
+
claim_status: "Prepared"
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1640
|
+
]
|
|
1641
|
+
}
|
|
1642
|
+
],
|
|
1643
|
+
relationships: [
|
|
1644
|
+
{
|
|
1645
|
+
describes: "A visit belongs to the patient who sits in the chair, and it dies with their chart.",
|
|
1646
|
+
fromTable: "visit",
|
|
1647
|
+
fromField: "patient",
|
|
1648
|
+
toTable: "patient",
|
|
1649
|
+
flavor: "owned",
|
|
1650
|
+
cardinality: "one",
|
|
1651
|
+
onDelete: "cascade",
|
|
1652
|
+
inverseKey: "visits"
|
|
1653
|
+
},
|
|
1654
|
+
{
|
|
1655
|
+
describes: "A claim bills exactly one completed visit, and it cannot outlive the visit it bills.",
|
|
1656
|
+
fromTable: "insurance_claim",
|
|
1657
|
+
fromField: "visit",
|
|
1658
|
+
toTable: "visit",
|
|
1659
|
+
flavor: "owned",
|
|
1660
|
+
cardinality: "one",
|
|
1661
|
+
onDelete: "cascade",
|
|
1662
|
+
inverseKey: "claims"
|
|
1663
|
+
}
|
|
1664
|
+
],
|
|
1665
|
+
form: {
|
|
1666
|
+
token: "harbor_dental_new_patient_intake",
|
|
1667
|
+
name: "Harbor Dental new-patient intake",
|
|
1668
|
+
describes: "The packet the front desk emails after the first call. The patient fills it in before they arrive so the hygienist is not taking a medical history in the chair.",
|
|
1669
|
+
audience: "public",
|
|
1670
|
+
table: "patient",
|
|
1671
|
+
fields: [
|
|
1672
|
+
{ fieldKey: "full_name", label: "Your full legal name", required: true, help: "As it appears on your insurance card." },
|
|
1673
|
+
{ fieldKey: "date_of_birth", label: "Date of birth", required: true },
|
|
1674
|
+
{ fieldKey: "phone", label: "Mobile number", required: true, help: "We text appointment reminders to this number." },
|
|
1675
|
+
{ fieldKey: "email", label: "Email", required: true },
|
|
1676
|
+
{ fieldKey: "street", label: "Street address", required: true },
|
|
1677
|
+
{ fieldKey: "city", label: "City", required: true },
|
|
1678
|
+
{ fieldKey: "region", label: "State", required: true },
|
|
1679
|
+
{ fieldKey: "postal_code", label: "ZIP", required: true },
|
|
1680
|
+
{ fieldKey: "insurance_carrier", label: "Dental insurance carrier", help: "Choose Self-pay if you do not have dental coverage." },
|
|
1681
|
+
{ fieldKey: "member_id", label: "Member ID", help: "On the front of your card. We use it to check your benefits before your visit." },
|
|
1682
|
+
{ fieldKey: "allergies", label: "Any known allergies", help: "Select all that apply. We read this out before any injection." },
|
|
1683
|
+
{ fieldKey: "referred_by", label: "How did you hear about us?" }
|
|
1684
|
+
],
|
|
1685
|
+
submitLabel: "Send my intake form",
|
|
1686
|
+
confirmation: "Thank you \u2014 we have your forms. We will check your benefits with your carrier and call you within two business days to find a first appointment that works."
|
|
1687
|
+
},
|
|
1688
|
+
pipeline: {
|
|
1689
|
+
token: "harbor_dental_intake_pipeline",
|
|
1690
|
+
name: "New-patient intake",
|
|
1691
|
+
describes: "The six steps between a stranger calling and a chart the hygienist can work from. Renata works this board every morning.",
|
|
1692
|
+
table: "patient",
|
|
1693
|
+
stageField: "intake_stage",
|
|
1694
|
+
stages: [
|
|
1695
|
+
{
|
|
1696
|
+
key: "Enquiry",
|
|
1697
|
+
label: "Enquiry",
|
|
1698
|
+
describes: "They called or walked in. Nothing has been sent yet. Moves on when the intake packet goes out.",
|
|
1699
|
+
typicalDurationDays: 1
|
|
1700
|
+
},
|
|
1701
|
+
{
|
|
1702
|
+
key: "Forms sent",
|
|
1703
|
+
label: "Forms sent",
|
|
1704
|
+
describes: "The packet is with them. Chase at three days; most people fill it in the evening they get it.",
|
|
1705
|
+
typicalDurationDays: 3
|
|
1706
|
+
},
|
|
1707
|
+
{
|
|
1708
|
+
key: "Forms received",
|
|
1709
|
+
label: "Forms received",
|
|
1710
|
+
describes: "Medical history is in. Anything flagged goes to the treating dentist before we book.",
|
|
1711
|
+
typicalDurationDays: 1
|
|
1712
|
+
},
|
|
1713
|
+
{
|
|
1714
|
+
key: "Insurance verified",
|
|
1715
|
+
label: "Insurance verified",
|
|
1716
|
+
describes: "Eligibility and remaining annual maximum confirmed with the carrier, so nobody is surprised by a bill.",
|
|
1717
|
+
typicalDurationDays: 2
|
|
1718
|
+
},
|
|
1719
|
+
{
|
|
1720
|
+
key: "First visit booked",
|
|
1721
|
+
label: "First visit booked",
|
|
1722
|
+
describes: "Exam and cleaning are on the schedule and confirmed. Moves on the day they are seen.",
|
|
1723
|
+
typicalDurationDays: 14
|
|
1724
|
+
},
|
|
1725
|
+
{
|
|
1726
|
+
key: "Active patient",
|
|
1727
|
+
label: "Active patient",
|
|
1728
|
+
describes: "Seen at least once and on recall. They leave this stage only if they transfer out."
|
|
1729
|
+
}
|
|
1730
|
+
]
|
|
1731
|
+
},
|
|
1732
|
+
dashboardQuestion: {
|
|
1733
|
+
question: "How many people have sent their forms back but still are not on the schedule?",
|
|
1734
|
+
whyItMatters: "Everyone sitting between 'Forms received' and 'First visit booked' is someone who already chose us and is quietly going cold. If the number climbs above about six, Renata blocks an hour to call them before the week gets away.",
|
|
1735
|
+
table: "patient",
|
|
1736
|
+
aggregate: "count",
|
|
1737
|
+
groupBy: "intake_stage",
|
|
1738
|
+
filter: "intake_stage is 'Forms received' or 'Insurance verified'",
|
|
1739
|
+
answerUnit: "patients"
|
|
1740
|
+
},
|
|
1741
|
+
documentTemplate: {
|
|
1742
|
+
token: "harbor_dental_welcome_letter",
|
|
1743
|
+
name: "New patient welcome letter",
|
|
1744
|
+
describes: "Goes out the moment a first visit is booked. It confirms who they will see, what to bring and what the first appointment actually involves, which is the single biggest reason people no-show.",
|
|
1745
|
+
table: "patient",
|
|
1746
|
+
title: "Welcome to {{practice_name}}, {{patient_name}}",
|
|
1747
|
+
body: [
|
|
1748
|
+
"Dear {{patient_name}},",
|
|
1749
|
+
"",
|
|
1750
|
+
"Thank you for choosing {{practice_name}}. Your chart is open under number {{chart_number}} and you will be seeing {{dentist}}.",
|
|
1751
|
+
"",
|
|
1752
|
+
"Your first appointment is a full examination with digital x-rays, followed by a cleaning with one of our hygienists. Together they take about two hours, so please allow for that.",
|
|
1753
|
+
"",
|
|
1754
|
+
"Please bring a photo ID and your {{carrier}} card. We have already checked your benefits, so we can tell you what is covered before any work is agreed \u2014 we do not start treatment you have not said yes to.",
|
|
1755
|
+
"",
|
|
1756
|
+
"If anything about your health has changed since you filled in your forms, tell the front desk when you arrive. It matters more than people expect.",
|
|
1757
|
+
"",
|
|
1758
|
+
"We look forward to meeting you.",
|
|
1759
|
+
"",
|
|
1760
|
+
"{{practice_name}}",
|
|
1761
|
+
"{{practice_phone}}",
|
|
1762
|
+
"{{today}}"
|
|
1763
|
+
].join("\n"),
|
|
1764
|
+
mergeFields: [
|
|
1765
|
+
{ key: "patient_name", from: "full_name", describes: "How we address them in the letter." },
|
|
1766
|
+
{ key: "chart_number", from: "chart_number", describes: "So the letter and the chart agree if they call about it." },
|
|
1767
|
+
{ key: "dentist", from: "primary_dentist", describes: "The dentist they are assigned to." },
|
|
1768
|
+
{ key: "carrier", from: "insurance_carrier", describes: "Tells them which card to bring." },
|
|
1769
|
+
{ key: "practice_name", from: "business", describes: "The practice name." },
|
|
1770
|
+
{ key: "practice_phone", from: "business", describes: "The front desk number." },
|
|
1771
|
+
{ key: "today", from: "today", describes: "The date the letter went out." }
|
|
1772
|
+
]
|
|
1773
|
+
},
|
|
1774
|
+
notificationRule: {
|
|
1775
|
+
token: "harbor_dental_visit_reminder",
|
|
1776
|
+
name: "Day-before appointment reminder",
|
|
1777
|
+
describes: "A no-show costs the practice the whole chair hour and the hygienist's time. A text the day before is the cheapest thing that prevents it, and it is the first automation any practice turns on.",
|
|
1778
|
+
when: {
|
|
1779
|
+
table: "visit",
|
|
1780
|
+
event: "due",
|
|
1781
|
+
field: "appointment_at",
|
|
1782
|
+
daysBefore: 1
|
|
1783
|
+
},
|
|
1784
|
+
audience: "the patient in the chair",
|
|
1785
|
+
channel: "sms",
|
|
1786
|
+
message: "Harbor Dental: a reminder that you are booked with {{provider}} tomorrow at {{appointment_time}}. Reply C to confirm or call 360 555 0142 if you need to move it."
|
|
1787
|
+
},
|
|
1788
|
+
provenance: {
|
|
1789
|
+
kind: "synthesized",
|
|
1790
|
+
authoredBy: "lane REAL-DATA (records use-case library)",
|
|
1791
|
+
authoredOn: "2026-09-21",
|
|
1792
|
+
noRealPeople: true
|
|
1793
|
+
}
|
|
1794
|
+
};
|
|
1795
|
+
harbor_dental_new_patient_intake_default = useCase3;
|
|
1796
|
+
}
|
|
1797
|
+
});
|
|
1798
|
+
|
|
1799
|
+
// src/use-cases/ridgeline-physical-therapy-plan-of-care.ts
|
|
1800
|
+
var ridgeline_physical_therapy_plan_of_care_exports = {};
|
|
1801
|
+
__export(ridgeline_physical_therapy_plan_of_care_exports, {
|
|
1802
|
+
default: () => ridgeline_physical_therapy_plan_of_care_default,
|
|
1803
|
+
useCase: () => useCase4
|
|
1804
|
+
});
|
|
1805
|
+
var useCase4, ridgeline_physical_therapy_plan_of_care_default;
|
|
1806
|
+
var init_ridgeline_physical_therapy_plan_of_care = __esm({
|
|
1807
|
+
"src/use-cases/ridgeline-physical-therapy-plan-of-care.ts"() {
|
|
1808
|
+
"use strict";
|
|
1809
|
+
useCase4 = {
|
|
1810
|
+
id: "ridgeline-physical-therapy-plan-of-care",
|
|
1811
|
+
useCase: "Sasha Lindqvist runs Ridgeline Physical Therapy single-handed, and she uses this to carry a patient from a physician's referral through a course of visits to a treatment goal that is either met or honestly written off, without losing track of who is overdue for a re-evaluation.",
|
|
1812
|
+
industry: "Physical therapy",
|
|
1813
|
+
cleanupTag: "use-case:ridgeline-physical-therapy-plan-of-care",
|
|
1814
|
+
business: {
|
|
1815
|
+
name: "Ridgeline Physical Therapy",
|
|
1816
|
+
legalName: "Ridgeline Physical Therapy, LLC",
|
|
1817
|
+
describes: "A solo outpatient physical therapy practice doing orthopaedic and post-surgical rehabilitation.",
|
|
1818
|
+
address: {
|
|
1819
|
+
line1: "3114 Foothill Boulevard",
|
|
1820
|
+
line2: "Suite B",
|
|
1821
|
+
city: "Boise",
|
|
1822
|
+
region: "ID",
|
|
1823
|
+
postalCode: "83702",
|
|
1824
|
+
country: "US"
|
|
1825
|
+
},
|
|
1826
|
+
phone: "+1 208 555 0173",
|
|
1827
|
+
website: "https://ridgelinept.com",
|
|
1828
|
+
email: "frontdesk@ridgelinept.com",
|
|
1829
|
+
timezone: "America/Boise"
|
|
1830
|
+
},
|
|
1831
|
+
tables: [
|
|
1832
|
+
{
|
|
1833
|
+
token: "patients",
|
|
1834
|
+
name: "Patients",
|
|
1835
|
+
labelSingular: "Patient",
|
|
1836
|
+
labelPlural: "Patients",
|
|
1837
|
+
type: "entity",
|
|
1838
|
+
display: "list",
|
|
1839
|
+
weight: "heavy",
|
|
1840
|
+
ordered: false,
|
|
1841
|
+
icon: "user-round",
|
|
1842
|
+
titleField: "full_name",
|
|
1843
|
+
describes: "Everyone on the caseload, from referral through discharge.",
|
|
1844
|
+
fields: [
|
|
1845
|
+
{ key: "full_name", label: "Patient name", parityType: "text", required: true, sensitivity: "confidential", contextPolicy: "summarize" },
|
|
1846
|
+
{ key: "date_of_birth", label: "Date of birth", parityType: "datetime", format: "date", sensitivity: "confidential", contextPolicy: "exclude" },
|
|
1847
|
+
{ key: "phone", label: "Phone", parityType: "phone", format: "phone", sensitivity: "confidential", contextPolicy: "exclude" },
|
|
1848
|
+
{ key: "email", label: "Email", parityType: "email", format: "email", sensitivity: "confidential", contextPolicy: "exclude" },
|
|
1849
|
+
{ key: "referring_physician", label: "Referring physician", parityType: "text", sensitivity: "internal", contextPolicy: "include" },
|
|
1850
|
+
{ key: "primary_diagnosis", label: "Primary diagnosis", parityType: "text", sensitivity: "confidential", contextPolicy: "summarize" },
|
|
1851
|
+
{ key: "insurance_provider", label: "Insurance", parityType: "select", choices: ["Aetna", "Blue Cross Blue Shield", "UnitedHealthcare", "Cigna", "Medicare", "Self-pay"], sensitivity: "confidential", contextPolicy: "summarize" },
|
|
1852
|
+
{ key: "intake_date", label: "Intake date", parityType: "datetime", format: "date", sensitivity: "internal", contextPolicy: "include" },
|
|
1853
|
+
{ key: "status", label: "Status", parityType: "select", choices: ["Active", "Discharged", "On Hold", "Referred Out"], sensitivity: "internal", contextPolicy: "include" }
|
|
1854
|
+
],
|
|
1855
|
+
rows: [
|
|
1856
|
+
{ key: "patient-nora-castellan", values: { "full_name": "Nora Castellan", "date_of_birth": "1978-03-14", "phone": "555-201-3341", "email": "nora.castellan@northshoremail.com", "referring_physician": "Dr. Amina Reyes", "primary_diagnosis": "Rotator cuff tendinopathy, right shoulder", "insurance_provider": "Aetna", "intake_date": "2026-06-02", "status": "Active" } },
|
|
1857
|
+
{ key: "patient-devon-ashworth", values: { "full_name": "Devon Ashworth", "date_of_birth": "1991-11-02", "phone": "555-201-3342", "email": "devon.ashworth@northshoremail.com", "referring_physician": "Dr. Marcus Feld", "primary_diagnosis": "ACL reconstruction, post-op (6 weeks)", "insurance_provider": "Blue Cross Blue Shield", "intake_date": "2026-06-05", "status": "Active" } },
|
|
1858
|
+
{ key: "patient-priya-vantana", values: { "full_name": "Priya Vantana", "date_of_birth": "1965-07-22", "phone": "555-201-3343", "email": "priya.vantana@northshoremail.com", "referring_physician": "Dr. Amina Reyes", "primary_diagnosis": "Chronic low back pain, L4-L5 disc bulge", "insurance_provider": "Medicare", "intake_date": "2026-05-19", "status": "Active" } },
|
|
1859
|
+
{ key: "patient-isaiah-broome", values: { "full_name": "Isaiah Broome", "date_of_birth": "2002-01-30", "phone": "555-201-3344", "email": "isaiah.broome@northshoremail.com", "referring_physician": "Dr. Lena Ostrowski", "primary_diagnosis": "Grade II ankle sprain, left", "insurance_provider": "UnitedHealthcare", "intake_date": "2026-07-01", "status": "Discharged" } },
|
|
1860
|
+
{ key: "patient-marguerite-solano", values: { "full_name": "Marguerite Solano", "date_of_birth": "1954-09-08", "phone": "555-201-3345", "email": "marguerite.solano@northshoremail.com", "referring_physician": "Dr. Marcus Feld", "primary_diagnosis": "Total knee replacement, post-op (3 weeks)", "insurance_provider": "Medicare", "intake_date": "2026-06-20", "status": "Active" } },
|
|
1861
|
+
{ key: "patient-tobias-reinholt", values: { "full_name": "Tobias Reinholt", "date_of_birth": "1988-04-17", "phone": "555-201-3346", "email": "tobias.reinholt@northshoremail.com", "referring_physician": "Dr. Lena Ostrowski", "primary_diagnosis": "Cervical radiculopathy, C6", "insurance_provider": "Cigna", "intake_date": "2026-07-10", "status": "Active" } },
|
|
1862
|
+
{ key: "patient-odalys-fenmore", values: { "full_name": "Odalys Fenmore", "date_of_birth": "1997-12-25", "phone": "555-201-3347", "email": "odalys.fenmore@northshoremail.com", "referring_physician": "Dr. Amina Reyes", "primary_diagnosis": "Patellofemoral pain syndrome, bilateral", "insurance_provider": "Self-pay", "intake_date": "2026-07-15", "status": "On Hold" } },
|
|
1863
|
+
{ key: "patient-wendell-okafor", values: { "full_name": "Wendell Okafor", "date_of_birth": "1972-02-11", "phone": "555-201-3348", "email": "wendell.okafor@northshoremail.com", "referring_physician": "Dr. Marcus Feld", "primary_diagnosis": "Plantar fasciitis, right heel", "insurance_provider": "Aetna", "intake_date": "2026-06-28", "status": "Active" } },
|
|
1864
|
+
{ key: "patient-camille-duprez", values: { "full_name": "Camille Duprez", "date_of_birth": "1983-06-04", "phone": "555-201-3349", "email": "camille.duprez@northshoremail.com", "referring_physician": "Dr. Lena Ostrowski", "primary_diagnosis": "Lumbar spinal stenosis", "insurance_provider": "Blue Cross Blue Shield", "intake_date": "2026-05-30", "status": "Active" } },
|
|
1865
|
+
{ key: "patient-griffin-alderete", values: { "full_name": "Griffin Alderete", "date_of_birth": "1995-10-19", "phone": "555-201-3350", "email": "griffin.alderete@northshoremail.com", "referring_physician": "Dr. Amina Reyes", "primary_diagnosis": "Achilles tendinopathy, left", "insurance_provider": "UnitedHealthcare", "intake_date": "2026-07-18", "status": "Referred Out" } }
|
|
1866
|
+
]
|
|
1867
|
+
},
|
|
1868
|
+
{
|
|
1869
|
+
token: "appointments",
|
|
1870
|
+
name: "Visits",
|
|
1871
|
+
labelSingular: "Visit",
|
|
1872
|
+
labelPlural: "Visits",
|
|
1873
|
+
type: "entity",
|
|
1874
|
+
display: "calendar",
|
|
1875
|
+
weight: "heavy",
|
|
1876
|
+
ordered: true,
|
|
1877
|
+
icon: "calendar-clock",
|
|
1878
|
+
titleField: "visit_type",
|
|
1879
|
+
describes: "Every booked appointment, what kind of visit it is and whether it happened.",
|
|
1880
|
+
fields: [
|
|
1881
|
+
{ key: "patient", label: "Patient", parityType: "relation", required: true, relationTarget: "patients", relationMax: 1, sensitivity: "internal", contextPolicy: "include" },
|
|
1882
|
+
{ key: "appointment_date", label: "Date", parityType: "datetime", format: "date", sensitivity: "internal", contextPolicy: "include" },
|
|
1883
|
+
{ key: "appointment_time", label: "Time", parityType: "text", sensitivity: "internal", contextPolicy: "include" },
|
|
1884
|
+
{ key: "visit_type", label: "Visit type", parityType: "select", required: true, choices: ["Initial Evaluation", "Follow-up", "Re-evaluation", "Discharge Visit"], sensitivity: "internal", contextPolicy: "include" },
|
|
1885
|
+
{ key: "therapist_name", label: "Therapist", parityType: "text", sensitivity: "internal", contextPolicy: "include" },
|
|
1886
|
+
{ key: "duration_minutes", label: "Length", parityType: "integer", unit: "min", sensitivity: "internal", contextPolicy: "include" },
|
|
1887
|
+
{ key: "status", label: "Status", parityType: "select", choices: ["Scheduled", "Completed", "No-show", "Cancelled"], sensitivity: "internal", contextPolicy: "include" },
|
|
1888
|
+
{ key: "notes", label: "Visit notes", parityType: "long_text", sensitivity: "confidential", contextPolicy: "on_request" }
|
|
1889
|
+
],
|
|
1890
|
+
rows: [
|
|
1891
|
+
{ key: "appointment-01", values: { "patient": "patient-nora-castellan", "appointment_date": "2026-06-02", "appointment_time": "09:00", "visit_type": "Initial Evaluation", "therapist_name": "Dr. Sasha Lindqvist, DPT", "duration_minutes": 60, "status": "Completed", "notes": "AROM shoulder flexion limited to 110 deg, pain 6/10 with overhead reach." } },
|
|
1892
|
+
{ key: "appointment-02", values: { "patient": "patient-nora-castellan", "appointment_date": "2026-06-09", "appointment_time": "09:00", "visit_type": "Follow-up", "therapist_name": "Dr. Sasha Lindqvist, DPT", "duration_minutes": 45, "status": "Completed", "notes": "Progressing isometrics, pain down to 4/10." } },
|
|
1893
|
+
{ key: "appointment-03", values: { "patient": "patient-nora-castellan", "appointment_date": "2026-06-16", "appointment_time": "09:00", "visit_type": "Follow-up", "therapist_name": "Dr. Sasha Lindqvist, DPT", "duration_minutes": 45, "status": "Scheduled", "notes": "" } },
|
|
1894
|
+
{ key: "appointment-04", values: { "patient": "patient-devon-ashworth", "appointment_date": "2026-06-05", "appointment_time": "13:00", "visit_type": "Initial Evaluation", "therapist_name": "Dr. Sasha Lindqvist, DPT", "duration_minutes": 60, "status": "Completed", "notes": "Quad lag present, effusion mild. Cleared for closed-chain work." } },
|
|
1895
|
+
{ key: "appointment-05", values: { "patient": "patient-devon-ashworth", "appointment_date": "2026-06-12", "appointment_time": "13:00", "visit_type": "Follow-up", "therapist_name": "Dr. Sasha Lindqvist, DPT", "duration_minutes": 45, "status": "Completed", "notes": "Quad lag resolving, full passive extension achieved." } },
|
|
1896
|
+
{ key: "appointment-06", values: { "patient": "patient-devon-ashworth", "appointment_date": "2026-06-19", "appointment_time": "13:00", "visit_type": "Follow-up", "therapist_name": "Dr. Sasha Lindqvist, DPT", "duration_minutes": 45, "status": "No-show", "notes": "Patient did not call." } },
|
|
1897
|
+
{ key: "appointment-07", values: { "patient": "patient-priya-vantana", "appointment_date": "2026-05-19", "appointment_time": "10:30", "visit_type": "Initial Evaluation", "therapist_name": "Dr. Marcus Reid, DPT", "duration_minutes": 60, "status": "Completed", "notes": "Positive slump test on right, centralization with extension." } },
|
|
1898
|
+
{ key: "appointment-08", values: { "patient": "patient-priya-vantana", "appointment_date": "2026-06-02", "appointment_time": "10:30", "visit_type": "Follow-up", "therapist_name": "Dr. Marcus Reid, DPT", "duration_minutes": 45, "status": "Completed", "notes": "Symptoms centralizing, tolerating prone press-ups." } },
|
|
1899
|
+
{ key: "appointment-09", values: { "patient": "patient-isaiah-broome", "appointment_date": "2026-07-01", "appointment_time": "15:00", "visit_type": "Initial Evaluation", "therapist_name": "Dr. Marcus Reid, DPT", "duration_minutes": 60, "status": "Completed", "notes": "Grade II sprain, moderate swelling, weight-bearing as tolerated." } },
|
|
1900
|
+
{ key: "appointment-10", values: { "patient": "patient-isaiah-broome", "appointment_date": "2026-07-22", "appointment_time": "15:00", "visit_type": "Discharge Visit", "therapist_name": "Dr. Marcus Reid, DPT", "duration_minutes": 30, "status": "Completed", "notes": "Full ROM restored, single-leg balance 30s, discharged to home program." } },
|
|
1901
|
+
{ key: "appointment-11", values: { "patient": "patient-marguerite-solano", "appointment_date": "2026-06-20", "appointment_time": "11:00", "visit_type": "Initial Evaluation", "therapist_name": "Dr. Sasha Lindqvist, DPT", "duration_minutes": 60, "status": "Completed", "notes": "Knee flexion 85 deg, using front-wheel walker." } },
|
|
1902
|
+
{ key: "appointment-12", values: { "patient": "patient-marguerite-solano", "appointment_date": "2026-06-27", "appointment_time": "11:00", "visit_type": "Follow-up", "therapist_name": "Dr. Sasha Lindqvist, DPT", "duration_minutes": 45, "status": "Completed", "notes": "Flexion improved to 100 deg." } },
|
|
1903
|
+
{ key: "appointment-13", values: { "patient": "patient-marguerite-solano", "appointment_date": "2026-07-04", "appointment_time": "11:00", "visit_type": "Follow-up", "therapist_name": "Dr. Sasha Lindqvist, DPT", "duration_minutes": 45, "status": "Scheduled", "notes": "" } },
|
|
1904
|
+
{ key: "appointment-14", values: { "patient": "patient-tobias-reinholt", "appointment_date": "2026-07-10", "appointment_time": "08:00", "visit_type": "Initial Evaluation", "therapist_name": "Dr. Marcus Reid, DPT", "duration_minutes": 60, "status": "Completed", "notes": "Positive Spurling's test right, numbness in C6 dermatome." } },
|
|
1905
|
+
{ key: "appointment-15", values: { "patient": "patient-wendell-okafor", "appointment_date": "2026-06-28", "appointment_time": "16:00", "visit_type": "Initial Evaluation", "therapist_name": "Dr. Sasha Lindqvist, DPT", "duration_minutes": 60, "status": "Completed", "notes": "Point tenderness at medial calcaneal tubercle, worse first step in AM." } },
|
|
1906
|
+
{ key: "appointment-16", values: { "patient": "patient-camille-duprez", "appointment_date": "2026-05-30", "appointment_time": "09:30", "visit_type": "Initial Evaluation", "therapist_name": "Dr. Marcus Reid, DPT", "duration_minutes": 60, "status": "Completed", "notes": "Symptoms improve with flexion-biased posture, neurogenic claudication at 2 blocks." } },
|
|
1907
|
+
{ key: "appointment-17", values: { "patient": "patient-griffin-alderete", "appointment_date": "2026-07-18", "appointment_time": "14:00", "visit_type": "Initial Evaluation", "therapist_name": "Dr. Marcus Reid, DPT", "duration_minutes": 60, "status": "Completed", "notes": "Referred to orthopedic surgeon for imaging before continuing PT." } }
|
|
1908
|
+
]
|
|
1909
|
+
},
|
|
1910
|
+
{
|
|
1911
|
+
token: "treatment_plans",
|
|
1912
|
+
name: "Treatment plans",
|
|
1913
|
+
labelSingular: "Treatment plan",
|
|
1914
|
+
labelPlural: "Treatment plans",
|
|
1915
|
+
type: "entity",
|
|
1916
|
+
display: "board",
|
|
1917
|
+
weight: "heavy",
|
|
1918
|
+
ordered: false,
|
|
1919
|
+
icon: "clipboard-list",
|
|
1920
|
+
titleField: "diagnosis",
|
|
1921
|
+
describes: "The goal each patient is working toward, and whether they have met it.",
|
|
1922
|
+
fields: [
|
|
1923
|
+
{ key: "patient", label: "Patient", parityType: "relation", required: true, relationTarget: "patients", relationMax: 1, sensitivity: "internal", contextPolicy: "include" },
|
|
1924
|
+
{ key: "diagnosis", label: "Diagnosis", parityType: "text", required: true, sensitivity: "confidential", contextPolicy: "summarize" },
|
|
1925
|
+
{ key: "goal", label: "Goal", parityType: "long_text", sensitivity: "confidential", contextPolicy: "summarize" },
|
|
1926
|
+
{ key: "start_date", label: "Start date", parityType: "datetime", format: "date", sensitivity: "internal", contextPolicy: "include" },
|
|
1927
|
+
{ key: "target_date", label: "Target date", parityType: "datetime", format: "date", sensitivity: "internal", contextPolicy: "include" },
|
|
1928
|
+
{ key: "status", label: "Status", parityType: "select", choices: ["Active", "Met", "Modified", "Discontinued"], sensitivity: "internal", contextPolicy: "include" }
|
|
1929
|
+
],
|
|
1930
|
+
rows: [
|
|
1931
|
+
{ key: "plan-nora-castellan", values: { "patient": "patient-nora-castellan", "diagnosis": "Rotator cuff tendinopathy, right shoulder", "goal": "Restore pain-free overhead reach to 160 deg flexion within 6 weeks.", "start_date": "2026-06-02", "target_date": "2026-07-14", "status": "Active" } },
|
|
1932
|
+
{ key: "plan-devon-ashworth", values: { "patient": "patient-devon-ashworth", "diagnosis": "ACL reconstruction, post-op", "goal": "Return to single-leg squat and stair descent without compensation by week 12.", "start_date": "2026-06-05", "target_date": "2026-08-28", "status": "Active" } },
|
|
1933
|
+
{ key: "plan-priya-vantana", values: { "patient": "patient-priya-vantana", "diagnosis": "Chronic low back pain, L4-L5 disc bulge", "goal": "Centralize symptoms and tolerate 30-minute walk without radiating pain.", "start_date": "2026-05-19", "target_date": "2026-07-19", "status": "Active" } },
|
|
1934
|
+
{ key: "plan-isaiah-broome", values: { "patient": "patient-isaiah-broome", "diagnosis": "Grade II ankle sprain, left", "goal": "Full weight-bearing, return to recreational basketball.", "start_date": "2026-07-01", "target_date": "2026-07-22", "status": "Met" } },
|
|
1935
|
+
{ key: "plan-marguerite-solano", values: { "patient": "patient-marguerite-solano", "diagnosis": "Total knee replacement, post-op", "goal": "Achieve 110 deg flexion and walk without assistive device by week 8.", "start_date": "2026-06-20", "target_date": "2026-08-15", "status": "Active" } },
|
|
1936
|
+
{ key: "plan-tobias-reinholt", values: { "patient": "patient-tobias-reinholt", "diagnosis": "Cervical radiculopathy, C6", "goal": "Resolve numbness, restore full cervical rotation.", "start_date": "2026-07-10", "target_date": "2026-08-21", "status": "Active" } },
|
|
1937
|
+
{ key: "plan-wendell-okafor", values: { "patient": "patient-wendell-okafor", "diagnosis": "Plantar fasciitis, right heel", "goal": "Pain-free first step in the morning, return to daily 3-mile walk.", "start_date": "2026-06-28", "target_date": "2026-08-09", "status": "Active" } },
|
|
1938
|
+
{ key: "plan-camille-duprez", values: { "patient": "patient-camille-duprez", "diagnosis": "Lumbar spinal stenosis", "goal": "Increase walking tolerance to 6 blocks without claudication.", "start_date": "2026-05-30", "target_date": "2026-08-01", "status": "Active" } }
|
|
1939
|
+
]
|
|
1940
|
+
},
|
|
1941
|
+
{
|
|
1942
|
+
token: "exercises_prescribed",
|
|
1943
|
+
name: "Home exercises",
|
|
1944
|
+
labelSingular: "Home exercise",
|
|
1945
|
+
labelPlural: "Home exercises",
|
|
1946
|
+
type: "detail",
|
|
1947
|
+
display: "list",
|
|
1948
|
+
weight: "light",
|
|
1949
|
+
ordered: true,
|
|
1950
|
+
icon: "dumbbell",
|
|
1951
|
+
titleField: "exercise_name",
|
|
1952
|
+
describes: "What each patient was told to do between visits, and how it progresses.",
|
|
1953
|
+
fields: [
|
|
1954
|
+
{ key: "treatment_plan", label: "Treatment plan", parityType: "relation", required: true, relationTarget: "treatment_plans", relationMax: 1, sensitivity: "internal", contextPolicy: "include" },
|
|
1955
|
+
{ key: "exercise_name", label: "Exercise", parityType: "select", required: true, choices: ["Pendulum Exercise", "Scapular Retraction", "Straight Leg Raise", "Quadriceps Sets", "Heel Slides", "Terminal Knee Extension", "Prone Press-ups (McKenzie)", "Cat-Camel Stretch", "Clamshells", "Bridging", "Standing Hip Abduction", "Wall Sits", "Calf Raises", "Hamstring Curls", "Ankle Pumps", "Chin Tucks"], sensitivity: "internal", contextPolicy: "include" },
|
|
1956
|
+
{ key: "sets", label: "Sets", parityType: "integer", sensitivity: "internal", contextPolicy: "include" },
|
|
1957
|
+
{ key: "reps", label: "Reps", parityType: "integer", sensitivity: "internal", contextPolicy: "include" },
|
|
1958
|
+
{ key: "frequency_per_week", label: "Times per week", parityType: "integer", sensitivity: "internal", contextPolicy: "include" },
|
|
1959
|
+
{ key: "progression_notes", label: "Progression notes", parityType: "long_text", sensitivity: "confidential", contextPolicy: "on_request" }
|
|
1960
|
+
],
|
|
1961
|
+
rows: [
|
|
1962
|
+
{ key: "exercises_prescribed-01", values: { "treatment_plan": "plan-nora-castellan", "exercise_name": "Pendulum Exercise", "sets": 3, "reps": 15, "frequency_per_week": 7, "progression_notes": "Started week 1, pain-free arc, add light weight at week 3." } },
|
|
1963
|
+
{ key: "exercises_prescribed-02", values: { "treatment_plan": "plan-nora-castellan", "exercise_name": "Scapular Retraction", "sets": 3, "reps": 12, "frequency_per_week": 5, "progression_notes": "Using resistance band, increase band tension at week 4." } },
|
|
1964
|
+
{ key: "exercises_prescribed-03", values: { "treatment_plan": "plan-devon-ashworth", "exercise_name": "Quadriceps Sets", "sets": 3, "reps": 10, "frequency_per_week": 7, "progression_notes": "Hold 5 seconds, progressing to straight leg raise next visit." } },
|
|
1965
|
+
{ key: "exercises_prescribed-04", values: { "treatment_plan": "plan-devon-ashworth", "exercise_name": "Straight Leg Raise", "sets": 3, "reps": 10, "frequency_per_week": 6, "progression_notes": "No lag observed, add ankle weight 2lb." } },
|
|
1966
|
+
{ key: "exercises_prescribed-05", values: { "treatment_plan": "plan-devon-ashworth", "exercise_name": "Terminal Knee Extension", "sets": 3, "reps": 12, "frequency_per_week": 5, "progression_notes": "Using resistance band anchored behind knee." } },
|
|
1967
|
+
{ key: "exercises_prescribed-06", values: { "treatment_plan": "plan-priya-vantana", "exercise_name": "Prone Press-ups (McKenzie)", "sets": 2, "reps": 10, "frequency_per_week": 6, "progression_notes": "Symptoms centralizing, hold end range 2 seconds." } },
|
|
1968
|
+
{ key: "exercises_prescribed-07", values: { "treatment_plan": "plan-priya-vantana", "exercise_name": "Cat-Camel Stretch", "sets": 2, "reps": 10, "frequency_per_week": 7, "progression_notes": "Morning stiffness reduced." } },
|
|
1969
|
+
{ key: "exercises_prescribed-08", values: { "treatment_plan": "plan-isaiah-broome", "exercise_name": "Ankle Pumps", "sets": 3, "reps": 20, "frequency_per_week": 7, "progression_notes": "Early edema control, progressed to standing balance week 2." } },
|
|
1970
|
+
{ key: "exercises_prescribed-09", values: { "treatment_plan": "plan-marguerite-solano", "exercise_name": "Heel Slides", "sets": 3, "reps": 10, "frequency_per_week": 7, "progression_notes": "Flexion improving 5 deg/week." } },
|
|
1971
|
+
{ key: "exercises_prescribed-10", values: { "treatment_plan": "plan-marguerite-solano", "exercise_name": "Quadriceps Sets", "sets": 4, "reps": 10, "frequency_per_week": 7, "progression_notes": "Hold 5 seconds, no extensor lag." } },
|
|
1972
|
+
{ key: "exercises_prescribed-11", values: { "treatment_plan": "plan-tobias-reinholt", "exercise_name": "Chin Tucks", "sets": 3, "reps": 10, "frequency_per_week": 6, "progression_notes": "Reduces referred symptoms into arm during session." } },
|
|
1973
|
+
{ key: "exercises_prescribed-12", values: { "treatment_plan": "plan-wendell-okafor", "exercise_name": "Calf Raises", "sets": 3, "reps": 15, "frequency_per_week": 5, "progression_notes": "Eccentric emphasis, 3-second lower." } },
|
|
1974
|
+
{ key: "exercises_prescribed-13", values: { "treatment_plan": "plan-camille-duprez", "exercise_name": "Bridging", "sets": 3, "reps": 12, "frequency_per_week": 5, "progression_notes": "Flexion-biased, tolerating well." } },
|
|
1975
|
+
{ key: "exercises_prescribed-14", values: { "treatment_plan": "plan-camille-duprez", "exercise_name": "Standing Hip Abduction", "sets": 3, "reps": 12, "frequency_per_week": 5, "progression_notes": "Added ankle weight this week." } }
|
|
1976
|
+
]
|
|
1977
|
+
}
|
|
1978
|
+
],
|
|
1979
|
+
relationships: [
|
|
1980
|
+
{
|
|
1981
|
+
describes: "A visit belongs to the patient who attends it, and it dies with their chart.",
|
|
1982
|
+
fromTable: "appointments",
|
|
1983
|
+
fromField: "patient",
|
|
1984
|
+
toTable: "patients",
|
|
1985
|
+
flavor: "owned",
|
|
1986
|
+
cardinality: "one",
|
|
1987
|
+
onDelete: "cascade",
|
|
1988
|
+
inverseKey: "visits"
|
|
1989
|
+
},
|
|
1990
|
+
{
|
|
1991
|
+
describes: "A treatment plan belongs to the patient it sets a goal for.",
|
|
1992
|
+
fromTable: "treatment_plans",
|
|
1993
|
+
fromField: "patient",
|
|
1994
|
+
toTable: "patients",
|
|
1995
|
+
flavor: "owned",
|
|
1996
|
+
cardinality: "one",
|
|
1997
|
+
onDelete: "cascade",
|
|
1998
|
+
inverseKey: "treatment_plans"
|
|
1999
|
+
},
|
|
2000
|
+
{
|
|
2001
|
+
describes: "A home exercise is prescribed under exactly one treatment plan and ends with it.",
|
|
2002
|
+
fromTable: "exercises_prescribed",
|
|
2003
|
+
fromField: "treatment_plan",
|
|
2004
|
+
toTable: "treatment_plans",
|
|
2005
|
+
flavor: "owned",
|
|
2006
|
+
cardinality: "one",
|
|
2007
|
+
onDelete: "cascade",
|
|
2008
|
+
inverseKey: "exercises"
|
|
2009
|
+
}
|
|
2010
|
+
],
|
|
2011
|
+
form: {
|
|
2012
|
+
token: "ridgeline_new_patient_referral",
|
|
2013
|
+
name: "Ridgeline new-patient referral intake",
|
|
2014
|
+
describes: "What a referred patient fills in before the initial evaluation, so the first visit is spent examining them rather than typing.",
|
|
2015
|
+
audience: "public",
|
|
2016
|
+
table: "patients",
|
|
2017
|
+
fields: [
|
|
2018
|
+
{ fieldKey: "full_name", label: "Your full name", required: true },
|
|
2019
|
+
{ fieldKey: "date_of_birth", label: "Date of birth", required: true },
|
|
2020
|
+
{ fieldKey: "phone", label: "Best number to reach you", required: true },
|
|
2021
|
+
{ fieldKey: "email", label: "Email", required: true },
|
|
2022
|
+
{ fieldKey: "referring_physician", label: "Who referred you?", required: true, help: "The doctor's name on your referral, so we can send them your plan of care." },
|
|
2023
|
+
{ fieldKey: "primary_diagnosis", label: "What are you coming in for?", help: "In your own words is fine \u2014 we will write the clinical version." },
|
|
2024
|
+
{ fieldKey: "insurance_provider", label: "Insurance", help: "Choose Self-pay if you would rather not bill insurance." }
|
|
2025
|
+
],
|
|
2026
|
+
submitLabel: "Send my referral details",
|
|
2027
|
+
confirmation: "Thank you \u2014 we have your details. We will verify your benefits and call you within one business day to book your initial evaluation, which takes about an hour."
|
|
2028
|
+
},
|
|
2029
|
+
pipeline: {
|
|
2030
|
+
token: "ridgeline_plan_of_care",
|
|
2031
|
+
name: "Plan of care",
|
|
2032
|
+
describes: "What happens to a treatment goal once it is written. Sasha reviews this board every Friday, because a plan that sits in Active past its target date is the one that quietly fails.",
|
|
2033
|
+
table: "treatment_plans",
|
|
2034
|
+
stageField: "status",
|
|
2035
|
+
stages: [
|
|
2036
|
+
{ key: "Active", label: "Active", describes: "The patient is working toward the goal and attending visits. Leaves when the goal is met, changed or abandoned.", typicalDurationDays: 42 },
|
|
2037
|
+
{ key: "Modified", label: "Modified", describes: "Re-evaluation changed the goal or the timeline \u2014 progress was faster or slower than predicted.", typicalDurationDays: 21 },
|
|
2038
|
+
{ key: "Met", label: "Met", describes: "The measured goal was reached. This is what discharge is built on and what the referring physician is told." },
|
|
2039
|
+
{ key: "Discontinued", label: "Discontinued", describes: "Stopped without meeting the goal \u2014 the patient withdrew, was referred out, or their insurance ran out. Written down honestly rather than left Active." }
|
|
2040
|
+
]
|
|
2041
|
+
},
|
|
2042
|
+
dashboardQuestion: {
|
|
2043
|
+
question: "How many plans are still Active past the date I said they would be finished?",
|
|
2044
|
+
whyItMatters: "A plan sitting Active past its target date means a patient is being treated without anyone re-checking whether the treatment is working. Every one of those needs a re-evaluation booked this week, or a decision to change the goal.",
|
|
2045
|
+
table: "treatment_plans",
|
|
2046
|
+
aggregate: "count",
|
|
2047
|
+
groupBy: "status",
|
|
2048
|
+
filter: "status is 'Active' and target_date is before today",
|
|
2049
|
+
answerUnit: "treatment plans"
|
|
2050
|
+
},
|
|
2051
|
+
documentTemplate: {
|
|
2052
|
+
token: "ridgeline_plan_of_care_letter",
|
|
2053
|
+
name: "Plan of care letter to the referring physician",
|
|
2054
|
+
describes: "Goes back to the doctor who made the referral, at the start of care and again at discharge. Physicians refer again when they hear what happened to the last patient they sent, which makes this letter the practice's whole marketing plan.",
|
|
2055
|
+
table: "treatment_plans",
|
|
2056
|
+
title: "Plan of care \u2014 {{diagnosis}}",
|
|
2057
|
+
body: [
|
|
2058
|
+
"Thank you for the referral.",
|
|
2059
|
+
"",
|
|
2060
|
+
"Following evaluation I have started a course of treatment for {{diagnosis}}.",
|
|
2061
|
+
"",
|
|
2062
|
+
"Goal: {{goal}}",
|
|
2063
|
+
"",
|
|
2064
|
+
"Care began on {{start_date}} and I expect to reach that goal by {{target_date}}. The plan is currently {{status}}. The patient is on a home exercise programme between visits, and I re-evaluate objectively rather than by report.",
|
|
2065
|
+
"",
|
|
2066
|
+
"I will write again at discharge with the measured outcome. If anything in the history changes at your end, please tell me \u2014 it usually changes the plan.",
|
|
2067
|
+
"",
|
|
2068
|
+
"{{practice_name}}",
|
|
2069
|
+
"{{practice_phone}}",
|
|
2070
|
+
"{{today}}"
|
|
2071
|
+
].join("\n"),
|
|
2072
|
+
mergeFields: [
|
|
2073
|
+
{ key: "diagnosis", from: "diagnosis", describes: "What is being treated." },
|
|
2074
|
+
{ key: "goal", from: "goal", describes: "The measurable goal, in the words the physician will be told at discharge." },
|
|
2075
|
+
{ key: "start_date", from: "start_date", describes: "When care began." },
|
|
2076
|
+
{ key: "target_date", from: "target_date", describes: "When the goal is expected to be met." },
|
|
2077
|
+
{ key: "status", from: "status", describes: "Where the plan stands today." },
|
|
2078
|
+
{ key: "practice_name", from: "business", describes: "The practice name." },
|
|
2079
|
+
{ key: "practice_phone", from: "business", describes: "The number the physician's office calls back on." },
|
|
2080
|
+
{ key: "today", from: "today", describes: "The date the letter went out." }
|
|
2081
|
+
]
|
|
2082
|
+
},
|
|
2083
|
+
notificationRule: {
|
|
2084
|
+
token: "ridgeline_plan_past_target",
|
|
2085
|
+
name: "A plan has passed its target date",
|
|
2086
|
+
describes: "The one automation a solo therapist genuinely needs: nobody else is watching the caseload, so a goal that quietly slips past its date has to come and find her.",
|
|
2087
|
+
when: {
|
|
2088
|
+
table: "treatment_plans",
|
|
2089
|
+
event: "overdue",
|
|
2090
|
+
field: "target_date"
|
|
2091
|
+
},
|
|
2092
|
+
audience: "the treating therapist",
|
|
2093
|
+
channel: "in_app",
|
|
2094
|
+
message: "{{diagnosis}} has passed its target date of {{target_date}} and is still {{status}}. Book a re-evaluation or change the goal."
|
|
2095
|
+
},
|
|
2096
|
+
provenance: {
|
|
2097
|
+
kind: "synthesized",
|
|
2098
|
+
authoredBy: "data crew (dataset) + lane REAL-DATA (business identity, relationships, form, pipeline, dashboard question, document, notification rule)",
|
|
2099
|
+
authoredOn: "2026-09-21",
|
|
2100
|
+
noRealPeople: true
|
|
2101
|
+
}
|
|
2102
|
+
};
|
|
2103
|
+
ridgeline_physical_therapy_plan_of_care_default = useCase4;
|
|
2104
|
+
}
|
|
2105
|
+
});
|
|
2106
|
+
|
|
2107
|
+
// src/use-cases/registry.ts
|
|
2108
|
+
var registry_exports = {};
|
|
2109
|
+
__export(registry_exports, {
|
|
2110
|
+
USE_CASE_LOADERS: () => USE_CASE_LOADERS,
|
|
2111
|
+
listUseCases: () => listUseCases,
|
|
2112
|
+
loadAllUseCases: () => loadAllUseCases,
|
|
2113
|
+
loadUseCase: () => loadUseCase,
|
|
2114
|
+
summarize: () => summarize,
|
|
2115
|
+
useCaseFor: () => useCaseFor,
|
|
2116
|
+
useCaseIds: () => useCaseIds
|
|
2117
|
+
});
|
|
2118
|
+
function useCaseIds() {
|
|
2119
|
+
return Object.keys(USE_CASE_LOADERS).sort();
|
|
2120
|
+
}
|
|
2121
|
+
async function loadUseCase(id) {
|
|
2122
|
+
const loader = USE_CASE_LOADERS[id];
|
|
2123
|
+
if (!loader) {
|
|
2124
|
+
throw new Error(
|
|
2125
|
+
`There is no use case registered as "${id}". Registered: ${useCaseIds().join(", ")}.`
|
|
2126
|
+
);
|
|
2127
|
+
}
|
|
2128
|
+
const module = await loader();
|
|
2129
|
+
return module.useCase;
|
|
2130
|
+
}
|
|
2131
|
+
async function loadAllUseCases() {
|
|
2132
|
+
return Promise.all(useCaseIds().map((id) => loadUseCase(id)));
|
|
2133
|
+
}
|
|
2134
|
+
function summarize(useCase5) {
|
|
2135
|
+
return {
|
|
2136
|
+
id: useCase5.id,
|
|
2137
|
+
useCase: useCase5.useCase,
|
|
2138
|
+
industry: useCase5.industry,
|
|
2139
|
+
businessName: useCase5.business.name,
|
|
2140
|
+
tableCount: useCase5.tables.length,
|
|
2141
|
+
rowCount: useCase5.tables.reduce((total, table) => total + table.rows.length, 0)
|
|
2142
|
+
};
|
|
2143
|
+
}
|
|
2144
|
+
async function listUseCases() {
|
|
2145
|
+
return (await loadAllUseCases()).map(summarize);
|
|
2146
|
+
}
|
|
2147
|
+
function useCaseFor(consumer) {
|
|
2148
|
+
const ids = useCaseIds();
|
|
2149
|
+
let hash = 0;
|
|
2150
|
+
for (let i = 0; i < consumer.length; i += 1) {
|
|
2151
|
+
hash = hash * 31 + consumer.charCodeAt(i) >>> 0;
|
|
2152
|
+
}
|
|
2153
|
+
const id = ids[hash % ids.length];
|
|
2154
|
+
if (!id) {
|
|
2155
|
+
throw new Error(
|
|
2156
|
+
`No use cases are registered, so there is nothing to give "${consumer}". Add one to USE_CASE_LOADERS.`
|
|
2157
|
+
);
|
|
2158
|
+
}
|
|
2159
|
+
return id;
|
|
2160
|
+
}
|
|
2161
|
+
var USE_CASE_LOADERS;
|
|
2162
|
+
var init_registry = __esm({
|
|
2163
|
+
"src/use-cases/registry.ts"() {
|
|
2164
|
+
"use strict";
|
|
2165
|
+
USE_CASE_LOADERS = {
|
|
2166
|
+
"alvarado-chen-kitchen-weekly-cooking": () => Promise.resolve().then(() => (init_alvarado_chen_kitchen_weekly_cooking(), alvarado_chen_kitchen_weekly_cooking_exports)),
|
|
2167
|
+
"birchwood-avenue-renovation-budget": () => Promise.resolve().then(() => (init_birchwood_avenue_renovation_budget(), birchwood_avenue_renovation_budget_exports)),
|
|
2168
|
+
"harbor-dental-new-patient-intake": () => Promise.resolve().then(() => (init_harbor_dental_new_patient_intake(), harbor_dental_new_patient_intake_exports)),
|
|
2169
|
+
"ridgeline-physical-therapy-plan-of-care": () => Promise.resolve().then(() => (init_ridgeline_physical_therapy_plan_of_care(), ridgeline_physical_therapy_plan_of_care_exports))
|
|
2170
|
+
};
|
|
2171
|
+
}
|
|
2172
|
+
});
|
|
3
2173
|
|
|
4
2174
|
// src/react/context.tsx
|
|
5
2175
|
import {
|
|
@@ -122,6 +2292,80 @@ function isRecordsErr(result) {
|
|
|
122
2292
|
var ok = (data) => ({ ok: true, data });
|
|
123
2293
|
var err = (error) => ({ ok: false, error });
|
|
124
2294
|
|
|
2295
|
+
// src/grid.ts
|
|
2296
|
+
function actionRefusals(error) {
|
|
2297
|
+
return Array.isArray(error.detail) ? error.detail : [];
|
|
2298
|
+
}
|
|
2299
|
+
function exampleSpec(useCase5) {
|
|
2300
|
+
return {
|
|
2301
|
+
business: useCase5.business.name,
|
|
2302
|
+
tables: useCase5.tables.map((t) => ({
|
|
2303
|
+
token: t.token,
|
|
2304
|
+
name: t.name,
|
|
2305
|
+
labelSingular: t.labelSingular,
|
|
2306
|
+
labelPlural: t.labelPlural,
|
|
2307
|
+
type: t.type,
|
|
2308
|
+
display: t.display,
|
|
2309
|
+
weight: t.weight,
|
|
2310
|
+
ordered: t.ordered,
|
|
2311
|
+
titleField: t.titleField,
|
|
2312
|
+
describes: t.describes,
|
|
2313
|
+
fields: t.fields.map((f) => ({
|
|
2314
|
+
key: f.key,
|
|
2315
|
+
label: f.label,
|
|
2316
|
+
parityType: f.parityType,
|
|
2317
|
+
multi: f.multi,
|
|
2318
|
+
dated: f.dated,
|
|
2319
|
+
required: f.required,
|
|
2320
|
+
unit: f.unit ?? void 0,
|
|
2321
|
+
rules: f.rules,
|
|
2322
|
+
choices: f.choices,
|
|
2323
|
+
source: f.source,
|
|
2324
|
+
computeOn: f.computeOn,
|
|
2325
|
+
relationTarget: f.relationTarget,
|
|
2326
|
+
relationMax: f.relationMax,
|
|
2327
|
+
sensitivity: f.sensitivity,
|
|
2328
|
+
contextPolicy: f.contextPolicy
|
|
2329
|
+
})),
|
|
2330
|
+
rows: t.rows
|
|
2331
|
+
}))
|
|
2332
|
+
};
|
|
2333
|
+
}
|
|
2334
|
+
function exportCellText(value) {
|
|
2335
|
+
if (value === null || value === void 0) return "";
|
|
2336
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") return value;
|
|
2337
|
+
return JSON.stringify(value);
|
|
2338
|
+
}
|
|
2339
|
+
async function exportPageXlsx(page, labels = {}, sheetLabel = "Records") {
|
|
2340
|
+
const XLSX = await import("xlsx");
|
|
2341
|
+
const header = page.columns.map((c) => labels[c] ?? c);
|
|
2342
|
+
const body = page.rows.map((row) => page.columns.map((c) => exportCellText(row[c])));
|
|
2343
|
+
const workbook = XLSX.utils.book_new();
|
|
2344
|
+
const name = sheetLabel.replace(/[\\/?*[\]:]/g, " ").trim().slice(0, 31) || "Records";
|
|
2345
|
+
XLSX.utils.book_append_sheet(workbook, XLSX.utils.aoa_to_sheet([header, ...body]), name);
|
|
2346
|
+
const withheld = Object.entries(page.withheld ?? {});
|
|
2347
|
+
if (withheld.length > 0) {
|
|
2348
|
+
XLSX.utils.book_append_sheet(
|
|
2349
|
+
workbook,
|
|
2350
|
+
XLSX.utils.aoa_to_sheet([
|
|
2351
|
+
["Column", "Why it is empty in this export"],
|
|
2352
|
+
...withheld.map(([k, v]) => [labels[k] ?? k, typeof v === "string" ? v : JSON.stringify(v)])
|
|
2353
|
+
]),
|
|
2354
|
+
"Withheld columns"
|
|
2355
|
+
);
|
|
2356
|
+
}
|
|
2357
|
+
if (page.page?.next !== null && page.page?.next !== void 0) {
|
|
2358
|
+
XLSX.utils.book_append_sheet(
|
|
2359
|
+
workbook,
|
|
2360
|
+
XLSX.utils.aoa_to_sheet([[
|
|
2361
|
+
`This file holds the first ${page.page.returned} rows. The table has more; export again from row ${page.page.next + 1}.`
|
|
2362
|
+
]]),
|
|
2363
|
+
"More rows"
|
|
2364
|
+
);
|
|
2365
|
+
}
|
|
2366
|
+
return XLSX.write(workbook, { type: "array", bookType: "xlsx", compression: true });
|
|
2367
|
+
}
|
|
2368
|
+
|
|
125
2369
|
// src/store.generated.ts
|
|
126
2370
|
var ACTOR_VOCABULARY = ["user", "agent", "system"];
|
|
127
2371
|
var RETIRED_ACTOR_WORDS = { "ai": "agent", "code": "system", "human": "user" };
|
|
@@ -367,6 +2611,7 @@ var STORE_DOORS = [
|
|
|
367
2611
|
{ name: "doors_not_deciding_the_record", args: "", returns: "TABLE(function_name text, identity_args text, why text)", security: "invoker" },
|
|
368
2612
|
{ name: "doors_not_masking_fields", args: "", returns: "TABLE(function_name text, identity_args text, why text)", security: "invoker" },
|
|
369
2613
|
{ name: "doors_not_on_one_ladder", args: "", returns: "TABLE(function_name text, identity_args text, why text)", security: "invoker" },
|
|
2614
|
+
{ name: "doors_refusing_in_another_doors_name", args: "", returns: "TABLE(function_name text, identity_args text, why text)", security: "invoker" },
|
|
370
2615
|
{ name: "effective_level", args: "p_user_id uuid, p_organization_id uuid, p_id uuid, p_type text DEFAULT 'record'::text", returns: "permission_level", security: "definer" },
|
|
371
2616
|
{ name: "enrich_cells", args: "p_organization_id uuid, p_table_id uuid, p_field_keys text[] DEFAULT NULL::text[], p_record_ids uuid[] DEFAULT NULL::uuid[]", returns: "TABLE(record_id uuid, field_key text, agent_owned boolean, value jsonb, value_version integer, actor text, on_behalf_of text, written_at timestamp with time zone, source jsonb, absent_reason text, alternates jsonb, pinned boolean, stale boolean, due_at timestamp with time zone)", security: "definer" },
|
|
372
2617
|
{ name: "enrich_declare", args: "p_organization_id uuid, p_field_id uuid, p_spec jsonb", returns: "jsonb", security: "definer" },
|
|
@@ -409,6 +2654,7 @@ var STORE_DOORS = [
|
|
|
409
2654
|
{ name: "field_rules", args: "p_field_data jsonb", returns: "TABLE(kind text, spec jsonb)", security: "invoker" },
|
|
410
2655
|
{ name: "field_update", args: "p_organization_id uuid, p_field_id uuid, p_patch jsonb", returns: "uuid", security: "definer" },
|
|
411
2656
|
{ name: "field_value_convert", args: "p_to jsonb, p_value jsonb", returns: "jsonb", security: "invoker" },
|
|
2657
|
+
{ name: "field_words", args: "p_organization_id uuid, p_field_id uuid, p_value jsonb", returns: "text", security: "invoker" },
|
|
412
2658
|
{ name: "file_kernel_id", args: "", returns: "uuid", security: "invoker" },
|
|
413
2659
|
{ name: "form_declare", args: "p_organization_id uuid, p_table_id uuid, p_title text, p_questions jsonb, p_presentation jsonb DEFAULT '{}'::jsonb, p_submission_cap integer DEFAULT NULL::integer, p_quarantine_rule_id uuid DEFAULT NULL::uuid, p_notify_rule_id uuid DEFAULT NULL::uuid, p_form_id uuid DEFAULT NULL::uuid, p_slug text DEFAULT NULL::text", returns: "uuid", security: "definer" },
|
|
414
2660
|
{ name: "form_notify", args: "p_organization_id uuid, p_form_id uuid, p_record_id uuid, p_submission_id uuid", returns: "uuid", security: "invoker" },
|
|
@@ -500,6 +2746,7 @@ var STORE_DOORS = [
|
|
|
500
2746
|
{ name: "migrate_merge", args: "p_organization_id uuid, p_winner_id uuid, p_loser_id uuid, p_note text DEFAULT NULL::text", returns: "jsonb", security: "definer" },
|
|
501
2747
|
{ name: "migrate_promote", args: "p_organization_id uuid, p_table_id uuid, p_note text DEFAULT NULL::text", returns: "jsonb", security: "definer" },
|
|
502
2748
|
{ name: "migrate_purge", args: "p_organization_id uuid, p_table_id uuid DEFAULT NULL::uuid, p_dry_run boolean DEFAULT true", returns: "jsonb", security: "definer" },
|
|
2749
|
+
{ name: "migrate_purge_hard", args: "p_organization_id uuid, p_table_id uuid DEFAULT NULL::uuid, p_compliance_reason text DEFAULT NULL::text, p_chunk integer DEFAULT 200, p_dry_run boolean DEFAULT true", returns: "jsonb", security: "definer" },
|
|
503
2750
|
{ name: "migrate_reclass", args: "p_organization_id uuid, p_id uuid, p_to text DEFAULT 'field'::text, p_note text DEFAULT NULL::text", returns: "jsonb", security: "definer" },
|
|
504
2751
|
{ name: "migrate_rename", args: "p_organization_id uuid, p_id uuid, p_to text, p_note text DEFAULT NULL::text", returns: "jsonb", security: "definer" },
|
|
505
2752
|
{ name: "migrate_reparent", args: "p_organization_id uuid, p_id uuid, p_parent_id uuid, p_note text DEFAULT NULL::text", returns: "jsonb", security: "definer" },
|
|
@@ -627,6 +2874,7 @@ var STORE_DOORS = [
|
|
|
627
2874
|
{ name: "record_values_versioned", args: "p_organization_id uuid, p_record_id uuid", returns: "TABLE(field_key text, field_id uuid, value jsonb, value_version integer, source jsonb, absent_reason text, actor text, on_behalf_of text, written_at timestamp with time zone, alternates jsonb)", security: "definer" },
|
|
628
2875
|
{ name: "record_words", args: "p_organization_id uuid, p_record_id uuid, p_noun text DEFAULT NULL::text", returns: "text", security: "definer" },
|
|
629
2876
|
{ name: "record_write", args: "p_organization_id uuid, p_table_id uuid, p_data jsonb", returns: "uuid", security: "definer" },
|
|
2877
|
+
{ name: "record_write_graph", args: "p_organization_id uuid, p_table_id uuid, p_parent jsonb, p_edges jsonb DEFAULT '[]'::jsonb, p_children jsonb DEFAULT '[]'::jsonb", returns: "jsonb", security: "definer" },
|
|
630
2878
|
{ name: "record_write_many", args: "p_organization_id uuid, p_table_id uuid, p_rows jsonb[], p_ids uuid[] DEFAULT NULL::uuid[]", returns: "uuid[]", security: "definer" },
|
|
631
2879
|
{ name: "refusals_claiming_a_level_never_asked", args: "", returns: "TABLE(function_name text, identity_args text, why text)", security: "invoker" },
|
|
632
2880
|
{ name: "relation_carry", args: "p_organization_id uuid, p_container_id uuid, p_item_id uuid", returns: "uuid", security: "definer" },
|
|
@@ -705,6 +2953,7 @@ var STORE_DOORS = [
|
|
|
705
2953
|
{ name: "table_declare", args: "p_organization_id uuid, p_spec jsonb", returns: "uuid", security: "definer" },
|
|
706
2954
|
{ name: "table_has_a_visible_record", args: "p_user uuid, p_organization_id uuid, p_table_id uuid", returns: "boolean", security: "definer" },
|
|
707
2955
|
{ name: "table_is_live", args: "p_organization_id uuid, p_table_id uuid", returns: "boolean", security: "invoker" },
|
|
2956
|
+
{ name: "table_is_options_table", args: "p_organization_id uuid, p_table_id uuid", returns: "boolean", security: "invoker" },
|
|
708
2957
|
{ name: "table_kernel_id", args: "", returns: "uuid", security: "invoker" },
|
|
709
2958
|
{ name: "table_record_ceiling", args: "", returns: "integer", security: "invoker" },
|
|
710
2959
|
{ name: "table_record_ceiling", args: "p_organization_id uuid", returns: "integer", security: "invoker" },
|
|
@@ -718,6 +2967,8 @@ var STORE_DOORS = [
|
|
|
718
2967
|
{ name: "table_stage_field", args: "p_organization_id uuid, p_table_id uuid", returns: "text", security: "definer" },
|
|
719
2968
|
{ name: "table_storage", args: "p_organization_id uuid, p_table_id uuid", returns: "text", security: "invoker" },
|
|
720
2969
|
{ name: "table_type_field", args: "p_organization_id uuid, p_table_id uuid", returns: "text", security: "definer" },
|
|
2970
|
+
{ name: "table_unique_rule_fields", args: "p_organization_id uuid, p_table_id uuid", returns: "jsonb", security: "invoker" },
|
|
2971
|
+
{ name: "table_work_kind", args: "p_organization_id uuid, p_table_id uuid", returns: "text", security: "invoker" },
|
|
721
2972
|
{ name: "tables_at_home", args: "p_organization_id uuid, p_home_ids uuid[]", returns: "TABLE(table_id uuid, home_record_id uuid, kind text)", security: "definer" },
|
|
722
2973
|
{ name: "tables_described_without_asking", args: "", returns: "TABLE(function_name text, identity_args text, why text)", security: "invoker" },
|
|
723
2974
|
{ name: "trg_associations_bump_visibility", args: "", returns: "trigger", security: "definer" },
|
|
@@ -833,15 +3084,15 @@ var STORE_REFUSAL_CODES = [
|
|
|
833
3084
|
{ code: "02000", raised_by: "_checklist_instantiate,_portal_invite_payload,_share_write_person,_table_share_invite_payload,checklist_declare,checklist_run,checklist_step_complete,checklist_step_refusal,checklist_template_shape,conversation_scope_bind,dashboard_delete,dashboard_run,doc_letterhead,doc_render_body,doc_render_document,doc_render_read,doc_sign,doc_signature_intact,doc_signature_read,doc_template_delete,doc_template_read,doc_template_save,enrich_pin,entity_field_retire,entity_field_update,entity_record_read,entity_value_write,external_history_event,external_rows,external_stub_upsert,external_writes_set,io_restore,migrate_delete,migrate_extract_parent,migrate_merge,migrate_reclass,migrate_rename,migrate_reparent,migrate_retype,migrate_split,migrate_undo,organization_clear,portal_archive,portal_card,portal_declare,portal_invite,portal_invite_accept,portal_preview,portal_principal_bind,portal_restore,portal_revoke,read_record,record_delete,record_restore,record_restore_preview,record_table,record_update,relation_uncarry,share_access,share_grant,share_lane_set,share_people,share_revoke,sign_request_cancel,sign_request_create,sign_request_remind,sign_request_unchanged,table_archive,table_share_outside_accept,table_share_outside_invite,table_share_outside_resend,table_share_outside_revoke,visibility_as_of,work_approval_decide,work_approval_read,work_approval_request,work_assign,work_record_states,work_set_state" },
|
|
834
3085
|
{ code: "0A000", raised_by: "checklist_step_complete,external_rows,external_source_declare,external_write_through,promote_field,promoted_index_expr,promoted_query_sql,promoted_read,rule_eval,work_assign" },
|
|
835
3086
|
{ code: "22003", raised_by: "context_resolve" },
|
|
836
|
-
{ code: "22004", raised_by: "_entity_custom_fields_guard,_share_write_person,_value_envelope,actor_word,agg_assert_key,agg_sql,anon_capture,anon_token_issue,anon_write,assert_client_may_reach,booking_declare,capture_submit,checklist_declare,context_resolve,dashboard_block_normalize,dashboard_declare,dashboard_window_sql,doc_render_write,doc_sign,doc_signature_write,doc_template_save,enrich_land,enrich_normalize,external_history_event,external_rows,external_source_declare,external_stub_upsert,external_write_through,external_writes_set,field_history,form_declare,form_submit,home_add,io_comment_write,io_import_begin,io_infer_column,io_outbox_drain,io_restore,migrate_choice_keys,migrate_purge,migrate_reclass,migrate_split,migrate_undo,organization_clear,organization_contents,pipeline_declare,pipeline_gate_preview,portal_declare,portal_invite,portal_principal_bind,provenance_retention_days,provenance_write,query_across_homes,query_by_coordinates,query_rollup,record_delete,record_reparent,record_resolve,record_restore,record_update,record_write,record_write_many,relation_carry,relation_own,rule_declare,share_grant,sign_request_create,sign_request_sign,subscription_declare,table_archive,table_declare,table_share_outside_invite,value_restore,view_declare,work_approval_decide,work_approval_request,work_template_declare" },
|
|
3087
|
+
{ code: "22004", raised_by: "_entity_custom_fields_guard,_share_write_person,_value_envelope,actor_word,agg_assert_key,agg_sql,anon_capture,anon_token_issue,anon_write,assert_client_may_reach,booking_declare,capture_submit,checklist_declare,context_resolve,dashboard_block_normalize,dashboard_declare,dashboard_window_sql,doc_render_write,doc_sign,doc_signature_write,doc_template_save,enrich_land,enrich_normalize,external_history_event,external_rows,external_source_declare,external_stub_upsert,external_write_through,external_writes_set,field_history,form_declare,form_submit,home_add,io_comment_write,io_import_begin,io_infer_column,io_outbox_drain,io_restore,migrate_choice_keys,migrate_purge,migrate_purge_hard,migrate_reclass,migrate_split,migrate_undo,organization_clear,organization_contents,pipeline_declare,pipeline_gate_preview,portal_declare,portal_invite,portal_principal_bind,provenance_retention_days,provenance_write,query_across_homes,query_by_coordinates,query_rollup,record_delete,record_reparent,record_resolve,record_restore,record_update,record_write,record_write_graph,record_write_many,relation_carry,relation_own,rule_declare,share_grant,sign_request_create,sign_request_sign,subscription_declare,table_archive,table_declare,table_share_outside_invite,value_restore,view_declare,work_approval_decide,work_approval_request,work_template_declare" },
|
|
837
3088
|
{ code: "22007", raised_by: "dashboard_window_sql" },
|
|
838
3089
|
{ code: "22012", raised_by: "rule_eval" },
|
|
839
|
-
{ code: "22023", raised_by: "_booking_availability,_entity_custom_fields_guard,_take_op_id,_value_envelope,_work_shape_guard,actor_word,agg_assert_key,agg_sql,anon_token_issue,booking_declare,containment_parent,dashboard_block_normalize,dashboard_window_sql,doc_render_body,doc_render_write,doc_signature_write,enrich_declare,enrich_land,enrich_normalize,enrich_pin,entity_value_write,external_history_event,external_source_declare,external_stub_upsert,external_write_through,field_history,field_update,io_export,io_import_begin,io_import_finish,io_import_plan,io_import_report,io_proposal_accept,list_portals,migrate_merge,migrate_reclass,my_levels,organization_clear,page_size,pin_agent_cells,pipeline_move,portal_declare,provenance_write,query_by_coordinates,query_rollup,read_records_archived,record_update,record_write_many,relation_carry,rule_eval,rule_members,share_grant,share_lane_set,sign_request_create,sign_request_sign,subscription_declare,table_rules,visibility_as_of,work_approval_request,work_list,work_slot_hold" },
|
|
3090
|
+
{ code: "22023", raised_by: "_booking_availability,_entity_custom_fields_guard,_take_op_id,_value_envelope,_work_shape_guard,actor_word,agg_assert_key,agg_sql,anon_token_issue,booking_declare,containment_parent,dashboard_block_normalize,dashboard_window_sql,doc_render_body,doc_render_write,doc_signature_write,enrich_declare,enrich_land,enrich_normalize,enrich_pin,entity_value_write,external_history_event,external_source_declare,external_stub_upsert,external_write_through,field_history,field_update,io_export,io_import_begin,io_import_finish,io_import_plan,io_import_report,io_proposal_accept,list_portals,migrate_merge,migrate_reclass,my_levels,organization_clear,page_size,pin_agent_cells,pipeline_move,portal_declare,provenance_write,query_by_coordinates,query_rollup,read_records_archived,record_update,record_write_graph,record_write_many,relation_carry,rule_eval,rule_members,share_grant,share_lane_set,sign_request_create,sign_request_sign,subscription_declare,table_rules,visibility_as_of,work_approval_request,work_list,work_slot_hold" },
|
|
840
3091
|
{ code: "23503", raised_by: "_booking_availability,_checklist_instantiate,_containment_guard,_display_spec_for,_field_document_for,_field_type_parity_guard,_pipeline_stage_key,_record_rule_uses,agg_digest_assemble,anon_publish,anon_rate_take,anon_token_issue,anon_write,assert_organization_wall,booking_cancel,booking_confirm,booking_declare,booking_hold,booking_reschedule,capture_publish,checklist_declare,checklist_steps_table,comment_write,dashboard_declare,delete_rule,doc_sign,doc_template_save,enrich_declare,enrich_due,enrich_land,form_declare,form_submit,home_add,inbound_declare,inbound_mail_land,inbound_set,io_comment_write,io_import_begin,io_import_finish,io_import_report,io_import_rows,io_proposal_accept,migrate_demote,migrate_promote,pipeline_board,pipeline_declare,pipeline_move,pipeline_read,pipeline_transition_refusal,promote_field,promote_table,record_applicability,record_reparent,relation_carry,relation_own,resolve_first_match,rule_applies,rule_declare,rule_eval,rule_members,rule_run,sign_request_create,subscription_mute,subscription_preview,view_declare,work_set_state,work_take_assignment,work_template_instantiate" },
|
|
841
3092
|
{ code: "23505", raised_by: "_share_write_person,_unique_rule_holds,doc_sign,doc_signature_write,entity_field_declare,field_declare,home_add,inbound_declare,io_proposal_accept,relation_carry,relation_own,sign_request_cancel,sign_request_create,table_share_outside_resend,work_approval_decide,work_slot_hold" },
|
|
842
|
-
{ code: "23514", raised_by: "_checklist_instantiate,_checklist_step_guard,_containment_guard,_dated_values_guard,_derived_fields,_display_spec_for,_entity_custom_fields_guard,_field_class_guard,_field_document_for,_field_shape_guard,_field_type_parity_guard,_merge_field_shape_guard,_merge_field_temporal_guard,_promoted_field_cap_guard,_record_rule_uses,_resolve_choice_words,_rule_shape_guard,_rule_topology_guard,_store_relation_edge_names_its_field,_table_columns_word_guard,_table_shape_guard,_undeclared_key_guard,_value_envelope,_with_display,_work_shape_guard,_workdoors_approval_guard,assert_columns_are_defined,assert_entity_is_organization_scoped,booking_declare,capture_publish,capture_sheet_declare,checklist_declare,checklist_step_complete,doc_sign,doc_signature_write,doc_template_save,entity_field_declare,entity_field_retire,entity_field_update,entity_records_find,entity_table,field_declare,field_retire,field_update,home_add,io_comment_write,io_import_rows,migrate_merge,portal_archive,portal_restore,relation_carry,relation_own,sign_request_create,sign_request_sign,table_declare,validate_value_envelope,validate_values,work_set_state,work_slots_declare,work_take_assignment,work_template_instantiate" },
|
|
3093
|
+
{ code: "23514", raised_by: "_checklist_instantiate,_checklist_step_guard,_containment_guard,_dated_values_guard,_derived_fields,_display_spec_for,_entity_custom_fields_guard,_field_class_guard,_field_document_for,_field_shape_guard,_field_type_parity_guard,_merge_field_shape_guard,_merge_field_temporal_guard,_promoted_field_cap_guard,_record_rule_uses,_relation_halves_agree,_resolve_choice_words,_rule_shape_guard,_rule_topology_guard,_store_relation_edge_names_its_field,_table_columns_word_guard,_table_shape_guard,_undeclared_key_guard,_value_envelope,_with_display,_work_shape_guard,_workdoors_approval_guard,assert_columns_are_defined,assert_entity_is_organization_scoped,booking_declare,capture_publish,capture_sheet_declare,checklist_declare,checklist_step_complete,doc_sign,doc_signature_write,doc_template_save,entity_field_declare,entity_field_retire,entity_field_update,entity_records_find,entity_table,field_declare,field_retire,field_update,home_add,io_comment_write,io_import_rows,migrate_merge,migrate_purge_hard,portal_archive,portal_restore,record_write_graph,relation_carry,relation_own,sign_request_create,sign_request_sign,table_declare,validate_value_envelope,validate_values,work_set_state,work_slots_declare,work_take_assignment,work_template_instantiate" },
|
|
843
3094
|
{ code: "40001", raised_by: "has_visibility_at" },
|
|
844
|
-
{ code: "42501", raised_by: "_doc_render_immutable,_doc_signature_immutable,_field_definition_write,_field_write_door,_rule_definition_write,_store_door,agent_table_claim,anon_capture,anon_inbound_land,anon_publish,anon_token_issue,anon_token_verify,anon_write,assert_client_may_change,assert_client_may_open,assert_client_may_reach,assert_may_know_table,assert_organization_admin,assert_store_door,booking_confirm,booking_declare,booking_hold,capture_submit,checklist_run,comment_write,conversation_scope_bind,conversation_scope_unbind,doc_sign,enrich_declare,enrich_due,enrich_land,enrich_normalize,entity_field_declare,entity_field_retire,entity_field_update,entity_value_write,external_write_through,form_declare,form_submit,inbound_mail_land,io_comment_resolve,io_comment_write,io_import_begin,io_import_finish,io_restore,migrate_purge,migrate_reclass,my_levels,organization_clear,portal_declare,portal_invitation,portal_invite,portal_invite_accept,portal_principal_bind,promote_table,query_visibility_parity,read_record,read_records,read_records_archived,read_records_by_ids,read_records_matching,record_table,share_grant,subscription_mute,subscription_preview,table_share_outside_accept,table_share_outside_invite,table_share_outside_resend,visibility_as_of,work_approval_decide,work_approval_read,work_approval_request,work_person" },
|
|
3095
|
+
{ code: "42501", raised_by: "_doc_render_immutable,_doc_signature_immutable,_field_definition_write,_field_write_door,_rule_definition_write,_store_door,agent_table_claim,anon_capture,anon_inbound_land,anon_publish,anon_token_issue,anon_token_verify,anon_write,assert_client_may_change,assert_client_may_open,assert_client_may_reach,assert_may_know_table,assert_organization_admin,assert_store_door,booking_confirm,booking_declare,booking_hold,capture_submit,checklist_run,comment_write,conversation_scope_bind,conversation_scope_unbind,doc_sign,enrich_declare,enrich_due,enrich_land,enrich_normalize,entity_field_declare,entity_field_retire,entity_field_update,entity_value_write,external_write_through,form_declare,form_submit,inbound_mail_land,io_comment_resolve,io_comment_write,io_import_begin,io_import_finish,io_restore,migrate_purge,migrate_purge_hard,migrate_reclass,my_levels,organization_clear,portal_declare,portal_invitation,portal_invite,portal_invite_accept,portal_principal_bind,promote_table,query_visibility_parity,read_record,read_records,read_records_archived,read_records_by_ids,read_records_matching,record_table,record_write_graph,share_grant,subscription_mute,subscription_preview,table_share_outside_accept,table_share_outside_invite,table_share_outside_resend,visibility_as_of,work_approval_decide,work_approval_read,work_approval_request,work_person" },
|
|
845
3096
|
{ code: "42703", raised_by: "entity_table,portal_declare" },
|
|
846
3097
|
{ code: "53400", raised_by: "anon_rate_take,delete_cascade_closure,enrich_due,enrich_land,promote_field" },
|
|
847
3098
|
{ code: "54001", raised_by: "record_delete" },
|
|
@@ -1884,6 +4135,21 @@ var OWED_BY = {
|
|
|
1884
4135
|
table_propose: "W5-AGENT \u2014 AGT-8, the proposal and its approvers",
|
|
1885
4136
|
merge_field_resolve: "W5-MERGE-B \u2014 the resolver's server half",
|
|
1886
4137
|
record_query: "W1-INDEX / W5-SRV \u2014 the promoted-field query path",
|
|
4138
|
+
// Lane GRID-PRIMITIVES (2026-09-22): on the rehearsal branch; they reach the main database at
|
|
4139
|
+
// the chair's 01:00–04:00 PT apply, and `pnpm records:generate` then lists them in
|
|
4140
|
+
// STORE_DOORS. Until then each call answers door_absent naming this line — never a guess.
|
|
4141
|
+
table_decorate: "GRID-PRIMITIVES G1 \u2014 gridprim_a_table_wears_its_colors_and_its_layout.sql (chair's production apply)",
|
|
4142
|
+
table_decorations: "GRID-PRIMITIVES G1 \u2014 gridprim_a_table_wears_its_colors_and_its_layout.sql (chair's production apply)",
|
|
4143
|
+
grid_layout: "GRID-PRIMITIVES G1 \u2014 gridprim_a_table_wears_its_colors_and_its_layout.sql (chair's production apply)",
|
|
4144
|
+
formula_parse: "GRID-PRIMITIVES G3 \u2014 gridprim_a_formula_is_typed_and_the_store_works_it_out.sql (chair's production apply)",
|
|
4145
|
+
action_declare: "GRID-PRIMITIVES G2 \u2014 gridprim_a_row_action_runs_the_whole_selection_at_once.sql (chair's production apply)",
|
|
4146
|
+
row_actions: "GRID-PRIMITIVES G2 \u2014 gridprim_a_row_action_runs_the_whole_selection_at_once.sql (chair's production apply)",
|
|
4147
|
+
action_run: "GRID-PRIMITIVES G2 \u2014 gridprim_a_row_action_runs_the_whole_selection_at_once.sql (chair's production apply)",
|
|
4148
|
+
table_webhook_declare: "GRID-PRIMITIVES G4 \u2014 gridprim_every_row_change_reaches_the_webhook.sql (chair's production apply)",
|
|
4149
|
+
table_webhooks: "GRID-PRIMITIVES G4 \u2014 gridprim_every_row_change_reaches_the_webhook.sql (chair's production apply)",
|
|
4150
|
+
table_webhook_archive: "GRID-PRIMITIVES G4 \u2014 gridprim_every_row_change_reaches_the_webhook.sql (chair's production apply)",
|
|
4151
|
+
table_from_example: "GRID-PRIMITIVES G5 \u2014 gridprim_a_table_can_start_from_a_real_example.sql (chair's production apply)",
|
|
4152
|
+
autonumber_backfill: "GRID-PRIMITIVES G5 \u2014 gridprim_a_table_can_start_from_a_real_example.sql (chair's production apply)",
|
|
1887
4153
|
rule_declare: "W1-RULE \u2014 `custom.record_write` writes `data_class = 'record'`, so the ONE write door cannot make a Rule record; declaring a Rule (and therefore a DOOR-18 subscription) needs a door of its own"
|
|
1888
4154
|
};
|
|
1889
4155
|
var TRUST_SCHEMA = "iam";
|
|
@@ -1905,6 +4171,18 @@ var TRUST_DOORS = {
|
|
|
1905
4171
|
worldPublishAdmit: "world_publish_admit",
|
|
1906
4172
|
claimWorldNamespace: "claim_world_namespace"
|
|
1907
4173
|
};
|
|
4174
|
+
var WORKBENCH_SCHEMA = "workbench";
|
|
4175
|
+
var WORKBENCH_DOORS = {
|
|
4176
|
+
/**
|
|
4177
|
+
* What a page of the OLDER store's relation cells reads, in one round trip.
|
|
4178
|
+
* Same answer shape as `custom.relation_words_many`, same withheld sentence,
|
|
4179
|
+
* and the ladder is asked per record inside it — so batching buys a round
|
|
4180
|
+
* trip and never a disclosure. An id that names nothing comes back as
|
|
4181
|
+
* NOTHING rather than as the withheld sentence, which is what makes an
|
|
4182
|
+
* unresolvable cell distinguishable from a refused one in that store.
|
|
4183
|
+
*/
|
|
4184
|
+
udtRowWordsMany: "udt_row_words_many"
|
|
4185
|
+
};
|
|
1908
4186
|
var DOOR_NAMES = new Set(STORE_DOORS.map((d) => d.name));
|
|
1909
4187
|
function doorExists(name) {
|
|
1910
4188
|
return DOOR_NAMES.has(name);
|
|
@@ -1957,6 +4235,17 @@ var DOORS = {
|
|
|
1957
4235
|
queryTableAsOf: "query_table_as_of",
|
|
1958
4236
|
recordWrite: "record_write",
|
|
1959
4237
|
recordWriteMany: "record_write_many",
|
|
4238
|
+
// A PARENT, THE EDGES IT STANDS ON AND THE ROWS THAT BELONG TO IT — ALL OR NOTHING.
|
|
4239
|
+
// `recordWrite` and `recordWriteMany` are each ONE statement, so a caller that needs a
|
|
4240
|
+
// parent, its provenance edge and its child rows to land together had no door at all: a
|
|
4241
|
+
// loop is N transactions, and a failure on child nineteen leaves a parent standing without
|
|
4242
|
+
// the lines it promised. `custom.record_write_graph` is one statement, so it is one
|
|
4243
|
+
// transaction — and it is not a second write path: it CALLS `custom.record_write_many` for
|
|
4244
|
+
// the rows, `public.assoc_add` for an edge that points out of the store, and
|
|
4245
|
+
// `platform.relation_set` for the parent's own declared relation to its children. Every
|
|
4246
|
+
// guard, every trigger and the same editor rung, once. A refusal anywhere refuses the whole
|
|
4247
|
+
// graph, by name, and nothing is written.
|
|
4248
|
+
recordWriteGraph: "record_write_graph",
|
|
1960
4249
|
recordUpdate: "record_update",
|
|
1961
4250
|
recordDelete: "record_delete",
|
|
1962
4251
|
recordRestore: "record_restore",
|
|
@@ -2352,6 +4641,20 @@ var DOORS = {
|
|
|
2352
4641
|
checklistRuns: "checklist_runs",
|
|
2353
4642
|
checklistStepComplete: "checklist_step_complete",
|
|
2354
4643
|
checklistStepRefusal: "checklist_step_refusal",
|
|
4644
|
+
// THE GRID (lane GRID-PRIMITIVES, 2026-09-22) — what the /data grid rebuild calls. See ../grid.ts.
|
|
4645
|
+
tableDecorate: "table_decorate",
|
|
4646
|
+
tableDecorations: "table_decorations",
|
|
4647
|
+
gridLayout: "grid_layout",
|
|
4648
|
+
formulaParse: "formula_parse",
|
|
4649
|
+
actionDeclare: "action_declare",
|
|
4650
|
+
rowActions: "row_actions",
|
|
4651
|
+
actionRun: "action_run",
|
|
4652
|
+
tableWebhookDeclare: "table_webhook_declare",
|
|
4653
|
+
tableWebhooks: "table_webhooks",
|
|
4654
|
+
tableWebhookArchive: "table_webhook_archive",
|
|
4655
|
+
tableFromExample: "table_from_example",
|
|
4656
|
+
autonumberBackfill: "autonumber_backfill",
|
|
4657
|
+
ioExport: "io_export",
|
|
2355
4658
|
// Declared here BECAUSE they do not exist yet: naming them is what makes the
|
|
2356
4659
|
// absence visible to `pnpm check:store-registry` and to the suite.
|
|
2357
4660
|
metadataSearch: "metadata_search",
|
|
@@ -2571,6 +4874,15 @@ function createRecordsClient(config) {
|
|
|
2571
4874
|
}
|
|
2572
4875
|
return ok(response.data);
|
|
2573
4876
|
}
|
|
4877
|
+
async function workbenchDoor(door, args, where) {
|
|
4878
|
+
const response = await config.dataSource.rpc(door, args, { schema: WORKBENCH_SCHEMA });
|
|
4879
|
+
if (response.error) {
|
|
4880
|
+
const refusal = mapPgError(response.error, where);
|
|
4881
|
+
scream({ code: refusal.code, message: refusal.message, ...refusal.hint ? { hint: refusal.hint } : {}, where });
|
|
4882
|
+
return err(refusal);
|
|
4883
|
+
}
|
|
4884
|
+
return ok(response.data);
|
|
4885
|
+
}
|
|
2574
4886
|
function unfold(document) {
|
|
2575
4887
|
const raw = document ?? {};
|
|
2576
4888
|
const hidden = raw._hidden ?? {};
|
|
@@ -2610,6 +4922,25 @@ function createRecordsClient(config) {
|
|
|
2610
4922
|
"recordWriteMany"
|
|
2611
4923
|
);
|
|
2612
4924
|
},
|
|
4925
|
+
async recordWriteGraph({ table_id, parent, children, edges }) {
|
|
4926
|
+
const opId = mintOpId();
|
|
4927
|
+
return callDoor(
|
|
4928
|
+
DOORS.recordWriteGraph,
|
|
4929
|
+
{
|
|
4930
|
+
p_organization_id: org,
|
|
4931
|
+
p_table_id: table_id,
|
|
4932
|
+
p_parent: { ...parent, _op_id: opId },
|
|
4933
|
+
p_edges: edges ?? [],
|
|
4934
|
+
p_children: (children ?? []).map((child) => ({
|
|
4935
|
+
data: child.data,
|
|
4936
|
+
role: child.role,
|
|
4937
|
+
...child.table_id === void 0 ? {} : { table_id: child.table_id },
|
|
4938
|
+
...child.position === void 0 ? {} : { position: child.position }
|
|
4939
|
+
}))
|
|
4940
|
+
},
|
|
4941
|
+
"recordWriteGraph"
|
|
4942
|
+
);
|
|
4943
|
+
},
|
|
2613
4944
|
async recordUpdate({ record_id, patch, expectedVersion }) {
|
|
2614
4945
|
const result = await callDoor(
|
|
2615
4946
|
DOORS.recordUpdate,
|
|
@@ -2995,16 +5326,26 @@ function createRecordsClient(config) {
|
|
|
2995
5326
|
"relationWords"
|
|
2996
5327
|
);
|
|
2997
5328
|
},
|
|
2998
|
-
async relationWordsMany(
|
|
2999
|
-
const
|
|
5329
|
+
async relationWordsMany(args) {
|
|
5330
|
+
const older = args.store === "older";
|
|
5331
|
+
const result = older ? await workbenchDoor(
|
|
5332
|
+
WORKBENCH_DOORS.udtRowWordsMany,
|
|
5333
|
+
{
|
|
5334
|
+
p_organization_id: org,
|
|
5335
|
+
p_display: args.display ?? null,
|
|
5336
|
+
p_row_ids: args.record_ids
|
|
5337
|
+
},
|
|
5338
|
+
"relationWordsMany(older)"
|
|
5339
|
+
) : await callDoor(
|
|
3000
5340
|
DOORS.relationWordsMany,
|
|
3001
|
-
{ p_organization_id: org, p_field_id: field_id, p_record_ids: record_ids },
|
|
5341
|
+
{ p_organization_id: org, p_field_id: args.field_id, p_record_ids: args.record_ids },
|
|
3002
5342
|
"relationWordsMany"
|
|
3003
5343
|
);
|
|
3004
5344
|
if (!result.ok) return result;
|
|
3005
5345
|
const map = {};
|
|
3006
5346
|
for (const row of result.data ?? []) {
|
|
3007
|
-
|
|
5347
|
+
const id = row?.record_id ?? row?.row_id;
|
|
5348
|
+
if (id && typeof row.words === "string") map[id] = row.words;
|
|
3008
5349
|
}
|
|
3009
5350
|
return { ok: true, data: map };
|
|
3010
5351
|
},
|
|
@@ -4405,6 +6746,132 @@ function createRecordsClient(config) {
|
|
|
4405
6746
|
async storeIsOpen() {
|
|
4406
6747
|
return callDoor(DOORS.storeIsOpen, { p_organization_id: org }, "storeIsOpen");
|
|
4407
6748
|
},
|
|
6749
|
+
// ── THE GRID (lane GRID-PRIMITIVES) ──────────────────────────────────────
|
|
6750
|
+
async tableDecorate({ table_id, path, value }) {
|
|
6751
|
+
return callDoor(
|
|
6752
|
+
DOORS.tableDecorate,
|
|
6753
|
+
{ p_organization_id: org, p_table_id: table_id, p_path: path, p_value: value ?? null },
|
|
6754
|
+
"tableDecorate"
|
|
6755
|
+
);
|
|
6756
|
+
},
|
|
6757
|
+
async tableDecorations({ table_id }) {
|
|
6758
|
+
return callDoor(
|
|
6759
|
+
DOORS.tableDecorations,
|
|
6760
|
+
{ p_organization_id: org, p_table_id: table_id },
|
|
6761
|
+
"tableDecorations"
|
|
6762
|
+
);
|
|
6763
|
+
},
|
|
6764
|
+
async gridLayout({ table_id, view_id }) {
|
|
6765
|
+
return callDoor(
|
|
6766
|
+
DOORS.gridLayout,
|
|
6767
|
+
{ p_organization_id: org, p_table_id: table_id, p_view_id: view_id ?? null },
|
|
6768
|
+
"gridLayout"
|
|
6769
|
+
);
|
|
6770
|
+
},
|
|
6771
|
+
async formulaParse({ table_id, text }) {
|
|
6772
|
+
return callDoor(
|
|
6773
|
+
DOORS.formulaParse,
|
|
6774
|
+
{ p_organization_id: org, p_table_id: table_id, p_text: text },
|
|
6775
|
+
"formulaParse"
|
|
6776
|
+
);
|
|
6777
|
+
},
|
|
6778
|
+
async actionDeclare({ table_id, actions }) {
|
|
6779
|
+
return callDoor(
|
|
6780
|
+
DOORS.actionDeclare,
|
|
6781
|
+
{ p_organization_id: org, p_table_id: table_id, p_actions: actions },
|
|
6782
|
+
"actionDeclare"
|
|
6783
|
+
);
|
|
6784
|
+
},
|
|
6785
|
+
async rowActions({ table_id }) {
|
|
6786
|
+
return callDoor(
|
|
6787
|
+
DOORS.rowActions,
|
|
6788
|
+
{ p_organization_id: org, p_table_id: table_id },
|
|
6789
|
+
"rowActions"
|
|
6790
|
+
);
|
|
6791
|
+
},
|
|
6792
|
+
async actionRun({ action_id, record_ids }) {
|
|
6793
|
+
return callDoor(
|
|
6794
|
+
DOORS.actionRun,
|
|
6795
|
+
{ p_organization_id: org, p_action_id: action_id, p_record_ids: record_ids },
|
|
6796
|
+
"actionRun"
|
|
6797
|
+
);
|
|
6798
|
+
},
|
|
6799
|
+
async tableWebhookDeclare({ table_id, target_url, events, description }) {
|
|
6800
|
+
return callDoor(
|
|
6801
|
+
DOORS.tableWebhookDeclare,
|
|
6802
|
+
{
|
|
6803
|
+
p_organization_id: org,
|
|
6804
|
+
p_table_id: table_id,
|
|
6805
|
+
p_target_url: target_url,
|
|
6806
|
+
p_events: events ?? null,
|
|
6807
|
+
p_description: description ?? null
|
|
6808
|
+
},
|
|
6809
|
+
"tableWebhookDeclare"
|
|
6810
|
+
);
|
|
6811
|
+
},
|
|
6812
|
+
async tableWebhooks({ table_id }) {
|
|
6813
|
+
return callDoor(
|
|
6814
|
+
DOORS.tableWebhooks,
|
|
6815
|
+
{ p_organization_id: org, p_table_id: table_id },
|
|
6816
|
+
"tableWebhooks"
|
|
6817
|
+
);
|
|
6818
|
+
},
|
|
6819
|
+
async tableWebhookArchive({ webhook_id }) {
|
|
6820
|
+
return callDoor(
|
|
6821
|
+
DOORS.tableWebhookArchive,
|
|
6822
|
+
{ p_organization_id: org, p_webhook_id: webhook_id },
|
|
6823
|
+
"tableWebhookArchive"
|
|
6824
|
+
);
|
|
6825
|
+
},
|
|
6826
|
+
async tableFromExample({ home_id, useCaseId }) {
|
|
6827
|
+
const { loadUseCase: loadUseCase2 } = await Promise.resolve().then(() => (init_registry(), registry_exports));
|
|
6828
|
+
let spec;
|
|
6829
|
+
try {
|
|
6830
|
+
spec = exampleSpec(await loadUseCase2(useCaseId));
|
|
6831
|
+
} catch (e) {
|
|
6832
|
+
const refusal = {
|
|
6833
|
+
code: "invalid_argument",
|
|
6834
|
+
message: e instanceof Error ? e.message : String(e),
|
|
6835
|
+
hint: "Offer an example from useCaseIds() in @ai-matrx/records/use-cases. Nothing was created."
|
|
6836
|
+
};
|
|
6837
|
+
scream({ code: refusal.code, message: refusal.message, ...refusal.hint ? { hint: refusal.hint } : {}, where: "tableFromExample" });
|
|
6838
|
+
return err(refusal);
|
|
6839
|
+
}
|
|
6840
|
+
return callDoor(
|
|
6841
|
+
DOORS.tableFromExample,
|
|
6842
|
+
{ p_organization_id: org, p_home_id: home_id, p_example: spec },
|
|
6843
|
+
"tableFromExample"
|
|
6844
|
+
);
|
|
6845
|
+
},
|
|
6846
|
+
async autonumberBackfill({ field_id }) {
|
|
6847
|
+
return callDoor(
|
|
6848
|
+
DOORS.autonumberBackfill,
|
|
6849
|
+
{ p_organization_id: org, p_field_id: field_id },
|
|
6850
|
+
"autonumberBackfill"
|
|
6851
|
+
);
|
|
6852
|
+
},
|
|
6853
|
+
async ioExport({ table_id, columns, limit }) {
|
|
6854
|
+
return callDoor(
|
|
6855
|
+
DOORS.ioExport,
|
|
6856
|
+
{
|
|
6857
|
+
p_organization_id: org,
|
|
6858
|
+
p_table_id: table_id,
|
|
6859
|
+
p_columns: columns ?? null,
|
|
6860
|
+
p_limit: limit ?? null,
|
|
6861
|
+
p_required: "viewer"
|
|
6862
|
+
},
|
|
6863
|
+
"ioExport"
|
|
6864
|
+
);
|
|
6865
|
+
},
|
|
6866
|
+
async exportXlsx({ table_id, columns, limit, labels, sheetLabel }) {
|
|
6867
|
+
const page = await client.ioExport({
|
|
6868
|
+
table_id,
|
|
6869
|
+
...columns !== void 0 ? { columns } : {},
|
|
6870
|
+
...limit !== void 0 ? { limit } : {}
|
|
6871
|
+
});
|
|
6872
|
+
if (!page.ok) return err(page.error);
|
|
6873
|
+
return ok(await exportPageXlsx(page.data, labels ?? {}, sheetLabel ?? "Records"));
|
|
6874
|
+
},
|
|
4408
6875
|
async myLevels({ ids, subject }) {
|
|
4409
6876
|
if (ids.length === 0) return ok([]);
|
|
4410
6877
|
const answered = await callDoor(
|
|
@@ -5119,6 +7586,7 @@ function fieldKindFor(field, kernel) {
|
|
|
5119
7586
|
return "text";
|
|
5120
7587
|
}
|
|
5121
7588
|
}
|
|
7589
|
+
var UUID_TEXT = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
5122
7590
|
var TRUE_WORDS = /* @__PURE__ */ new Set(["true", "yes", "y", "1", "\u2713", "x", "checked", "on"]);
|
|
5123
7591
|
var FALSE_WORDS = /* @__PURE__ */ new Set(["false", "no", "n", "0", "", "unchecked", "off"]);
|
|
5124
7592
|
function coercionLabel(field) {
|
|
@@ -5210,11 +7678,23 @@ function coerceTypedAnswer(field, raw, opts = {}) {
|
|
|
5210
7678
|
// id belongs, and every filter, colour and rollup built on that column
|
|
5211
7679
|
// would stop agreeing with it. So it is refused and the person is told
|
|
5212
7680
|
// which control does hold it.
|
|
7681
|
+
//
|
|
7682
|
+
// BUT AN ID IS AN IDENTITY (RELATION-TARGETS, 2026-09-23). A Person or File
|
|
7683
|
+
// column holds the kernel Person / File record, and the store itself now
|
|
7684
|
+
// turns the id a writer actually holds — a member's user id, an uploaded
|
|
7685
|
+
// file's id, or the record's own id — into that record at every write door
|
|
7686
|
+
// (`custom.relation_kernel_record`), refusing anything else in its own
|
|
7687
|
+
// words ("… names someone who is not a member of …"). So an import column
|
|
7688
|
+
// of member ids, or an agent handing over the file it just uploaded, is a
|
|
7689
|
+
// value and not a refusal; the store, not this mirror, decides whether the
|
|
7690
|
+
// id is somebody here.
|
|
5213
7691
|
case "member":
|
|
7692
|
+
if (UUID_TEXT.test(text)) return { value: text.toLowerCase() };
|
|
5214
7693
|
return {
|
|
5215
7694
|
refusal: `${label} names a person in this organization, so it is chosen rather than typed. Open it and pick them.`
|
|
5216
7695
|
};
|
|
5217
7696
|
case "attachment":
|
|
7697
|
+
if (UUID_TEXT.test(text)) return { value: text.toLowerCase() };
|
|
5218
7698
|
return {
|
|
5219
7699
|
refusal: `${label} holds a file, which cannot arrive as typed-in text. Open it and attach the file.`
|
|
5220
7700
|
};
|
|
@@ -5630,6 +8110,7 @@ export {
|
|
|
5630
8110
|
TABLE_TYPES,
|
|
5631
8111
|
VALUE_ALTERNATE_KEYS,
|
|
5632
8112
|
VALUE_ENVELOPE_KEYS,
|
|
8113
|
+
actionRefusals,
|
|
5633
8114
|
archivedByLine,
|
|
5634
8115
|
archivedWhen,
|
|
5635
8116
|
asPermissionLevel,
|
|
@@ -5644,6 +8125,8 @@ export {
|
|
|
5644
8125
|
emptyArchiveLine,
|
|
5645
8126
|
emptyPortalArchiveLine,
|
|
5646
8127
|
err,
|
|
8128
|
+
exampleSpec,
|
|
8129
|
+
exportPageXlsx,
|
|
5647
8130
|
fieldKindFor,
|
|
5648
8131
|
forgetAllOps,
|
|
5649
8132
|
highestLevel,
|