@alfadocs/ui-kit 1.15.1 → 1.17.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.
Files changed (76) hide show
  1. package/dist/_chunks/{calendar-CHT9Rm3M.js → calendar-PFO-NlYw.js} +2 -2
  2. package/dist/_chunks/{calendar-event-card-BjdHZaqz.js → calendar-event-card-66CEEWU6.js} +38 -20
  3. package/dist/_chunks/calendar-workspace-Ca0n_r1v.js +7341 -0
  4. package/dist/_chunks/{file-manager-DJMeB3V8.js → file-manager-spc3_khe.js} +152 -136
  5. package/dist/_chunks/{signature-field-CEiPe-vX.js → signature-field-0rFODJlW.js} +34 -19
  6. package/dist/agent-catalog.json +10 -56
  7. package/dist/agent-i18n/en.json +3 -5
  8. package/dist/components/calendar/index.js +1 -1
  9. package/dist/components/calendar-event-card/index.js +1 -1
  10. package/dist/components/file-manager/index.js +1 -1
  11. package/dist/components/signature-field/index.js +1 -1
  12. package/dist/i18n/locales/ar.d.ts +2 -38
  13. package/dist/i18n/locales/ar.js +4 -40
  14. package/dist/i18n/locales/de.d.ts +2 -38
  15. package/dist/i18n/locales/de.js +4 -40
  16. package/dist/i18n/locales/el.d.ts +2 -38
  17. package/dist/i18n/locales/el.js +4 -40
  18. package/dist/i18n/locales/en.d.ts +2 -38
  19. package/dist/i18n/locales/en.js +4 -40
  20. package/dist/i18n/locales/es.d.ts +2 -38
  21. package/dist/i18n/locales/es.js +4 -40
  22. package/dist/i18n/locales/fr.d.ts +2 -38
  23. package/dist/i18n/locales/fr.js +4 -40
  24. package/dist/i18n/locales/hi.d.ts +2 -38
  25. package/dist/i18n/locales/hi.js +4 -40
  26. package/dist/i18n/locales/it.d.ts +2 -38
  27. package/dist/i18n/locales/it.js +4 -40
  28. package/dist/i18n/locales/ja.d.ts +2 -38
  29. package/dist/i18n/locales/ja.js +4 -40
  30. package/dist/i18n/locales/nl.d.ts +2 -38
  31. package/dist/i18n/locales/nl.js +4 -40
  32. package/dist/i18n/locales/pl.d.ts +2 -38
  33. package/dist/i18n/locales/pl.js +4 -40
  34. package/dist/i18n/locales/pt.d.ts +2 -38
  35. package/dist/i18n/locales/pt.js +4 -40
  36. package/dist/i18n/locales/ro.d.ts +2 -38
  37. package/dist/i18n/locales/ro.js +4 -40
  38. package/dist/i18n/locales/ru.d.ts +2 -38
  39. package/dist/i18n/locales/ru.js +4 -40
  40. package/dist/i18n/locales/sq.d.ts +2 -38
  41. package/dist/i18n/locales/sq.js +4 -40
  42. package/dist/i18n/locales/sv.d.ts +2 -38
  43. package/dist/i18n/locales/sv.js +4 -40
  44. package/dist/i18n/locales/tr.d.ts +2 -38
  45. package/dist/i18n/locales/tr.js +4 -40
  46. package/dist/i18n/locales/zh.d.ts +2 -38
  47. package/dist/i18n/locales/zh.js +4 -40
  48. package/dist/index.js +5 -5
  49. package/dist/locales/ar.json +4 -40
  50. package/dist/locales/de.json +4 -40
  51. package/dist/locales/el.json +4 -40
  52. package/dist/locales/en.json +4 -40
  53. package/dist/locales/es.json +4 -40
  54. package/dist/locales/fr.json +4 -40
  55. package/dist/locales/hi.json +4 -40
  56. package/dist/locales/it.json +4 -40
  57. package/dist/locales/ja.json +4 -40
  58. package/dist/locales/nl.json +4 -40
  59. package/dist/locales/pl.json +4 -40
  60. package/dist/locales/pt.json +4 -40
  61. package/dist/locales/ro.json +4 -40
  62. package/dist/locales/ru.json +4 -40
  63. package/dist/locales/sq.json +4 -40
  64. package/dist/locales/sv.json +4 -40
  65. package/dist/locales/tr.json +4 -40
  66. package/dist/locales/zh.json +4 -40
  67. package/dist/patterns/calendar/calendar-workspace.model.d.ts +59 -13
  68. package/dist/patterns/calendar/calendar.model.d.ts +18 -5
  69. package/dist/patterns/calendar/calendar.sheets.d.ts +10 -13
  70. package/dist/patterns/calendar/calendar.types.d.ts +79 -13
  71. package/dist/patterns/calendar/index.js +1 -1
  72. package/dist/tokens.css +1 -1
  73. package/package.json +1 -1
  74. package/dist/_chunks/calendar-workspace-CqVe4v5s.js +0 -7481
  75. package/dist/_chunks/folder-plus-CutOs4DP.js +0 -22
  76. package/dist/_chunks/signature-CpFNpsVK.js +0 -21
@@ -3989,6 +3989,8 @@
3989
3989
  "phone": "Telefon",
3990
3990
  "email": "E-posta",
3991
3991
  "city": "Şehir",
3992
+ "patientNotLoaded": "Hasta kaydı yüklenmedi",
3993
+ "patientPhoneUnknown": "Bu hasta için telefon numarası mevcut değil",
3992
3994
  "docked": "{{name}} için randevu ayrıntıları yan panelde açıldı",
3993
3995
  "remind": "Hatırlatma gönder",
3994
3996
  "remindWhatsApp": "WhatsApp",
@@ -4017,8 +4019,6 @@
4017
4019
  "anamnesisTitle": "Anamnez dikkat gerektiriyor",
4018
4020
  "anamnesisHighlighted": "İşaretli yanıtlar: {{n}}",
4019
4021
  "anamnesisExpired": "Süresi dolmuş yanıtlar: {{n}}",
4020
- "anamnesisRenew": "Yenile",
4021
- "anamnesisRenewToast": "Anamnez yenileme — yalnızca demo, hiçbir şey gönderilmez",
4022
4022
  "sectionSigning": "İmzalanacak belgeler",
4023
4023
  "signingToSignOne": "İmzalanacak 1 belge",
4024
4024
  "signingToSignMany": "İmzalanacak {{n}} belge",
@@ -4034,8 +4034,6 @@
4034
4034
  "sectionBooking": "Çevrimiçi rezervasyon",
4035
4035
  "bookedAt": "Rezervasyon tarihi",
4036
4036
  "bookingNote": "Hasta notu",
4037
- "joinTelehealth": "Görüntülü muayeneye katıl",
4038
- "joinTelehealthToast": "Görüntülü muayene oturumu {{code}} — yalnızca demo, arama başlatılmaz",
4039
4037
  "historyAction": "Değişiklik geçmişi",
4040
4038
  "historyTitle": "Değişiklik geçmişi",
4041
4039
  "historyBack": "Ayrıntılara dön",
@@ -4059,12 +4057,8 @@
4059
4057
  "move": "Taşı…",
4060
4058
  "copy": "Kopyala…",
4061
4059
  "signingOnDevice": "Bu cihazda…",
4062
- "aesEnable": "Gelişmiş e-imzayı etkinleştir",
4063
- "aesToast": "Gelişmiş e-imza kurulumunu açar. Bu demonun parçası değil.",
4064
4060
  "paidOnline": "Çevrimiçi ödendi",
4065
4061
  "toCollect": "Tahsil edilecek",
4066
- "pauUpsell": "Ödemeleri otomatikleştir",
4067
- "pauToast": "Ödeme otomasyonunu açar. Bu demonun parçası değil.",
4068
4062
  "address": "Adres",
4069
4063
  "mapsLink": "Google Maps'te aç",
4070
4064
  "bookingPhone": "Rezervasyon telefonu",
@@ -4252,15 +4246,6 @@
4252
4246
  "duplicateAppointmentOnly": "Yalnızca randevu",
4253
4247
  "duplicateWithTreatments": "Randevu ve tedaviler",
4254
4248
  "cancel": "İptal",
4255
- "createDocument": "Belge oluştur",
4256
- "createBill": "Fatura oluştur",
4257
- "createBillNoOperator": "Önce bir operatör atayın",
4258
- "createFolder": "Yeni klasör",
4259
- "createFromTemplate": "Şablondan belge",
4260
- "createEmptyDocument": "Boş belge",
4261
- "createIdDocument": "Kimlik belgesi",
4262
- "createWebCamera": "Web kamerası",
4263
- "createDocumentToast": "{{item}} — yalnızca demo, hiçbir şey oluşturulmaz",
4264
4249
  "branch": "Branş",
4265
4250
  "devices": "Tıbbi cihazlar",
4266
4251
  "signModeSms": "SMS ile iste",
@@ -4286,10 +4271,6 @@
4286
4271
  "carePlanCleanup": "Tedavi planındaki tedaviler",
4287
4272
  "carePlanRemove": "Tedaviyi tedavi planından kaldır",
4288
4273
  "carePlanKeep": "Tedaviyi tedavi planında tut",
4289
- "createBillConfirmTitle": "Fatura oluşturulsun mu?",
4290
- "createBillConfirmBody": "Bu randevuya bağlı her tedavi, atanan operatör tarafından yapıldı olarak işaretlenir, ardından fatura açılır.",
4291
- "createBillConfirm": "Devam et",
4292
- "createBillCancel": "İptal",
4293
4274
  "devicesRequired_one": "{{count}} cihaz gerektirir",
4294
4275
  "devicesRequired_many": "{{count}} cihaz gerektirir",
4295
4276
  "devicesRequired_other": "{{count}} cihaz gerektirir",
@@ -4370,9 +4351,7 @@
4370
4351
  "region": "Tedavi planı",
4371
4352
  "entriesToggle": "Tedavi satırları ({{count}})",
4372
4353
  "linkedToThis": "Bu randevuya bağlı",
4373
- "showOnCalendar": "Takvimde göster",
4374
- "openFull": "Planın tamamını aç",
4375
- "openFullToast": "Tedavi planının tamamı hasta dosyasında açılır — bu demonun parçası değil."
4354
+ "showOnCalendar": "Takvimde göster"
4376
4355
  },
4377
4356
  "backlog": {
4378
4357
  "tool": "Bekleyen işler",
@@ -4452,10 +4431,6 @@
4452
4431
  "chairs": "Koltuklar",
4453
4432
  "operators": "Operatörler",
4454
4433
  "resetFilters": "Filtreleri sıfırla",
4455
- "scheduler": "Planlayıcı",
4456
- "schedulerToast": "Planlayıcıyı açar — klinik çalışma saatleri ve operatör müsaitliği. Bu demonun parçası değil.",
4457
- "settings": "Takvim ayarları",
4458
- "settingsToast": "Takvim ayarları sayfasını açar. Bu demonun parçası değil.",
4459
4434
  "navigation": "Takvimde gezinme",
4460
4435
  "waitingListCount_one": "Bekleme listesi — {{count}} kayıt",
4461
4436
  "waitingListCount_many": "Bekleme listesi — {{count}} kayıt",
@@ -4513,9 +4488,7 @@
4513
4488
  "chairFull": "Tam ad",
4514
4489
  "chairShort": "İki harf",
4515
4490
  "mapsLink": "Randevu ayrıntılarında harita bağlantısı",
4516
- "windowPractice": "Klinik çalışma saatleri ({{from}}–{{to}})",
4517
- "tutorial": "Öğretici",
4518
- "tutorialToast": "Ajanda için Academy öğreticisini açar. Bu demonun parçası değil."
4491
+ "windowPractice": "Klinik çalışma saatleri ({{from}}–{{to}})"
4519
4492
  },
4520
4493
  "print": {
4521
4494
  "title": "Günü yazdır",
@@ -4529,9 +4502,6 @@
4529
4502
  "undo": "Geri al",
4530
4503
  "undone": "Süre eski haline getirildi"
4531
4504
  },
4532
- "dialogs": {
4533
- "carePlanToast": "Tedavi planını hasta dosyasında açar. Bu demonun parçası değil."
4534
- },
4535
4505
  "bookings": {
4536
4506
  "title": "Çevrimiçi rezervasyonlar",
4537
4507
  "intro": "Son otuz gün içinde yapılan ve hâlâ hasta ya da operatör bekleyen rezervasyonlar.",
@@ -4586,12 +4556,6 @@
4586
4556
  "readOnly": {
4587
4557
  "createBlocked": "Randevu oluşturma izniniz yok."
4588
4558
  },
4589
- "legacy": {
4590
- "patientFolder": "{{name}} adlı hastanın dosyasını açar. Bu demonun parçası değil.",
4591
- "saveAndReturn": "Kaydedildi. Platform, bağlantının geldiği tedavi planına geri dönerdi. Bu demonun parçası değil.",
4592
- "whatsapp": "Eski WhatsApp Snippets penceresini açar. Bu demonun parçası değil.",
4593
- "signOnDevice": "Eski e-imza penceresini açar — bu cihazda imzalama, imzalayan ve operatör ataması. Bu demonun parçası değil."
4594
- },
4595
4559
  "rail": {
4596
4560
  "appointments": "Randevular",
4597
4561
  "appointmentsTitle": "Yaklaşan randevular",
@@ -3989,6 +3989,8 @@
3989
3989
  "phone": "电话",
3990
3990
  "email": "邮箱",
3991
3991
  "city": "城市",
3992
+ "patientNotLoaded": "未加载患者信息",
3993
+ "patientPhoneUnknown": "无法获取该患者的电话号码",
3992
3994
  "docked": "{{name}} 的预约详情已在侧边面板中打开",
3993
3995
  "remind": "发送提醒",
3994
3996
  "remindWhatsApp": "WhatsApp",
@@ -4017,8 +4019,6 @@
4017
4019
  "anamnesisTitle": "病史需要关注",
4018
4020
  "anamnesisHighlighted": "重点标记的回答:{{n}}",
4019
4021
  "anamnesisExpired": "已过期回答:{{n}}",
4020
- "anamnesisRenew": "更新",
4021
- "anamnesisRenewToast": "病史更新——仅为演示,不会发送任何内容",
4022
4022
  "sectionSigning": "待签署文件",
4023
4023
  "signingToSignOne": "1 份文件待签署",
4024
4024
  "signingToSignMany": "{{n}} 份文件待签署",
@@ -4034,8 +4034,6 @@
4034
4034
  "sectionBooking": "在线预约",
4035
4035
  "bookedAt": "预约提交时间",
4036
4036
  "bookingNote": "患者留言",
4037
- "joinTelehealth": "加入远程问诊",
4038
- "joinTelehealthToast": "远程问诊会话 {{code}}——仅为演示,不会发起通话",
4039
4037
  "historyAction": "修改记录",
4040
4038
  "historyTitle": "修改记录",
4041
4039
  "historyBack": "返回详情",
@@ -4059,12 +4057,8 @@
4059
4057
  "move": "移动…",
4060
4058
  "copy": "复制…",
4061
4059
  "signingOnDevice": "在此设备上…",
4062
- "aesEnable": "启用高级电子签名",
4063
- "aesToast": "打开高级电子签名设置。不属于本演示内容。",
4064
4060
  "paidOnline": "已在线支付",
4065
4061
  "toCollect": "待收款",
4066
- "pauUpsell": "自动化收款",
4067
- "pauToast": "打开“自动化收款”。不属于本演示内容。",
4068
4062
  "address": "地址",
4069
4063
  "mapsLink": "在 Google 地图中打开",
4070
4064
  "bookingPhone": "预约电话",
@@ -4252,15 +4246,6 @@
4252
4246
  "duplicateAppointmentOnly": "仅预约",
4253
4247
  "duplicateWithTreatments": "预约及治疗项目",
4254
4248
  "cancel": "取消",
4255
- "createDocument": "创建文档",
4256
- "createBill": "创建发票",
4257
- "createBillNoOperator": "请先分配操作员",
4258
- "createFolder": "新建文件夹",
4259
- "createFromTemplate": "从模板创建文档",
4260
- "createEmptyDocument": "空白文档",
4261
- "createIdDocument": "身份证件",
4262
- "createWebCamera": "摄像头",
4263
- "createDocumentToast": "{{item}}——仅为演示,不会创建任何内容",
4264
4249
  "branch": "专科",
4265
4250
  "devices": "医疗设备",
4266
4251
  "signModeSms": "通过短信请求",
@@ -4286,10 +4271,6 @@
4286
4271
  "carePlanCleanup": "诊疗计划中的治疗项目",
4287
4272
  "carePlanRemove": "从诊疗计划中移除该治疗项目",
4288
4273
  "carePlanKeep": "在诊疗计划中保留该治疗项目",
4289
- "createBillConfirmTitle": "创建发票?",
4290
- "createBillConfirmBody": "与此预约关联的所有治疗项目将标记为由指定操作员完成,然后打开发票。",
4291
- "createBillConfirm": "继续",
4292
- "createBillCancel": "取消",
4293
4274
  "devicesRequired_one": "需要 {{count}} 台设备",
4294
4275
  "devicesRequired_many": "需要 {{count}} 台设备",
4295
4276
  "devicesRequired_other": "需要 {{count}} 台设备",
@@ -4370,9 +4351,7 @@
4370
4351
  "region": "诊疗计划",
4371
4352
  "entriesToggle": "治疗条目({{count}})",
4372
4353
  "linkedToThis": "已关联此预约",
4373
- "showOnCalendar": "在日历中显示",
4374
- "openFull": "打开完整计划",
4375
- "openFullToast": "完整的诊疗计划将在患者档案中打开——不属于本演示内容。"
4354
+ "showOnCalendar": "在日历中显示"
4376
4355
  },
4377
4356
  "backlog": {
4378
4357
  "tool": "待处理",
@@ -4452,10 +4431,6 @@
4452
4431
  "chairs": "诊椅",
4453
4432
  "operators": "操作员",
4454
4433
  "resetFilters": "重置筛选",
4455
- "scheduler": "排班",
4456
- "schedulerToast": "打开排班——诊所营业时间和操作员可用时间。不属于本演示内容。",
4457
- "settings": "日历设置",
4458
- "settingsToast": "打开日历设置页面。不属于本演示内容。",
4459
4434
  "navigation": "日历导航",
4460
4435
  "waitingListCount_one": "等候名单——{{count}} 个条目",
4461
4436
  "waitingListCount_many": "等候名单——{{count}} 个条目",
@@ -4513,9 +4488,7 @@
4513
4488
  "chairFull": "全名",
4514
4489
  "chairShort": "两字母缩写",
4515
4490
  "mapsLink": "在预约详情中显示地图链接",
4516
- "windowPractice": "诊所营业时间({{from}}–{{to}})",
4517
- "tutorial": "教程",
4518
- "tutorialToast": "打开 Academy 的日程教程。不属于本演示内容。"
4491
+ "windowPractice": "诊所营业时间({{from}}–{{to}})"
4519
4492
  },
4520
4493
  "print": {
4521
4494
  "title": "按日打印",
@@ -4529,9 +4502,6 @@
4529
4502
  "undo": "撤销",
4530
4503
  "undone": "时长已恢复"
4531
4504
  },
4532
- "dialogs": {
4533
- "carePlanToast": "在患者档案中打开诊疗计划。不属于本演示内容。"
4534
- },
4535
4505
  "bookings": {
4536
4506
  "title": "在线预约",
4537
4507
  "intro": "最近三十天内仍需分配患者或操作员的预约。",
@@ -4586,12 +4556,6 @@
4586
4556
  "readOnly": {
4587
4557
  "createBlocked": "您没有创建预约的权限。"
4588
4558
  },
4589
- "legacy": {
4590
- "patientFolder": "打开 {{name}} 的患者档案。不属于本演示内容。",
4591
- "saveAndReturn": "已保存。平台将返回到链接来源的诊疗计划。不属于本演示内容。",
4592
- "whatsapp": "打开旧版 WhatsApp Snippets 对话框。不属于本演示内容。",
4593
- "signOnDevice": "打开旧版电子签名对话框——在此设备上签名、签署人及操作员分配。不属于本演示内容。"
4594
- },
4595
4559
  "rail": {
4596
4560
  "appointments": "预约",
4597
4561
  "appointmentsTitle": "即将到来的预约",
@@ -10,7 +10,7 @@
10
10
  import type { AppointmentItem } from '../../components/appointment-card';
11
11
  import type { CalendarResource } from '../../components/calendar';
12
12
  import type { CalendarData } from './calendar.data';
13
- import type { CalendarPatient, CalendarWaitingEntry } from './calendar.types';
13
+ import { type CalendarPatient, type CalendarWaitingEntry, type PatientChannelState, type PatientRef } from './calendar.types';
14
14
  import { type CalendarRow, type DisplaySettings, type EditorDraft, type EditorPrefill, type WaitingQuickView } from './calendar.model';
15
15
  export declare const WORKSPACE_TOOL: {
16
16
  readonly appointments: "appointments";
@@ -186,14 +186,36 @@ export declare function slotConflicts(rows: readonly CalendarRow[], slot: {
186
186
  export declare function devicesForCares(cares: readonly {
187
187
  careId?: string;
188
188
  }[] | undefined, devicesByCare: Readonly<Record<string, readonly string[]>>): string[];
189
- /** Which sign channels a patient can take a request on. */
190
- export declare function signChannelsFor(patient: CalendarPatient | undefined): {
191
- sms: boolean;
192
- email: boolean;
189
+ /**
190
+ * Which sign / notify channels a patient can take a request on — as the
191
+ * FOUR-state `PatientChannelState`, not a boolean.
192
+ *
193
+ * A boolean here was the bug: it folded "the record says the practice
194
+ * holds no number" together with "we were never told", and every caller
195
+ * then printed the first as the second ("No SMS-enabled number on
196
+ * file") for a patient the host had simply supplied without a `phone`.
197
+ * Callers now read the state: `channelReady` seeds a control ON,
198
+ * `channelOfferable` decides whether to disable it at all, and
199
+ * `channelReasonKey` gives a reason ONLY in the states that have one.
200
+ */
201
+ export declare function signChannelStates(ref: PatientRef): {
202
+ sms: PatientChannelState;
203
+ email: PatientChannelState;
193
204
  };
194
205
  /** The platform's default: SMS when the patient can take one, else
195
- * email, else nothing. */
196
- export declare function defaultSignMode(patient: CalendarPatient | undefined): RequiredDocsSignMode;
206
+ * email, else nothing. "Can take one" is `ready` alone — a channel we
207
+ * know nothing about is not a channel to send on by default. */
208
+ export declare function defaultSignMode(ref: PatientRef): RequiredDocsSignMode;
209
+ /** The patient's address as one line — the map link's search text, and
210
+ * the link's own label. Empty when the host supplied no address at all,
211
+ * which is the caller's signal to leave the map row out rather than
212
+ * offer a search for nothing. */
213
+ export declare function patientAddressLine(patient: CalendarPatient): string;
214
+ /** The map link's own LABEL — street and city, the pair the popover has
215
+ * always printed. The postcode belongs in the search query, not in the
216
+ * visible text, so widening `patientAddressLine` for the URL must not
217
+ * drag the label along with it. */
218
+ export declare function patientAddressLabel(patient: CalendarPatient): string;
197
219
  /** Google Maps search for the patient's address — the popover's map link. */
198
220
  export declare function patientMapsUrl(patient: CalendarPatient): string;
199
221
  /** A CREATE mode armed by a deep link (`createParameters`) or the
@@ -291,10 +313,22 @@ export declare function upcomingAppointmentRows(rows: CalendarRow[], bounds: {
291
313
  startMs: number;
292
314
  endMs: number;
293
315
  }): CalendarRow[];
294
- /** One agenda row as the kit timeline's item — identity, allocation and
295
- * care lines; the row id stays the event id so a click maps straight
296
- * back onto the grid. */
297
- export declare function upcomingAppointmentItem(row: CalendarRow, privacy: boolean, data: CalendarData): AppointmentItem;
316
+ /**
317
+ * One agenda row as the kit timeline's item — identity, allocation and
318
+ * care lines; the row id stays the event id so a click maps straight
319
+ * back onto the grid.
320
+ *
321
+ * The card prints its own "no patient assigned" whenever `patient` is
322
+ * absent, so absence here has to mean exactly that: the appointment
323
+ * carries NO patient id. A row that carries one but whose record the
324
+ * host could not resolve still names its patient — from the record, from
325
+ * the title the row already carries, and only then from
326
+ * `unresolvedPatientLabel`, which must say the record was not loaded and
327
+ * never that nobody is booked.
328
+ */
329
+ export declare function upcomingAppointmentItem(row: CalendarRow, privacy: boolean, data: CalendarData,
330
+ /** Localised name-of-last-resort for an unresolvable patient id. */
331
+ unresolvedPatientLabel: string): AppointmentItem;
298
332
  /** How far back the platform's booking query looks, on `createdAt`. */
299
333
  export declare const ONLINE_BOOKINGS_WINDOW_DAYS = 30;
300
334
  /**
@@ -355,16 +389,28 @@ export declare function waitingFiltersActiveCount(filters: WaitingListFilters):
355
389
  */
356
390
  export interface WaitingListRowView {
357
391
  entry: CalendarWaitingEntry;
358
- /** Platform `patientId` / `patientName` / `patientPhoneNumber`. */
392
+ /** The entry's OWN patient, id and record together. `assigned` is what
393
+ * decides whether this entry has a patient — the record may simply
394
+ * not have loaded. */
395
+ patientRef: PatientRef;
396
+ /** Platform `patientId` / `patientName` / `patientPhoneNumber` — the
397
+ * record alone, when the host could load it. */
359
398
  patient?: CalendarPatient;
360
399
  /** The linked appointment, live from the grid's rows. */
361
400
  appointment?: CalendarRow;
362
- /** Platform `appointmentPatientId` — the linked appointment's patient. */
401
+ /** Platform `appointmentPatientId` — the linked appointment's patient,
402
+ * id and record together. */
403
+ appointmentPatientRef: PatientRef;
404
+ /** The linked appointment's patient record, when it loaded. */
363
405
  appointmentPatient?: CalendarPatient;
364
406
  /** Platform `operatorName`. */
365
407
  operatorTitle?: string;
366
408
  /** Platform `appointmentName` — the linked appointment's care line. */
367
409
  appointmentName?: string;
410
+ /** Someone is booked on this row — the entry's own patient or the
411
+ * linked appointment's. Keyed on the IDS: a record we could not load
412
+ * is still a patient. */
413
+ patientAssigned: boolean;
368
414
  noConnection: boolean;
369
415
  }
370
416
  export declare function waitingListRowView(entry: CalendarWaitingEntry, rows: readonly CalendarRow[], data: CalendarData): WaitingListRowView;
@@ -12,7 +12,7 @@ import type { TFunction } from 'i18next';
12
12
  import { ThumbsUp } from 'lucide-react';
13
13
  import { type CalendarEvent, type CalendarEventStatus, type CalendarResource } from '../../components/calendar';
14
14
  import type { CalendarData } from './calendar.data';
15
- import { type CareDescriptionMode, type ColorAssociation, type CalendarBaseEvent, type CalendarBookingContact, type CalendarCareEntry, type CalendarCareLink, type CalendarClosure, type CalendarDayHours, type CalendarHistoryEntry, type CalendarPatient, type CalendarPhoneNumber, type CalendarSignDocument, type CalendarWaitingEntry } from './calendar.types';
15
+ import { type CareDescriptionMode, type ColorAssociation, type CalendarBaseEvent, type CalendarBookingContact, type CalendarCareEntry, type CalendarCareLink, type CalendarClosure, type CalendarDayHours, type CalendarHistoryEntry, type CalendarPatient, type CalendarPhoneNumber, type CalendarSignDocument, type CalendarWaitingEntry, type PatientRef } from './calendar.types';
16
16
  export declare const STATUS_UI_KEY: Record<CalendarEventStatus, string>;
17
17
  export interface CalendarRow {
18
18
  event: CalendarEvent;
@@ -47,6 +47,11 @@ export interface PendingMove {
47
47
  revert?: () => void;
48
48
  }
49
49
  export declare function movesSilently(event: CalendarEvent): boolean;
50
+ /** The reference for one patient id — the record when the host could
51
+ * answer, and always the id itself. */
52
+ export declare function patientRefById(id: string | number | null | undefined, data: CalendarData): PatientRef;
53
+ /** The reference for the patient an appointment carries. */
54
+ export declare function eventPatientRef(event: CalendarEvent, data: CalendarData): PatientRef;
50
55
  export declare function isPendingBooking(event: CalendarEvent): boolean;
51
56
  export declare function selectPendingBookings(rows: CalendarRow[]): CalendarRow[];
52
57
  /**
@@ -420,7 +425,11 @@ export declare function buildBacklog(args: {
420
425
  }, data: CalendarData): BacklogItem[];
421
426
  /** Per-type counts — the strip's segment badges. */
422
427
  export declare function backlogCounts(items: readonly BacklogItem[]): Record<BacklogType, number>;
423
- /** The patient behind a row (bookings have none — a typed name only). */
428
+ /** The patient behind a row (bookings have none — a typed name only),
429
+ * as the reference: `assigned` says whether anyone is booked at all,
430
+ * which is what a "no patient" label may key on — never the record. */
431
+ export declare function backlogPatientRef(item: BacklogItem, data: CalendarData): PatientRef;
432
+ /** The record behind a queue row, when the host could load it. */
424
433
  export declare function backlogPatient(item: BacklogItem, data: CalendarData): CalendarPatient | undefined;
425
434
  /** The row's headline — patient name, the booker's typed name, or the
426
435
  * free-text hold. */
@@ -448,9 +457,9 @@ export declare function waitingEntryInQuickView(entry: CalendarWaitingEntry, vie
448
457
  export declare function filterWaitingQuickView(items: readonly BacklogItem[], view: WaitingQuickView, data: CalendarData): BacklogItem[];
449
458
  /**
450
459
  * Process an online booking: the editor opens for THAT event with the
451
- * booker's typed details, a matching record pre-selected, and BOTH the
452
- * patient and the operator marked required — the two things the booking
453
- * needs before it leaves the queue.
460
+ * booker's typed details, a patient pre-selected — the id the booking
461
+ * already carries, or a typed-name match — and BOTH the patient and the
462
+ * operator marked required, the two things it needs to leave the queue.
454
463
  */
455
464
  export declare function processBookingPrefill(row: CalendarRow, data: CalendarData): EditorPrefill;
456
465
  /** Assign an operator: the editor opens for the event with the operator
@@ -621,6 +630,10 @@ export interface PrintSheetInput {
621
630
  /** A date-only start (all-day rows) is already a local day; anything
622
631
  * else parses as the wall clock the fixtures and the editor write. */
623
632
  export declare function parseEventDate(value: string | Date): Date;
633
+ /** The title privacy mode shows. TOTAL in the masked branch: a host
634
+ * that supplies an EMPTY `privacyModeTitle` gets the bullets, never a
635
+ * blank and never a fallback that would leak what we do or do not hold
636
+ * on the one surface whose job is to say nothing. */
624
637
  export declare function maskedTitle(event: CalendarEvent, privacy: boolean): string;
625
638
  export declare function printRowOf(row: CalendarRow, privacy: boolean, data: CalendarData): PrintRow;
626
639
  export declare function byStart(a: PrintRow, b: PrintRow): number;
@@ -24,7 +24,7 @@
24
24
  import { type ReactNode } from 'react';
25
25
  import { type CalendarEvent } from '../../components/calendar';
26
26
  import { type NotesPanelNote, type NotesPanelProps, type NotesPanelSubmission } from '../../components/notes-panel';
27
- import { type ColorAssociation, type CalendarCarePlan, type CalendarAnamnesisAnswer, type CalendarOperatorGroup, type CalendarPatient, type CalendarWaitingEntry, type CalendarHistoryEntry, type CalendarSignChannel } from './calendar.types';
27
+ import { type ColorAssociation, type CalendarCarePlan, type CalendarAnamnesisAnswer, type CalendarOperatorGroup, type CalendarPatient, type CalendarWaitingEntry, type CalendarHistoryEntry, type CalendarSignChannel, type PatientRef } from './calendar.types';
28
28
  import { type CalendarRow, type DisplaySettings, type EditorPrefill, type EditorDraft, type DraftSlot, type SlotPatch, type BacklogFilter, type BacklogItem, type WaitingEntryDraft, type CalendarFreeSlot, type PrintDaySection, type FindSlotsSeed, type AvailabilityContext } from './calendar.model';
29
29
  import { type EditorDraftExtras, type DeleteOptions } from './calendar-workspace.model';
30
30
  export declare function TaskDetailsPanel({ row, locale, }: {
@@ -107,8 +107,6 @@ export interface EditorPlatformOptions {
107
107
  recurringScope?: boolean;
108
108
  /** Price-list recurrence parent — ask about the care-plan lines on delete. */
109
109
  carePlanCleanup?: boolean;
110
- /** Create bill asks before executing the linked treatments. */
111
- confirmCreateBill?: boolean;
112
110
  /** Operator options for the select — defaults to the shared active
113
111
  * cast. A host whose appointment is held by an operator the practice
114
112
  * has since DISABLED passes the wider list, so the name still shows
@@ -206,9 +204,11 @@ export declare function AppointmentEditorPanel({ prefill, onSave, onDelete, onDu
206
204
  export declare function IndicatorChips({ event }: {
207
205
  event: CalendarEvent;
208
206
  }): import("react/jsx-runtime").JSX.Element | null;
209
- export declare function AppointmentIdentity({ row, patient, showAge, onOpenPatient, anamnesisAnswers, }: {
207
+ export declare function AppointmentIdentity({ row, patientRef, showAge, onOpenPatient, anamnesisAnswers, }: {
210
208
  row: CalendarRow;
211
- patient?: CalendarPatient;
209
+ /** Who this appointment is for: the id it carries and the record, when
210
+ * the host could resolve it. */
211
+ patientRef: PatientRef;
212
212
  /** Append the platform popover's "(NN anni)" to the name (audit C15). */
213
213
  showAge?: boolean;
214
214
  /** Set = the name becomes the platform's patient-folder link. */
@@ -217,8 +217,7 @@ export declare function AppointmentIdentity({ row, patient, showAge, onOpenPatie
217
217
  * details dialog lists them, the popover only counts (audit C16). */
218
218
  anamnesisAnswers?: readonly CalendarAnamnesisAnswer[];
219
219
  }): import("react/jsx-runtime").JSX.Element;
220
- export declare function SendReminderGroup({ patient, onWhatsApp, channels: allowed, }: {
221
- patient: CalendarPatient;
220
+ export declare function SendReminderGroup({ onWhatsApp, channels: allowed, }: {
222
221
  /** When set, the WhatsApp segment bridges to the legacy Snippets
223
222
  * island instead of the demo-fake send. */
224
223
  onWhatsApp?: () => void;
@@ -229,14 +228,10 @@ export declare function SendReminderGroup({ patient, onWhatsApp, channels: allow
229
228
  /** The platform popover facts the Final State never modelled — every
230
229
  * field optional, so a host that passes nothing sees the extras as before. */
231
230
  export interface ExtrasPlatformOptions {
232
- /** The patient has an advanced e-signature setup (else "Enable AES"). */
233
- aesEnabled?: boolean;
234
231
  /** Deposit paid online when booking (Stripe). */
235
232
  paidOnlineAmount?: number;
236
233
  /** The patient's outstanding balance. */
237
234
  toCollectAmount?: number;
238
- /** Payment automation is off and the upsell toggle is on. */
239
- pauUpsell?: boolean;
240
235
  /** The user's map-link setting (the display cog). */
241
236
  mapsLink?: boolean;
242
237
  /** The phone typed on the booking site, when it differs from the record. */
@@ -323,8 +318,10 @@ export declare function WaitingListPanel({ entries, rows, locale, onPlaceWaiting
323
318
  onRemoveWaiting: (entry: CalendarWaitingEntry) => void;
324
319
  /** Add entry, and a row's edit → the host's entry sub-view. */
325
320
  onOpenEntryForm: (entry?: CalendarWaitingEntry) => void;
326
- /** The patient-folder hop the platform's name link makes. */
327
- onOpenPatient: (patient: CalendarPatient) => void;
321
+ /** The patient-folder hop the platform's name link makes. Unset — a
322
+ * host with no folder to route to — renders the name as plain text
323
+ * rather than a link that cannot arrive anywhere. */
324
+ onOpenPatient?: (patient: CalendarPatient) => void;
328
325
  /** The platform's `focusAppointmentId` deep link — steer and ring. */
329
326
  onOpenAppointment: (eventId: string) => void;
330
327
  }): import("react/jsx-runtime").JSX.Element;
@@ -30,25 +30,36 @@ export interface CalendarAnamnesisAnswer {
30
30
  answer?: string;
31
31
  interviewIso: string;
32
32
  }
33
+ /**
34
+ * A patient as the HOST knows them. Only the identity — `id` and `name` —
35
+ * is required: a host whose appointment feed carries a patient id and a
36
+ * display name and nothing else supplies exactly those two, and every
37
+ * reader below treats each remaining field as "the host did not tell us".
38
+ *
39
+ * The rule for a reader: never render a row, chip or label that asserts a
40
+ * value for a field the host omitted — an empty fiscal code printed under
41
+ * a "Fiscal code" label is a claim about the record, not a blank. Omit the
42
+ * row; where every row of a section would go, omit the section.
43
+ */
33
44
  export interface CalendarPatient {
34
45
  id: string;
35
46
  name: string;
36
- dobIso: string;
37
- phone: string;
38
- email: string;
47
+ dobIso?: string;
48
+ phone?: string;
49
+ email?: string;
39
50
  smsEnabled?: boolean;
40
51
  emailEnabled?: boolean;
41
- city: string;
52
+ city?: string;
42
53
  /** Optional profile photo — Avatar falls back to the initials circle. */
43
54
  avatarSrc?: string;
44
- sex: 'f' | 'm';
45
- fiscalCode: string;
46
- address: string;
47
- province: string;
48
- postalCode: string;
49
- patientSinceIso: string;
50
- lastVisitIso: string;
51
- priceList: string;
55
+ sex?: 'f' | 'm';
56
+ fiscalCode?: string;
57
+ address?: string;
58
+ province?: string;
59
+ postalCode?: string;
60
+ patientSinceIso?: string;
61
+ lastVisitIso?: string;
62
+ priceList?: string;
52
63
  discountPct?: number;
53
64
  unpaidAmount?: number;
54
65
  allergies?: string;
@@ -390,8 +401,63 @@ export type CalendarHistoryEntry = {
390
401
  kind: 'deleted';
391
402
  });
392
403
  /** Every labelled phone number — the single `phone` is the mobile when a
393
- * patient carries no explicit list (platform prints each label: number). */
404
+ * patient carries no explicit list (platform prints each label: number).
405
+ * A patient the host supplied without either has no numbers to print,
406
+ * which is not the same as one labelled blank: the list comes back empty
407
+ * and the caller omits the block. */
394
408
  export declare function patientPhones(patient: CalendarPatient): CalendarPhoneNumber[];
409
+ /**
410
+ * A patient as the calendar can see them at one point: the id a row,
411
+ * an event or a waiting entry carries, plus the record if the host's
412
+ * `patientById` could answer.
413
+ */
414
+ export interface PatientRef {
415
+ /** The id, as a string. `''` — and ONLY `''` — means nobody is booked. */
416
+ readonly id: string;
417
+ /** The record, when the host could resolve the id. */
418
+ readonly record?: CalendarPatient;
419
+ /** Someone is booked here, resolved or not. The existence test. */
420
+ readonly assigned: boolean;
421
+ /** Someone is booked and their record did not load — state A. */
422
+ readonly unresolved: boolean;
423
+ }
424
+ /** A patient id as a string, `''` when there is none. A host id of `0`
425
+ * IS an id, so the test is `!= null` and never truthiness. */
426
+ export declare function patientIdOf(id: string | number | null | undefined): string;
427
+ /** Pair the id a row carries with whatever the host made of it. */
428
+ export declare function patientRefOf(id: string | number | null | undefined, record: CalendarPatient | undefined): PatientRef;
429
+ /** What to CALL this patient: the record's name, else the title the row
430
+ * already carries, else the caller's localised "record not loaded".
431
+ * Never blank — a blank name renders an initials-less avatar — and
432
+ * never the "no patient assigned" of an unbooked slot. */
433
+ export declare function patientRefName(ref: PatientRef, rowTitle: string | undefined, notLoadedLabel: string): string;
434
+ /** Why a notify / signing channel is or is not usable for a patient. */
435
+ export type PatientChannelState =
436
+ /** On file, and the patient takes messages there. */
437
+ 'ready'
438
+ /** On file, and the patient opted this channel out. */
439
+ | 'optedOut'
440
+ /** The record loaded and really carries nothing here — state C, the
441
+ * only state in which "none on file" may be said. */
442
+ | 'none'
443
+ /** We were not told: no record at all, or the record omits the field
444
+ * — states A and B. Says nothing about what the practice holds. */
445
+ | 'unknown';
446
+ /** The state of one channel for one patient reference. */
447
+ export declare function patientChannelState(ref: PatientRef, channel: 'sms' | 'email'): PatientChannelState;
448
+ /** A channel the kit can hand a destination to right now — the test for
449
+ * seeding a checkbox ON, or for defaulting a sign mode to it. */
450
+ export declare function channelReady(state: PatientChannelState): boolean;
451
+ /** A channel the kit must leave OFFERED. `unknown` belongs here: the
452
+ * host may well succeed on send, and disabling the control would claim
453
+ * the practice holds nothing — a claim about a record we never saw. */
454
+ export declare function channelOfferable(state: PatientChannelState): boolean;
455
+ /** The reason a channel is not offered — `null` when it IS offered, so
456
+ * a caller never has to invent a string for a state it cannot reach. */
457
+ export declare function channelReasonKey(state: PatientChannelState, keys: {
458
+ optedOut: string;
459
+ none: string;
460
+ }): string | null;
395
461
  /** Practice-level toggles the platform gates the editor and popover on. */
396
462
  export interface CalendarPracticeFeatures {
397
463
  /** `FIND_FREE_SLOTS_BY_CARE` — devices per care, the device line. */
@@ -1,4 +1,4 @@
1
- import { C as s, a as r, b as E, D as P, c as t, S, V as A, W as C, d, i as o, m as D, r as i, u as n, e as W, f as _ } from "../../_chunks/calendar-workspace-CqVe4v5s.js";
1
+ import { C as s, a as r, b as E, D as P, c as t, S, V as A, W as C, d, i as o, m as D, r as i, u as n, e as W, f as _ } from "../../_chunks/calendar-workspace-Ca0n_r1v.js";
2
2
  export {
3
3
  s as CALENDAR_PREFERENCE_KEYS,
4
4
  r as CalendarDataProvider,