@pisell/materials 1.8.38 → 1.8.41

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 (758) hide show
  1. package/build/lowcode/assets-daily.json +11 -11
  2. package/build/lowcode/assets-dev.json +2 -2
  3. package/build/lowcode/assets-prod.json +11 -11
  4. package/build/lowcode/meta.js +3 -3
  5. package/build/lowcode/render/default/view.css +1 -1
  6. package/build/lowcode/render/default/view.js +216 -51
  7. package/build/lowcode/view.css +1 -1
  8. package/build/lowcode/view.js +216 -51
  9. package/es/components/Pagination/index.js +9 -43
  10. package/es/components/PisellCards/components/GraphicTextCard/docs/GraphicTextCard.$tab-dev.md +5 -2
  11. package/es/components/PisellCards/components/GraphicTextCard/docs/GraphicTextCard.$tab-test.md +169 -171
  12. package/es/components/PisellCards/components/GraphicTextCard/docs/GraphicTextCard.md +87 -27
  13. package/es/components/PisellCards/components/GraphicTextCard/types.d.ts +18 -7
  14. package/es/components/PisellCards/components/TextCard/TextCard.js +2 -3
  15. package/es/components/PisellCards/components/TextCard/components/BadgeWrapper.js +20 -6
  16. package/es/components/PisellCards/components/TextCard/components/TextContent.js +3 -1
  17. package/es/components/PisellCards/components/TextCard/docs/TextCard.$tab-dev.md +36 -5
  18. package/es/components/PisellCards/components/TextCard/docs/TextCard.$tab-test.md +2434 -258
  19. package/es/components/PisellCards/components/TextCard/docs/TextCard.md +78 -13
  20. package/es/components/PisellCards/index.d.ts +3 -0
  21. package/es/components/PisellCards/index.js +3 -1
  22. package/es/components/PisellContactBrief/PisellContactBrief.d.ts +34 -0
  23. package/es/components/PisellContactBrief/PisellContactBrief.js +156 -0
  24. package/es/components/PisellContactBrief/PisellContactBrief.less +192 -0
  25. package/es/components/PisellContactBrief/components/ContactFormModal.js +140 -0
  26. package/es/components/PisellContactBrief/docs/PisellContactBrief.$tab-design.md +109 -0
  27. package/es/components/PisellContactBrief/docs/PisellContactBrief.$tab-dev.md +106 -0
  28. package/es/components/PisellContactBrief/docs/PisellContactBrief.$tab-test.md +125 -0
  29. package/es/components/PisellContactBrief/docs/PisellContactBrief.md +129 -0
  30. package/es/components/PisellContactBrief/index.d.ts +2 -0
  31. package/es/components/PisellContactBrief/locales.js +57 -0
  32. package/es/components/PisellContactBrief/types.d.ts +86 -0
  33. package/es/components/PisellLayouts/index.d.ts +1 -1
  34. package/es/components/PisellProcedure/components/ProcedureHeader.js +1 -1
  35. package/es/components/PisellTabbar/PisellTabbar.js +1 -1
  36. package/es/components/PisellTabbar/template/Template1/PisellTabbar.js +1 -1
  37. package/es/components/Template/[ComponentName].less +1 -0
  38. package/es/components/Template/docs/[ComponentName].$tab-design.md +7 -0
  39. package/es/components/Template/docs/[ComponentName].$tab-dev.md +1137 -0
  40. package/es/components/Template/docs/[ComponentName].$tab-test.md +7 -0
  41. package/es/components/Template/docs/[ComponentName].md +510 -0
  42. package/es/components/appVersionControl/index.js +3 -2
  43. package/es/components/dataSourceComponents/dataSourceForm/BaseForm.js +4 -4
  44. package/es/components/dataSourceComponents/dataSourceForm/formItem.js +1 -1
  45. package/es/components/dataSourceComponents/dataSourceForm/index.js +1 -1
  46. package/es/components/dataSourceComponents/dataSourceForm/submitButton/index.js +3 -3
  47. package/es/components/dataSourceComponents/dataSourceForm/utils.js +3 -3
  48. package/es/components/dataSourceComponents/dataSourceShow/dataSourceTypography/index.js +1 -1
  49. package/es/components/dataSourceComponents/dataSourceSubForm/index.js +1 -1
  50. package/es/components/dataSourceComponents/dataSourceTable/BaseTable.js +2 -2
  51. package/es/components/dataSourceComponents/dataSourceTable/filter/index.js +1 -1
  52. package/es/components/dataSourceComponents/dataSourceTable/hooks/useTableProps.js +3 -2
  53. package/es/components/dataSourceComponents/dataSourceTable/type.d.ts +1 -0
  54. package/es/components/dataSourceComponents/dataSourceWrapper/BaseWrapper.js +1 -1
  55. package/es/components/dataSourceComponents/fields/DatePicker/WithMode.js +4 -0
  56. package/es/components/dataSourceComponents/fields/IconSelect/WithMode.js +1 -1
  57. package/es/components/dataSourceComponents/fields/Input/WithMode.js +1 -1
  58. package/es/components/dataSourceComponents/fields/Input.Phone/serve.js +4 -1
  59. package/es/components/dataSourceComponents/fields/Radio/WithMode.js +1 -1
  60. package/es/components/dataSourceComponents/fields/TimePicker/WithMode.js +1 -1
  61. package/es/components/dataSourceComponents/hooks/useActions.js +1 -1
  62. package/es/components/dataSourceComponents/provider/dataSource/DataSourceProvider.js +1 -1
  63. package/es/components/drag-sort-tree/index.d.ts +1 -0
  64. package/es/components/drag-sort-tree/index.js +0 -1
  65. package/es/components/drawer/index.js +7 -6
  66. package/es/components/filter/components/FilterItem/index.js +1 -3
  67. package/es/components/filter/components/QuickFilter/index.js +2 -3
  68. package/es/components/hardwareErrorTip/errorCard/index.d.ts +25 -0
  69. package/es/components/hardwareErrorTip/errorCard/index.js +68 -0
  70. package/es/components/hardwareErrorTip/errorCard/index.less +137 -0
  71. package/es/components/hardwareErrorTip/errorTipStatistics/index.d.ts +10 -0
  72. package/es/components/hardwareErrorTip/errorTipStatistics/index.js +31 -0
  73. package/es/components/hardwareErrorTip/errorTipStatistics/index.less +34 -0
  74. package/es/components/hardwareErrorTip/index.d.ts +20 -0
  75. package/es/components/hardwareErrorTip/index.js +151 -0
  76. package/es/components/hardwareErrorTip/index.less +95 -0
  77. package/es/components/hardwareErrorTip/logCard/index.d.ts +25 -0
  78. package/es/components/hardwareErrorTip/logCard/index.js +72 -0
  79. package/es/components/hardwareErrorTip/logCard/index.less +121 -0
  80. package/es/components/hardwareErrorTip/readme.md +309 -0
  81. package/es/components/hardwareErrorTip/types.js +54 -0
  82. package/es/components/iconfont/index.js +1 -1
  83. package/es/components/login-and-register/index.js +4 -5
  84. package/es/components/page/index.js +1 -1
  85. package/es/components/pisellActionPanel/PisellActionPanel.d.ts +24 -0
  86. package/es/components/pisellActionPanel/PisellActionPanel.js +68 -0
  87. package/es/components/pisellActionPanel/PisellActionPanel.less +69 -0
  88. package/es/components/pisellActionPanel/docs/pisellActionPanel.$tab-design.md +148 -0
  89. package/es/components/pisellActionPanel/docs/pisellActionPanel.$tab-dev.md +53 -0
  90. package/es/components/pisellActionPanel/docs/pisellActionPanel.$tab-test.md +64 -0
  91. package/es/components/pisellActionPanel/docs/pisellActionPanel.md +160 -0
  92. package/es/components/pisellActionPanel/index.d.ts +2 -0
  93. package/es/components/pisellActionPanel/types.d.ts +87 -0
  94. package/es/components/pisellAppCard/PisellAppCard.js +1 -1
  95. package/es/components/pisellBaseCard/PisellBaseCard.d.ts +20 -0
  96. package/es/components/pisellBaseCard/PisellBaseCard.js +73 -0
  97. package/es/components/pisellBaseCard/PisellBaseCard.less +25 -0
  98. package/es/components/pisellBaseCard/docs/pisellBaseCard.$tab-design.md +144 -0
  99. package/es/components/pisellBaseCard/docs/pisellBaseCard.$tab-dev.md +92 -0
  100. package/es/components/pisellBaseCard/docs/pisellBaseCard.$tab-test.md +86 -0
  101. package/es/components/pisellBaseCard/docs/pisellBaseCard.md +165 -0
  102. package/es/components/pisellBaseCard/index.d.ts +2 -0
  103. package/es/components/pisellBaseCard/types.d.ts +49 -0
  104. package/es/components/pisellCardList/index.js +1 -1
  105. package/es/components/pisellCurrency/PisellCurrency.js +13 -6
  106. package/es/components/pisellCurrency/PisellCurrency.less +0 -123
  107. package/es/components/pisellCustomerBrief/PisellCustomerBrief.d.ts +57 -0
  108. package/es/components/pisellCustomerBrief/PisellCustomerBrief.js +92 -0
  109. package/es/components/pisellCustomerBrief/PisellCustomerBrief.less +8 -0
  110. package/es/components/pisellCustomerBrief/docs/pisellCustomerBrief.$tab-design.md +115 -0
  111. package/es/components/pisellCustomerBrief/docs/pisellCustomerBrief.$tab-dev.md +73 -0
  112. package/es/components/pisellCustomerBrief/docs/pisellCustomerBrief.$tab-test.md +66 -0
  113. package/es/components/pisellCustomerBrief/docs/pisellCustomerBrief.md +132 -0
  114. package/es/components/pisellCustomerBrief/index.d.ts +2 -0
  115. package/es/components/pisellCustomerBrief/types.d.ts +86 -0
  116. package/es/components/pisellDataSourceContainer/components/Pagination/index.js +3 -9
  117. package/es/components/pisellDataSourceContainer/docs/PisellDataSourceContainer.md +189 -240
  118. package/es/components/pisellDataSourceContainer/type.d.ts +1 -1
  119. package/es/components/pisellDateTimeDisplay/docs/pisellDateTimeDisplay.md +556 -556
  120. package/es/components/pisellEmail/PisellEmail.js +13 -6
  121. package/es/components/pisellEmail/PisellEmail.less +0 -92
  122. package/es/components/pisellEmpty/index.d.ts +1 -1
  123. package/es/components/pisellEntityCard/PisellEntityCard.d.ts +47 -0
  124. package/es/components/pisellEntityCard/PisellEntityCard.js +315 -0
  125. package/es/components/pisellEntityCard/PisellEntityCard.less +362 -0
  126. package/es/components/pisellEntityCard/docs/pisellEntityCard.$tab-design.md +209 -0
  127. package/es/components/pisellEntityCard/docs/pisellEntityCard.$tab-dev.md +82 -0
  128. package/es/components/pisellEntityCard/docs/pisellEntityCard.$tab-test.md +122 -0
  129. package/es/components/pisellEntityCard/docs/pisellEntityCard.md +176 -0
  130. package/es/components/pisellEntityCard/index.d.ts +2 -0
  131. package/es/components/pisellEntityCard/types.d.ts +148 -0
  132. package/es/components/pisellExport/PisellExport.d.ts +11 -0
  133. package/es/components/pisellExport/PisellExport.js +44 -0
  134. package/es/components/pisellExport/PisellExport.less +141 -0
  135. package/es/components/pisellExport/docs/pisellExport.$tab-design.md +116 -0
  136. package/es/components/pisellExport/docs/pisellExport.$tab-dev.md +132 -0
  137. package/es/components/pisellExport/docs/pisellExport.$tab-test.md +61 -0
  138. package/es/components/pisellExport/docs/pisellExport.md +162 -0
  139. package/es/components/pisellExport/index.d.ts +2 -0
  140. package/es/components/pisellExport/types.d.ts +67 -0
  141. package/es/components/pisellFilter/docs/PisellFilter.md +2 -2
  142. package/es/components/pisellFind/docs/pisellFind.md +2 -2
  143. package/es/components/pisellFloorMapLayout/PisellFloorMapLayout.d.ts +1 -2
  144. package/es/components/pisellFloorMapLayout/PisellFloorMapLayout.js +51 -230
  145. package/es/components/pisellFloorMapLayout/PisellFloorMapLayout.less +0 -22
  146. package/es/components/pisellFloorMapLayout/components/EditableItemLayer.js +2 -3
  147. package/es/components/pisellFloorMapLayout/components/FigmaTableCard.d.ts +2 -2
  148. package/es/components/pisellFloorMapLayout/components/FigmaTableCard.js +74 -209
  149. package/es/components/pisellFloorMapLayout/components/FloorMapEditPanel.js +5 -40
  150. package/es/components/pisellFloorMapLayout/components/FloorMapEditTopBar.js +12 -131
  151. package/es/components/pisellFloorMapLayout/components/FloorMapEditTopBar.less +1 -9
  152. package/es/components/pisellFloorMapLayout/components/FloorMapToolbar.js +3 -24
  153. package/es/components/pisellFloorMapLayout/components/FloorMapToolbar.less +4 -97
  154. package/es/components/pisellFloorMapLayout/components/ItemLayer.js +9 -29
  155. package/es/components/pisellFloorMapLayout/components/ItemLayer.less +2 -19
  156. package/es/components/pisellFloorMapLayout/components/ViewControls.js +65 -119
  157. package/es/components/pisellFloorMapLayout/components/ViewControls.less +44 -208
  158. package/es/components/pisellFloorMapLayout/components/ViewControlsWithZoom.js +0 -4
  159. package/es/components/pisellFloorMapLayout/context/mergeFloorMapLayoutContext.js +1 -3
  160. package/es/components/pisellFloorMapLayout/docs/pisellFloorMapLayout.md +194 -559
  161. package/es/components/pisellFloorMapLayout/hooks/useFloorMapEditState.js +16 -82
  162. package/es/components/pisellFloorMapLayout/hooks/useFloorMapTransformMetrics.js +36 -369
  163. package/es/components/pisellFloorMapLayout/index.d.ts +0 -1
  164. package/es/components/pisellFloorMapLayout/locales-ja.js +1 -21
  165. package/es/components/pisellFloorMapLayout/locales-pt.js +1 -21
  166. package/es/components/pisellFloorMapLayout/locales.js +3 -63
  167. package/es/components/pisellFloorMapLayout/types.d.ts +9 -70
  168. package/es/components/pisellGoodPassCard/index.less +0 -1
  169. package/es/components/pisellGridPro/GridView/docs/GridView.md +48 -47
  170. package/es/components/pisellGridPro/ToolBar/docs/ToolBar.$tab-dev.md +2 -4
  171. package/es/components/pisellGridPro/ToolBar/docs/ToolBar.md +81 -95
  172. package/es/components/pisellGridPro/ToolBar/index.less +4 -5
  173. package/es/components/pisellGridPro/docs/PisellGridPro.md +262 -173
  174. package/es/components/pisellHierarchicalSummaryList/docs/pisellHierarchicalSummaryList.$tab-dev.md +6 -3
  175. package/es/components/pisellHierarchicalSummaryList/docs/pisellHierarchicalSummaryList.$tab-test.md +4 -3
  176. package/es/components/pisellHierarchicalSummaryList/docs/pisellHierarchicalSummaryList.md +2 -1
  177. package/es/components/pisellImport/PisellImport.d.ts +11 -0
  178. package/es/components/pisellImport/PisellImport.js +81 -0
  179. package/es/components/pisellImport/PisellImport.less +141 -0
  180. package/es/components/pisellImport/docs/pisellImport.$tab-design.md +121 -0
  181. package/es/components/pisellImport/docs/pisellImport.$tab-dev.md +137 -0
  182. package/es/components/pisellImport/docs/pisellImport.$tab-test.md +69 -0
  183. package/es/components/pisellImport/docs/pisellImport.md +174 -0
  184. package/es/components/pisellImport/index.d.ts +2 -0
  185. package/es/components/pisellImport/types.d.ts +89 -0
  186. package/es/components/pisellLongText/PisellLongText.js +13 -6
  187. package/es/components/pisellLongText/PisellLongText.less +0 -67
  188. package/es/components/pisellLookup/PisellLookup.less +1 -1
  189. package/es/components/pisellLookup/components/LookupTrigger.js +8 -6
  190. package/es/components/pisellLookup/docs/pisellLookup.md +1 -1
  191. package/es/components/pisellMultipleSelect/PisellMultipleSelect.js +7 -5
  192. package/es/components/pisellMultipleSelect/PisellMultipleSelect.less +18 -139
  193. package/es/components/pisellMultipleSelect/components/EditView.js +1 -0
  194. package/es/components/pisellNavigationMenu/PisellNavigationMenu.js +4 -0
  195. package/es/components/pisellNumber/PisellNumber.js +13 -6
  196. package/es/components/pisellNumber/PisellNumber.less +0 -103
  197. package/es/components/pisellPhone/PisellPhone.js +13 -6
  198. package/es/components/pisellPhone/PisellPhone.less +0 -119
  199. package/es/components/pisellPhone/components/EditView.js +37 -19
  200. package/es/components/pisellPhone/constants/countryCodes.js +26 -25
  201. package/es/components/pisellPhone/types.d.ts +2 -2
  202. package/es/components/pisellPhone/utils/countryCodeHelper.js +2 -2
  203. package/es/components/pisellQuickFilter/{docs → doc}/PisellQuickFilter.md +1 -1
  204. package/es/components/pisellRating/PisellRating.js +5 -3
  205. package/es/components/pisellRecordBoard/PisellRecordBoard.js +10 -26
  206. package/es/components/pisellRecordBoard/README.md +0 -12
  207. package/es/components/pisellRecordBoard/docs/PisellRecordBoard.md +70 -716
  208. package/es/components/pisellRecordBoard/docs/ShellFrame.md +44 -62
  209. package/es/components/pisellRecordBoard/index.d.ts +1 -7
  210. package/es/components/pisellRecordBoard/index.js +0 -4
  211. package/es/components/pisellRecordBoard/layouts/GridLayout/Grid.js +9 -147
  212. package/es/components/pisellRecordBoard/layouts/GridLayout/Grid.less +0 -31
  213. package/es/components/pisellRecordBoard/shellFrame/Calendar/BookingCalendarDemo.js +3811 -0
  214. package/es/components/pisellRecordBoard/shellFrame/Calendar/PisellRecordBoardCalendarView.d.ts +1 -5
  215. package/es/components/pisellRecordBoard/shellFrame/Calendar/PisellRecordBoardCalendarView.js +8 -10
  216. package/es/components/pisellRecordBoard/shellFrame/Calendar/calendarPersistGuard.d.ts +1 -1
  217. package/es/components/pisellRecordBoard/shellFrame/ColumnSetting/index.js +1 -2
  218. package/es/components/pisellRecordBoard/shellFrame/Pagination/index.js +1 -7
  219. package/es/components/pisellRecordBoard/shellFrame/Search/index.js +1 -1
  220. package/es/components/pisellRecordBoard/shellFrame/ShellBodyMetaContext.d.ts +1 -5
  221. package/es/components/pisellRecordBoard/shellFrame/ToolBar/index.js +65 -143
  222. package/es/components/pisellRecordBoard/shellFrame/ToolBar/recordBoardToolbar.less +13 -181
  223. package/es/components/pisellRecordBoard/shellFrame/ToolBarQuickFilter/index.js +2 -10
  224. package/es/components/pisellRecordBoard/shellFrame/index.d.ts +2 -9
  225. package/es/components/pisellRecordBoard/shellFrame/index.js +19 -73
  226. package/es/components/pisellRecordBoard/types.d.ts +8 -374
  227. package/es/components/pisellRecordBoard/utils/partitionShellFrameChildren.js +0 -16
  228. package/es/components/pisellReservationSchedule/PisellReservationSchedule.js +15 -67
  229. package/es/components/pisellReservationSchedule/PisellReservationSchedule.less +0 -23
  230. package/es/components/pisellReservationSchedule/locales.js +3 -21
  231. package/es/components/pisellReservationSchedule/types.d.ts +0 -5
  232. package/es/components/pisellReservationScheduleBand/PisellReservationScheduleBand.js +2 -2
  233. package/es/components/pisellReservationScheduleBand/PisellReservationScheduleBand.less +4 -37
  234. package/es/components/pisellReservationScheduleBand/types.d.ts +0 -4
  235. package/es/components/pisellShellFrame/PisellShellFrame.js +2 -2
  236. package/es/components/pisellShellFrame/PisellShellFrame.less +2 -18
  237. package/es/components/pisellShellFrame/types.d.ts +0 -6
  238. package/es/components/pisellSingleLineText/PisellSingleLineText.js +21 -14
  239. package/es/components/pisellSingleLineText/PisellSingleLineText.less +0 -143
  240. package/es/components/pisellSingleLineText/docs/pisellSingleLineText.md +256 -256
  241. package/es/components/pisellSingleSelect/PisellSingleSelect.js +7 -4
  242. package/es/components/pisellSingleSelect/PisellSingleSelect.less +5 -106
  243. package/es/components/pisellSingleSelect/docs/pisellSingleSelect.md +525 -428
  244. package/es/components/pisellSort/docs/PisellSort.md +67 -131
  245. package/es/components/pisellStatisticList/index.js +1 -0
  246. package/es/components/pisellTimeNavigator/PisellTimeNavigator.js +37 -151
  247. package/es/components/pisellTimeNavigator/PisellTimeNavigator.less +13 -126
  248. package/es/components/pisellTimeNavigator/components/CursorLayer.js +2 -2
  249. package/es/components/pisellTimeNavigator/components/GestureLayer.js +3 -12
  250. package/es/components/pisellTimeNavigator/docs/pisellTimeNavigator.$tab-dev.md +42 -26
  251. package/es/components/pisellTimeNavigator/docs/pisellTimeNavigator.$tab-test.md +5 -5
  252. package/es/components/pisellTimeNavigator/index.d.ts +1 -1
  253. package/es/components/pisellTimeNavigator/utils/index.d.ts +3 -9
  254. package/es/components/pisellTimeNavigator/utils/index.js +6 -15
  255. package/es/components/pisellTimeRangeDisplay/docs/pisellTimeRangeDisplay.md +227 -226
  256. package/es/components/pisellUrl/PisellUrl.js +13 -6
  257. package/es/components/pisellWalletPassCard/index.js +11 -5
  258. package/es/components/productCard/cartSkuCard/components/basicInfo/index.js +4 -65
  259. package/es/components/productCard/cartSkuCard/components/basicInfo/index.less +1 -80
  260. package/es/components/productCard/cartSkuCard/components/holders/index.js +1 -1
  261. package/es/components/productCard/cartSkuCard/components/packages/index.js +9 -24
  262. package/es/components/productCard/cartSkuCard/components/specs/index.js +7 -22
  263. package/es/components/productCard/cartSkuCard/components/specs/index.less +0 -11
  264. package/es/components/productCard/cartSkuCard/components/timeRange/index.js +1 -2
  265. package/es/components/productCard/cartSkuCard/index.js +8 -68
  266. package/es/components/productCard/cartSkuCard/locales.js +5 -40
  267. package/es/components/productCard/components/Header/Actions/index.less +15 -0
  268. package/es/components/productCard/components/Header/DeleteButton/index.js +2 -2
  269. package/es/components/productCard/components/Header/DeleteButton/index.less +2 -1
  270. package/es/components/productCard/components/Header/EditButton/index.js +1 -2
  271. package/es/components/productCard/components/Header/index.less +1 -1
  272. package/es/components/productCard/components/Time/components/SelectHolder/index.js +3 -2
  273. package/es/components/productCard/components/Time/components/SelectHolderModal/index.js +1 -1
  274. package/es/components/productCard/components/Time/components/SelectHolderMultiple/index.js +2 -2
  275. package/es/components/productCard/components/Time/components/SelectResource/index.js +6 -3
  276. package/es/components/productCard/components/Time/index.js +3 -2
  277. package/es/components/productCard/status.js +0 -3
  278. package/es/components/productCard/types.d.ts +0 -10
  279. package/es/components/productCard/utils.js +1 -1
  280. package/es/components/select-time/index.js +0 -1
  281. package/es/components/table/Actions/component/ExportImport/index.js +3 -4
  282. package/es/components/table/Actions/component/GallerySetting/index.js +10 -9
  283. package/es/components/table/Actions/component/ViewMode/index.js +4 -3
  284. package/es/components/table/Actions/index.js +1 -1
  285. package/es/components/table/BasicTable/index.js +4 -3
  286. package/es/components/table/Gallery/components/GalleryItem/components/Title/index.less +1 -1
  287. package/es/components/table/Gallery/components/GalleryItem/index.js +12 -4
  288. package/es/components/table/Gallery/components/GalleryItem/index.less +1 -0
  289. package/es/components/table/Gallery/index.js +11 -3
  290. package/es/components/table/Table/fields/text/Show/index.js +1 -1
  291. package/es/components/table/Table/index.js +2 -1
  292. package/es/components/table/Table/tableConfig/header/index.js +1 -1
  293. package/es/components/table/Table/utils.js +5 -1
  294. package/es/components/table/hooks/useTableSetting.js +3 -0
  295. package/es/components/table/hooks/useTransDataSource.js +4 -3
  296. package/es/components/table/index.js +1 -1
  297. package/es/components/tabs/index.less +1 -1
  298. package/es/components/translation/index.d.ts +1 -0
  299. package/es/components/translation/index.js +36 -10
  300. package/es/components/translation/index.less +12 -0
  301. package/es/components/versionModal/index.d.ts +1 -0
  302. package/es/components/versionModal/index.js +2 -2
  303. package/es/components/versionSelect/index.js +1 -1
  304. package/es/components/virtual-keyboard/Amount/index.js +2 -1
  305. package/es/components/virtual-keyboard/Amount/types.d.ts +1 -0
  306. package/es/index.d.ts +105 -94
  307. package/es/index.js +92 -90
  308. package/es/locales/en-US.js +69 -191
  309. package/es/locales/ja.js +12 -192
  310. package/es/locales/pt.js +12 -192
  311. package/es/locales/zh-CN.js +63 -185
  312. package/es/locales/zh-TW.js +68 -190
  313. package/es/pisell-materials.tw.css +1 -2414
  314. package/es/tailwind-input.css +1 -3
  315. package/es/theme/pisell-components.js +76 -0
  316. package/lib/components/Pagination/index.js +8 -42
  317. package/lib/components/PisellCards/components/GraphicTextCard/docs/GraphicTextCard.$tab-dev.md +5 -2
  318. package/lib/components/PisellCards/components/GraphicTextCard/docs/GraphicTextCard.$tab-test.md +169 -171
  319. package/lib/components/PisellCards/components/GraphicTextCard/docs/GraphicTextCard.md +87 -27
  320. package/lib/components/PisellCards/components/GraphicTextCard/types.d.ts +18 -7
  321. package/lib/components/PisellCards/components/TextCard/TextCard.js +2 -3
  322. package/lib/components/PisellCards/components/TextCard/components/BadgeWrapper.js +20 -6
  323. package/lib/components/PisellCards/components/TextCard/components/TextContent.js +3 -1
  324. package/lib/components/PisellCards/components/TextCard/docs/TextCard.$tab-dev.md +36 -5
  325. package/lib/components/PisellCards/components/TextCard/docs/TextCard.$tab-test.md +2434 -258
  326. package/lib/components/PisellCards/components/TextCard/docs/TextCard.md +78 -13
  327. package/lib/components/PisellCards/index.d.ts +3 -0
  328. package/lib/components/PisellCards/index.js +3 -1
  329. package/lib/components/PisellContactBrief/PisellContactBrief.d.ts +34 -0
  330. package/lib/components/PisellContactBrief/PisellContactBrief.js +158 -0
  331. package/lib/components/PisellContactBrief/PisellContactBrief.less +192 -0
  332. package/lib/components/PisellContactBrief/components/ContactFormModal.js +139 -0
  333. package/lib/components/PisellContactBrief/docs/PisellContactBrief.$tab-design.md +109 -0
  334. package/lib/components/PisellContactBrief/docs/PisellContactBrief.$tab-dev.md +106 -0
  335. package/lib/components/PisellContactBrief/docs/PisellContactBrief.$tab-test.md +125 -0
  336. package/lib/components/PisellContactBrief/docs/PisellContactBrief.md +129 -0
  337. package/lib/components/PisellContactBrief/index.d.ts +2 -0
  338. package/lib/components/PisellContactBrief/locales.js +57 -0
  339. package/lib/components/PisellContactBrief/types.d.ts +86 -0
  340. package/lib/components/PisellLayouts/index.d.ts +1 -1
  341. package/lib/components/PisellProcedure/components/ProcedureHeader.js +1 -1
  342. package/lib/components/PisellTabbar/PisellTabbar.js +6 -6
  343. package/lib/components/PisellTabbar/template/Template1/PisellTabbar.js +6 -6
  344. package/lib/components/Template/[ComponentName].less +1 -0
  345. package/lib/components/Template/docs/[ComponentName].$tab-design.md +7 -0
  346. package/lib/components/Template/docs/[ComponentName].$tab-dev.md +1137 -0
  347. package/lib/components/Template/docs/[ComponentName].$tab-test.md +7 -0
  348. package/lib/components/Template/docs/[ComponentName].md +510 -0
  349. package/lib/components/appVersionControl/index.js +12 -11
  350. package/lib/components/dataSourceComponents/dataSourceForm/BaseForm.js +6 -6
  351. package/lib/components/dataSourceComponents/dataSourceForm/formItem.js +1 -1
  352. package/lib/components/dataSourceComponents/dataSourceForm/index.js +1 -1
  353. package/lib/components/dataSourceComponents/dataSourceForm/submitButton/index.js +3 -3
  354. package/lib/components/dataSourceComponents/dataSourceForm/utils.js +3 -3
  355. package/lib/components/dataSourceComponents/dataSourceShow/dataSourceTypography/index.js +1 -1
  356. package/lib/components/dataSourceComponents/dataSourceSubForm/index.js +1 -1
  357. package/lib/components/dataSourceComponents/dataSourceTable/BaseTable.js +2 -2
  358. package/lib/components/dataSourceComponents/dataSourceTable/filter/index.js +1 -1
  359. package/lib/components/dataSourceComponents/dataSourceTable/hooks/useTableProps.js +3 -2
  360. package/lib/components/dataSourceComponents/dataSourceTable/type.d.ts +1 -0
  361. package/lib/components/dataSourceComponents/dataSourceWrapper/BaseWrapper.js +1 -1
  362. package/lib/components/dataSourceComponents/fields/DatePicker/WithMode.js +4 -0
  363. package/lib/components/dataSourceComponents/fields/IconSelect/WithMode.js +1 -1
  364. package/lib/components/dataSourceComponents/fields/Input/WithMode.js +1 -1
  365. package/lib/components/dataSourceComponents/fields/Input.Phone/serve.js +4 -1
  366. package/lib/components/dataSourceComponents/fields/Radio/WithMode.js +1 -1
  367. package/lib/components/dataSourceComponents/fields/TimePicker/WithMode.js +4 -4
  368. package/lib/components/dataSourceComponents/hooks/useActions.js +1 -1
  369. package/lib/components/dataSourceComponents/provider/dataSource/DataSourceProvider.js +1 -1
  370. package/lib/components/drag-sort-tree/index.d.ts +1 -0
  371. package/lib/components/drag-sort-tree/index.js +0 -1
  372. package/lib/components/drawer/index.js +7 -6
  373. package/lib/components/filter/components/FilterItem/index.js +1 -3
  374. package/lib/components/filter/components/QuickFilter/index.js +2 -3
  375. package/lib/components/hardwareErrorTip/errorCard/index.d.ts +25 -0
  376. package/lib/components/hardwareErrorTip/errorCard/index.js +71 -0
  377. package/lib/components/hardwareErrorTip/errorCard/index.less +137 -0
  378. package/lib/components/hardwareErrorTip/errorTipStatistics/index.d.ts +10 -0
  379. package/lib/components/hardwareErrorTip/errorTipStatistics/index.js +34 -0
  380. package/lib/components/hardwareErrorTip/errorTipStatistics/index.less +34 -0
  381. package/lib/components/hardwareErrorTip/index.d.ts +20 -0
  382. package/lib/components/hardwareErrorTip/index.js +153 -0
  383. package/lib/components/hardwareErrorTip/index.less +95 -0
  384. package/lib/components/hardwareErrorTip/logCard/index.d.ts +25 -0
  385. package/lib/components/hardwareErrorTip/logCard/index.js +75 -0
  386. package/lib/components/hardwareErrorTip/logCard/index.less +121 -0
  387. package/lib/components/hardwareErrorTip/readme.md +309 -0
  388. package/lib/components/hardwareErrorTip/types.js +57 -0
  389. package/lib/components/iconfont/index.js +1 -1
  390. package/lib/components/login-and-register/index.js +4 -5
  391. package/lib/components/page/index.js +1 -1
  392. package/lib/components/pisellActionPanel/PisellActionPanel.d.ts +24 -0
  393. package/lib/components/pisellActionPanel/PisellActionPanel.js +71 -0
  394. package/lib/components/pisellActionPanel/PisellActionPanel.less +69 -0
  395. package/lib/components/pisellActionPanel/docs/pisellActionPanel.$tab-design.md +148 -0
  396. package/lib/components/pisellActionPanel/docs/pisellActionPanel.$tab-dev.md +53 -0
  397. package/lib/components/pisellActionPanel/docs/pisellActionPanel.$tab-test.md +64 -0
  398. package/lib/components/pisellActionPanel/docs/pisellActionPanel.md +160 -0
  399. package/lib/components/pisellActionPanel/index.d.ts +2 -0
  400. package/lib/components/pisellActionPanel/types.d.ts +87 -0
  401. package/lib/components/pisellAppCard/PisellAppCard.js +7 -7
  402. package/lib/components/pisellBaseCard/PisellBaseCard.d.ts +20 -0
  403. package/lib/components/pisellBaseCard/PisellBaseCard.js +76 -0
  404. package/lib/components/pisellBaseCard/PisellBaseCard.less +25 -0
  405. package/lib/components/pisellBaseCard/docs/pisellBaseCard.$tab-design.md +144 -0
  406. package/lib/components/pisellBaseCard/docs/pisellBaseCard.$tab-dev.md +92 -0
  407. package/lib/components/pisellBaseCard/docs/pisellBaseCard.$tab-test.md +86 -0
  408. package/lib/components/pisellBaseCard/docs/pisellBaseCard.md +165 -0
  409. package/lib/components/pisellBaseCard/index.d.ts +2 -0
  410. package/lib/components/pisellBaseCard/types.d.ts +49 -0
  411. package/lib/components/pisellCardList/index.js +6 -6
  412. package/lib/components/pisellCurrency/PisellCurrency.js +13 -6
  413. package/lib/components/pisellCurrency/PisellCurrency.less +0 -123
  414. package/lib/components/pisellCustomerBrief/PisellCustomerBrief.d.ts +57 -0
  415. package/lib/components/pisellCustomerBrief/PisellCustomerBrief.js +94 -0
  416. package/lib/components/pisellCustomerBrief/PisellCustomerBrief.less +8 -0
  417. package/lib/components/pisellCustomerBrief/docs/pisellCustomerBrief.$tab-design.md +115 -0
  418. package/lib/components/pisellCustomerBrief/docs/pisellCustomerBrief.$tab-dev.md +73 -0
  419. package/lib/components/pisellCustomerBrief/docs/pisellCustomerBrief.$tab-test.md +66 -0
  420. package/lib/components/pisellCustomerBrief/docs/pisellCustomerBrief.md +132 -0
  421. package/lib/components/pisellCustomerBrief/index.d.ts +2 -0
  422. package/lib/components/pisellCustomerBrief/types.d.ts +86 -0
  423. package/lib/components/pisellDataSourceContainer/components/Pagination/index.js +3 -9
  424. package/lib/components/pisellDataSourceContainer/docs/PisellDataSourceContainer.md +189 -240
  425. package/lib/components/pisellDataSourceContainer/type.d.ts +1 -1
  426. package/lib/components/pisellDateTimeDisplay/docs/pisellDateTimeDisplay.md +556 -556
  427. package/lib/components/pisellEmail/PisellEmail.js +13 -6
  428. package/lib/components/pisellEmail/PisellEmail.less +0 -92
  429. package/lib/components/pisellEmpty/index.d.ts +1 -1
  430. package/lib/components/pisellEntityCard/PisellEntityCard.d.ts +47 -0
  431. package/lib/components/pisellEntityCard/PisellEntityCard.js +318 -0
  432. package/lib/components/pisellEntityCard/PisellEntityCard.less +362 -0
  433. package/lib/components/pisellEntityCard/docs/pisellEntityCard.$tab-design.md +209 -0
  434. package/lib/components/pisellEntityCard/docs/pisellEntityCard.$tab-dev.md +82 -0
  435. package/lib/components/pisellEntityCard/docs/pisellEntityCard.$tab-test.md +122 -0
  436. package/lib/components/pisellEntityCard/docs/pisellEntityCard.md +176 -0
  437. package/lib/components/pisellEntityCard/index.d.ts +2 -0
  438. package/lib/components/pisellEntityCard/types.d.ts +148 -0
  439. package/lib/components/pisellExport/PisellExport.d.ts +11 -0
  440. package/lib/components/pisellExport/PisellExport.js +47 -0
  441. package/lib/components/pisellExport/PisellExport.less +141 -0
  442. package/lib/components/pisellExport/docs/pisellExport.$tab-design.md +116 -0
  443. package/lib/components/pisellExport/docs/pisellExport.$tab-dev.md +132 -0
  444. package/lib/components/pisellExport/docs/pisellExport.$tab-test.md +61 -0
  445. package/lib/components/pisellExport/docs/pisellExport.md +162 -0
  446. package/lib/components/pisellExport/index.d.ts +2 -0
  447. package/lib/components/pisellExport/types.d.ts +67 -0
  448. package/lib/components/pisellFilter/docs/PisellFilter.md +2 -2
  449. package/lib/components/pisellFind/docs/pisellFind.md +2 -2
  450. package/lib/components/pisellFloorMapLayout/PisellFloorMapLayout.d.ts +1 -2
  451. package/lib/components/pisellFloorMapLayout/PisellFloorMapLayout.js +51 -230
  452. package/lib/components/pisellFloorMapLayout/PisellFloorMapLayout.less +0 -22
  453. package/lib/components/pisellFloorMapLayout/components/EditableItemLayer.js +2 -3
  454. package/lib/components/pisellFloorMapLayout/components/FigmaTableCard.d.ts +2 -2
  455. package/lib/components/pisellFloorMapLayout/components/FigmaTableCard.js +74 -209
  456. package/lib/components/pisellFloorMapLayout/components/FloorMapEditPanel.js +4 -39
  457. package/lib/components/pisellFloorMapLayout/components/FloorMapEditTopBar.js +11 -130
  458. package/lib/components/pisellFloorMapLayout/components/FloorMapEditTopBar.less +1 -9
  459. package/lib/components/pisellFloorMapLayout/components/FloorMapToolbar.js +2 -23
  460. package/lib/components/pisellFloorMapLayout/components/FloorMapToolbar.less +4 -97
  461. package/lib/components/pisellFloorMapLayout/components/ItemLayer.js +9 -29
  462. package/lib/components/pisellFloorMapLayout/components/ItemLayer.less +2 -19
  463. package/lib/components/pisellFloorMapLayout/components/ViewControls.js +64 -118
  464. package/lib/components/pisellFloorMapLayout/components/ViewControls.less +44 -208
  465. package/lib/components/pisellFloorMapLayout/components/ViewControlsWithZoom.js +0 -4
  466. package/lib/components/pisellFloorMapLayout/context/mergeFloorMapLayoutContext.js +1 -3
  467. package/lib/components/pisellFloorMapLayout/docs/pisellFloorMapLayout.md +194 -559
  468. package/lib/components/pisellFloorMapLayout/hooks/useFloorMapEditState.js +16 -82
  469. package/lib/components/pisellFloorMapLayout/hooks/useFloorMapTransformMetrics.js +36 -369
  470. package/lib/components/pisellFloorMapLayout/index.d.ts +0 -1
  471. package/lib/components/pisellFloorMapLayout/locales-ja.js +1 -21
  472. package/lib/components/pisellFloorMapLayout/locales-pt.js +1 -21
  473. package/lib/components/pisellFloorMapLayout/locales.js +3 -63
  474. package/lib/components/pisellFloorMapLayout/types.d.ts +9 -70
  475. package/lib/components/pisellGoodPassCard/index.less +0 -1
  476. package/lib/components/pisellGridPro/GridView/docs/GridView.md +48 -47
  477. package/lib/components/pisellGridPro/ToolBar/docs/ToolBar.$tab-dev.md +2 -4
  478. package/lib/components/pisellGridPro/ToolBar/docs/ToolBar.md +81 -95
  479. package/lib/components/pisellGridPro/ToolBar/index.less +4 -5
  480. package/lib/components/pisellGridPro/docs/PisellGridPro.md +262 -173
  481. package/lib/components/pisellHierarchicalSummaryList/docs/pisellHierarchicalSummaryList.$tab-dev.md +6 -3
  482. package/lib/components/pisellHierarchicalSummaryList/docs/pisellHierarchicalSummaryList.$tab-test.md +4 -3
  483. package/lib/components/pisellHierarchicalSummaryList/docs/pisellHierarchicalSummaryList.md +2 -1
  484. package/lib/components/pisellImport/PisellImport.d.ts +11 -0
  485. package/lib/components/pisellImport/PisellImport.js +84 -0
  486. package/lib/components/pisellImport/PisellImport.less +141 -0
  487. package/lib/components/pisellImport/docs/pisellImport.$tab-design.md +121 -0
  488. package/lib/components/pisellImport/docs/pisellImport.$tab-dev.md +137 -0
  489. package/lib/components/pisellImport/docs/pisellImport.$tab-test.md +69 -0
  490. package/lib/components/pisellImport/docs/pisellImport.md +174 -0
  491. package/lib/components/pisellImport/index.d.ts +2 -0
  492. package/lib/components/pisellImport/types.d.ts +89 -0
  493. package/lib/components/pisellLongText/PisellLongText.js +13 -6
  494. package/lib/components/pisellLongText/PisellLongText.less +0 -67
  495. package/lib/components/pisellLookup/PisellLookup.less +1 -1
  496. package/lib/components/pisellLookup/components/LookupTrigger.js +8 -6
  497. package/lib/components/pisellLookup/docs/pisellLookup.md +1 -1
  498. package/lib/components/pisellMultipleSelect/PisellMultipleSelect.js +6 -4
  499. package/lib/components/pisellMultipleSelect/PisellMultipleSelect.less +18 -139
  500. package/lib/components/pisellMultipleSelect/components/EditView.js +1 -0
  501. package/lib/components/pisellNavigationMenu/PisellNavigationMenu.js +4 -0
  502. package/lib/components/pisellNumber/PisellNumber.js +13 -6
  503. package/lib/components/pisellNumber/PisellNumber.less +0 -103
  504. package/lib/components/pisellPhone/PisellPhone.js +13 -6
  505. package/lib/components/pisellPhone/PisellPhone.less +0 -119
  506. package/lib/components/pisellPhone/components/EditView.js +37 -19
  507. package/lib/components/pisellPhone/constants/countryCodes.js +26 -25
  508. package/lib/components/pisellPhone/types.d.ts +2 -2
  509. package/lib/components/pisellPhone/utils/countryCodeHelper.js +2 -2
  510. package/lib/components/pisellQuickFilter/{docs → doc}/PisellQuickFilter.md +1 -1
  511. package/lib/components/pisellRating/PisellRating.js +4 -2
  512. package/lib/components/pisellRecordBoard/PisellRecordBoard.js +10 -26
  513. package/lib/components/pisellRecordBoard/README.md +0 -12
  514. package/lib/components/pisellRecordBoard/docs/PisellRecordBoard.md +70 -716
  515. package/lib/components/pisellRecordBoard/docs/ShellFrame.md +44 -62
  516. package/lib/components/pisellRecordBoard/index.d.ts +1 -7
  517. package/lib/components/pisellRecordBoard/index.js +0 -4
  518. package/lib/components/pisellRecordBoard/layouts/GridLayout/Grid.js +8 -146
  519. package/lib/components/pisellRecordBoard/layouts/GridLayout/Grid.less +0 -31
  520. package/lib/components/pisellRecordBoard/shellFrame/Calendar/BookingCalendarDemo.js +3813 -0
  521. package/lib/components/pisellRecordBoard/shellFrame/Calendar/PisellRecordBoardCalendarView.d.ts +1 -5
  522. package/lib/components/pisellRecordBoard/shellFrame/Calendar/PisellRecordBoardCalendarView.js +8 -11
  523. package/lib/components/pisellRecordBoard/shellFrame/Calendar/calendarPersistGuard.d.ts +1 -1
  524. package/lib/components/pisellRecordBoard/shellFrame/ColumnSetting/index.js +1 -2
  525. package/lib/components/pisellRecordBoard/shellFrame/Pagination/index.js +1 -7
  526. package/lib/components/pisellRecordBoard/shellFrame/Search/index.js +1 -1
  527. package/lib/components/pisellRecordBoard/shellFrame/ShellBodyMetaContext.d.ts +1 -5
  528. package/lib/components/pisellRecordBoard/shellFrame/ToolBar/index.js +78 -156
  529. package/lib/components/pisellRecordBoard/shellFrame/ToolBar/recordBoardToolbar.less +13 -181
  530. package/lib/components/pisellRecordBoard/shellFrame/ToolBarQuickFilter/index.js +2 -10
  531. package/lib/components/pisellRecordBoard/shellFrame/index.d.ts +2 -9
  532. package/lib/components/pisellRecordBoard/shellFrame/index.js +19 -73
  533. package/lib/components/pisellRecordBoard/types.d.ts +8 -374
  534. package/lib/components/pisellRecordBoard/utils/partitionShellFrameChildren.js +0 -16
  535. package/lib/components/pisellReservationSchedule/PisellReservationSchedule.js +15 -67
  536. package/lib/components/pisellReservationSchedule/PisellReservationSchedule.less +0 -23
  537. package/lib/components/pisellReservationSchedule/locales.js +3 -21
  538. package/lib/components/pisellReservationSchedule/types.d.ts +0 -5
  539. package/lib/components/pisellReservationScheduleBand/PisellReservationScheduleBand.js +2 -2
  540. package/lib/components/pisellReservationScheduleBand/PisellReservationScheduleBand.less +4 -37
  541. package/lib/components/pisellReservationScheduleBand/types.d.ts +0 -4
  542. package/lib/components/pisellShellFrame/PisellShellFrame.js +2 -2
  543. package/lib/components/pisellShellFrame/PisellShellFrame.less +2 -18
  544. package/lib/components/pisellShellFrame/types.d.ts +0 -6
  545. package/lib/components/pisellSingleLineText/PisellSingleLineText.js +21 -14
  546. package/lib/components/pisellSingleLineText/PisellSingleLineText.less +0 -143
  547. package/lib/components/pisellSingleLineText/docs/pisellSingleLineText.md +256 -256
  548. package/lib/components/pisellSingleSelect/PisellSingleSelect.js +7 -4
  549. package/lib/components/pisellSingleSelect/PisellSingleSelect.less +5 -106
  550. package/lib/components/pisellSingleSelect/docs/pisellSingleSelect.md +525 -428
  551. package/lib/components/pisellSort/docs/PisellSort.md +67 -131
  552. package/lib/components/pisellStatisticList/index.js +1 -0
  553. package/lib/components/pisellTimeNavigator/PisellTimeNavigator.js +38 -152
  554. package/lib/components/pisellTimeNavigator/PisellTimeNavigator.less +13 -126
  555. package/lib/components/pisellTimeNavigator/components/CursorLayer.js +2 -2
  556. package/lib/components/pisellTimeNavigator/components/GestureLayer.js +3 -12
  557. package/lib/components/pisellTimeNavigator/docs/pisellTimeNavigator.$tab-dev.md +42 -26
  558. package/lib/components/pisellTimeNavigator/docs/pisellTimeNavigator.$tab-test.md +5 -5
  559. package/lib/components/pisellTimeNavigator/index.d.ts +1 -1
  560. package/lib/components/pisellTimeNavigator/utils/index.d.ts +3 -9
  561. package/lib/components/pisellTimeNavigator/utils/index.js +5 -16
  562. package/lib/components/pisellTimeRangeDisplay/docs/pisellTimeRangeDisplay.md +227 -226
  563. package/lib/components/pisellUrl/PisellUrl.js +13 -6
  564. package/lib/components/pisellWalletPassCard/index.js +11 -5
  565. package/lib/components/productCard/cartSkuCard/components/basicInfo/index.js +8 -69
  566. package/lib/components/productCard/cartSkuCard/components/basicInfo/index.less +1 -80
  567. package/lib/components/productCard/cartSkuCard/components/holders/index.js +1 -1
  568. package/lib/components/productCard/cartSkuCard/components/packages/index.js +11 -26
  569. package/lib/components/productCard/cartSkuCard/components/specs/index.js +8 -23
  570. package/lib/components/productCard/cartSkuCard/components/specs/index.less +0 -11
  571. package/lib/components/productCard/cartSkuCard/components/timeRange/index.js +1 -2
  572. package/lib/components/productCard/cartSkuCard/index.js +8 -68
  573. package/lib/components/productCard/cartSkuCard/locales.js +5 -40
  574. package/lib/components/productCard/components/Header/Actions/index.less +15 -0
  575. package/lib/components/productCard/components/Header/DeleteButton/index.js +2 -2
  576. package/lib/components/productCard/components/Header/DeleteButton/index.less +2 -1
  577. package/lib/components/productCard/components/Header/EditButton/index.js +1 -2
  578. package/lib/components/productCard/components/Header/index.less +1 -1
  579. package/lib/components/productCard/components/Time/components/SelectHolder/index.js +3 -2
  580. package/lib/components/productCard/components/Time/components/SelectHolderModal/index.js +5 -5
  581. package/lib/components/productCard/components/Time/components/SelectHolderMultiple/index.js +2 -2
  582. package/lib/components/productCard/components/Time/components/SelectResource/index.js +6 -3
  583. package/lib/components/productCard/components/Time/index.js +3 -2
  584. package/lib/components/productCard/status.js +0 -3
  585. package/lib/components/productCard/types.d.ts +0 -10
  586. package/lib/components/productCard/utils.js +1 -1
  587. package/lib/components/select-time/index.js +0 -1
  588. package/lib/components/table/Actions/component/ExportImport/index.js +3 -4
  589. package/lib/components/table/Actions/component/GallerySetting/index.js +12 -11
  590. package/lib/components/table/Actions/component/ViewMode/index.js +6 -5
  591. package/lib/components/table/Actions/index.js +1 -1
  592. package/lib/components/table/BasicTable/index.js +4 -3
  593. package/lib/components/table/Gallery/components/GalleryItem/components/Title/index.less +1 -1
  594. package/lib/components/table/Gallery/components/GalleryItem/index.js +17 -9
  595. package/lib/components/table/Gallery/components/GalleryItem/index.less +1 -0
  596. package/lib/components/table/Gallery/index.js +11 -3
  597. package/lib/components/table/Table/fields/text/Show/index.js +1 -1
  598. package/lib/components/table/Table/index.js +2 -1
  599. package/lib/components/table/Table/tableConfig/header/index.js +2 -2
  600. package/lib/components/table/Table/utils.js +5 -1
  601. package/lib/components/table/hooks/useTableSetting.js +3 -0
  602. package/lib/components/table/hooks/useTransDataSource.js +4 -3
  603. package/lib/components/table/index.js +1 -1
  604. package/lib/components/tabs/index.less +1 -1
  605. package/lib/components/translation/index.d.ts +1 -0
  606. package/lib/components/translation/index.js +35 -9
  607. package/lib/components/translation/index.less +12 -0
  608. package/lib/components/versionModal/index.d.ts +1 -0
  609. package/lib/components/versionModal/index.js +2 -2
  610. package/lib/components/versionSelect/index.js +4 -4
  611. package/lib/components/virtual-keyboard/Amount/index.js +5 -4
  612. package/lib/components/virtual-keyboard/Amount/types.d.ts +1 -0
  613. package/lib/index.d.ts +105 -94
  614. package/lib/index.js +298 -299
  615. package/lib/locales/en-US.js +69 -191
  616. package/lib/locales/ja.js +12 -192
  617. package/lib/locales/pt.js +12 -192
  618. package/lib/locales/zh-CN.js +63 -185
  619. package/lib/locales/zh-TW.js +68 -190
  620. package/lib/pisell-materials.tw.css +1 -2414
  621. package/lib/tailwind-input.css +1 -3
  622. package/lib/theme/pisell-components.js +76 -0
  623. package/lowcode/pisell-time-navigator/meta.ts +10 -0
  624. package/package.json +3 -2
  625. package/es/components/SafeAreaTop/index.d.ts +0 -6
  626. package/es/components/SafeAreaTop/index.js +0 -112
  627. package/es/components/SafeAreaTop/index.less +0 -11
  628. package/es/components/SafeAreaTop/types.d.ts +0 -13
  629. package/es/components/pisellFloorMapLayout/appearance/floorMapAppearance.d.ts +0 -4
  630. package/es/components/pisellFloorMapLayout/appearance/floorMapAppearance.js +0 -22
  631. package/es/components/pisellFloorMapLayout/components/HistoryIcons.js +0 -64
  632. package/es/components/pisellFloorMapLayout/floorMapLayoutConstants.js +0 -7
  633. package/es/components/pisellFloorMapLayout/hooks/floorMapViewportPersistence.js +0 -47
  634. package/es/components/pisellFloorMapLayout/hooks/useDraftConfigHistory.js +0 -95
  635. package/es/components/pisellFloorMapLayout/utils/floorMapElementNameAsTitle.d.ts +0 -52
  636. package/es/components/pisellFloorMapLayout/utils/floorMapElementNameAsTitle.js +0 -61
  637. package/es/components/pisellRecordBoard/shellFrame/Calendar/BookingCalendar.js +0 -758
  638. package/es/components/pisellRecordBoard/shellFrame/Calendar/BookingCalendar.less +0 -313
  639. package/es/components/pisellRecordBoard/shellFrame/Calendar/bookingCalendarViewShared.js +0 -191
  640. package/es/components/pisellRecordBoard/shellFrame/Calendar/calendarI18n.js +0 -22
  641. package/es/components/pisellRecordBoard/shellFrame/Calendar/const/bookingCalendarConstants.js +0 -39
  642. package/es/components/pisellRecordBoard/shellFrame/Calendar/hooks/useBookingCalendarDayOverlayLayout.js +0 -74
  643. package/es/components/pisellRecordBoard/shellFrame/Calendar/modal/BookingCalendarBlockPanel.js +0 -61
  644. package/es/components/pisellRecordBoard/shellFrame/Calendar/modal/BookingCalendarOverflowListLayer.js +0 -26
  645. package/es/components/pisellRecordBoard/shellFrame/Calendar/modal/MoveConfirmModal.js +0 -79
  646. package/es/components/pisellRecordBoard/shellFrame/Calendar/modal/OverflowListModal.js +0 -48
  647. package/es/components/pisellRecordBoard/shellFrame/Calendar/modal/OverflowPopover.js +0 -37
  648. package/es/components/pisellRecordBoard/shellFrame/Calendar/utils/BookingCalendarStyle.js +0 -20
  649. package/es/components/pisellRecordBoard/shellFrame/Calendar/utils/bookingCalendarDateUtils.js +0 -532
  650. package/es/components/pisellRecordBoard/shellFrame/Calendar/utils/bookingCalendarSelectionUtils.js +0 -17
  651. package/es/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarDaySelectionBar.js +0 -31
  652. package/es/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarDayView.js +0 -583
  653. package/es/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarGroupRowHeader.js +0 -41
  654. package/es/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarMonthView.js +0 -111
  655. package/es/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarResourceView.js +0 -612
  656. package/es/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarWeekView.js +0 -162
  657. package/es/components/pisellRecordBoard/shellFrame/Calendar/view/bookingCalendarDayViewContext.js +0 -8
  658. package/es/components/pisellRecordBoard/shellFrame/Calendar/view/day/useBookingCalendarDayHourRemaining.js +0 -33
  659. package/es/components/pisellRecordBoard/shellFrame/Calendar/view/day/useBookingCalendarDaySelection.js +0 -37
  660. package/es/components/pisellRecordBoard/shellFrame/Calendar/view/resource/useBookingCalendarResourceCellToggle.js +0 -18
  661. package/es/components/pisellRecordBoard/shellFrame/Calendar/view/resource/useBookingCalendarResourceDayHeaderRemaining.js +0 -33
  662. package/es/components/pisellRecordBoard/shellFrame/Calendar/view/useBookingCalendarGoToDayFromCell.js +0 -29
  663. package/es/components/pisellRecordBoard/shellFrame/ResourceWall/NoteTicker.js +0 -43
  664. package/es/components/pisellRecordBoard/shellFrame/ResourceWall/PisellRecordBoardResourceWallView.d.ts +0 -14
  665. package/es/components/pisellRecordBoard/shellFrame/ResourceWall/PisellRecordBoardResourceWallView.js +0 -436
  666. package/es/components/pisellRecordBoard/shellFrame/ResourceWall/RecordBoardResourceWall.d.ts +0 -11
  667. package/es/components/pisellRecordBoard/shellFrame/ResourceWall/RecordBoardResourceWall.js +0 -9
  668. package/es/components/pisellRecordBoard/shellFrame/ResourceWall/ResourceWallControlPanel.js +0 -179
  669. package/es/components/pisellRecordBoard/shellFrame/ResourceWall/ResourceWallControlPanelColorTab.js +0 -62
  670. package/es/components/pisellRecordBoard/shellFrame/ResourceWall/ResourceWallControlPanelLayoutTab.js +0 -57
  671. package/es/components/pisellRecordBoard/shellFrame/ResourceWall/ResourceWallViewport.less +0 -45
  672. package/es/components/pisellRecordBoard/shellFrame/ResourceWall/ResourceWallViewportToolbar.js +0 -91
  673. package/es/components/pisellRecordBoard/shellFrame/ResourceWall/VenueWallCard.js +0 -218
  674. package/es/components/pisellRecordBoard/shellFrame/ResourceWall/VenueWallCard.less +0 -339
  675. package/es/components/pisellRecordBoard/shellFrame/ResourceWall/VenueWallMarquee.less +0 -52
  676. package/es/components/pisellRecordBoard/shellFrame/ResourceWall/venueWallCardPresentation.js +0 -153
  677. package/es/components/pisellRecordBoard/shellFrame/ResourceWall/venueWallUtils.d.ts +0 -32
  678. package/es/components/pisellRecordBoard/shellFrame/ResourceWall/venueWallUtils.js +0 -170
  679. package/es/components/pisellRecordBoard/shellFrame/ToolBar/recordBoardToolBarConstants.js +0 -11
  680. package/es/components/pisellRecordBoard/shellFrame/ToolBar/recordBoardToolBarI18n.js +0 -56
  681. package/es/components/pisellRecordBoard/types.js +0 -12
  682. package/es/components/pisellTimeNavigator/timeNavigatorConstants.js +0 -7
  683. package/es/components/productCard/cartSkuCard/components/Gift/index.js +0 -34
  684. package/es/components/productCard/cartSkuCard/components/Gift/index.less +0 -84
  685. package/es/components/productCard/cartSkuCard/components/Promotion/index.js +0 -23
  686. package/es/components/productCard/cartSkuCard/components/Promotion/index.less +0 -16
  687. package/es/components/productCard/cartSkuCard/components/weighing/index.js +0 -27
  688. package/es/components/productCard/cartSkuCard/components/weighing/index.less +0 -25
  689. package/lib/components/SafeAreaTop/index.d.ts +0 -6
  690. package/lib/components/SafeAreaTop/index.js +0 -115
  691. package/lib/components/SafeAreaTop/index.less +0 -11
  692. package/lib/components/SafeAreaTop/types.d.ts +0 -13
  693. package/lib/components/pisellFloorMapLayout/appearance/floorMapAppearance.d.ts +0 -4
  694. package/lib/components/pisellFloorMapLayout/appearance/floorMapAppearance.js +0 -22
  695. package/lib/components/pisellFloorMapLayout/components/HistoryIcons.js +0 -67
  696. package/lib/components/pisellFloorMapLayout/floorMapLayoutConstants.js +0 -7
  697. package/lib/components/pisellFloorMapLayout/hooks/floorMapViewportPersistence.js +0 -52
  698. package/lib/components/pisellFloorMapLayout/hooks/useDraftConfigHistory.js +0 -96
  699. package/lib/components/pisellFloorMapLayout/utils/floorMapElementNameAsTitle.d.ts +0 -52
  700. package/lib/components/pisellFloorMapLayout/utils/floorMapElementNameAsTitle.js +0 -64
  701. package/lib/components/pisellRecordBoard/shellFrame/Calendar/BookingCalendar.js +0 -760
  702. package/lib/components/pisellRecordBoard/shellFrame/Calendar/BookingCalendar.less +0 -313
  703. package/lib/components/pisellRecordBoard/shellFrame/Calendar/bookingCalendarViewShared.js +0 -197
  704. package/lib/components/pisellRecordBoard/shellFrame/Calendar/calendarI18n.js +0 -23
  705. package/lib/components/pisellRecordBoard/shellFrame/Calendar/const/bookingCalendarConstants.js +0 -44
  706. package/lib/components/pisellRecordBoard/shellFrame/Calendar/hooks/useBookingCalendarDayOverlayLayout.js +0 -75
  707. package/lib/components/pisellRecordBoard/shellFrame/Calendar/modal/BookingCalendarBlockPanel.js +0 -63
  708. package/lib/components/pisellRecordBoard/shellFrame/Calendar/modal/BookingCalendarOverflowListLayer.js +0 -28
  709. package/lib/components/pisellRecordBoard/shellFrame/Calendar/modal/MoveConfirmModal.js +0 -81
  710. package/lib/components/pisellRecordBoard/shellFrame/Calendar/modal/OverflowListModal.js +0 -50
  711. package/lib/components/pisellRecordBoard/shellFrame/Calendar/modal/OverflowPopover.js +0 -39
  712. package/lib/components/pisellRecordBoard/shellFrame/Calendar/utils/BookingCalendarStyle.js +0 -21
  713. package/lib/components/pisellRecordBoard/shellFrame/Calendar/utils/bookingCalendarDateUtils.js +0 -562
  714. package/lib/components/pisellRecordBoard/shellFrame/Calendar/utils/bookingCalendarSelectionUtils.js +0 -17
  715. package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarDaySelectionBar.js +0 -33
  716. package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarDayView.js +0 -585
  717. package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarGroupRowHeader.js +0 -43
  718. package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarMonthView.js +0 -113
  719. package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarResourceView.js +0 -614
  720. package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/BookingCalendarWeekView.js +0 -164
  721. package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/bookingCalendarDayViewContext.js +0 -10
  722. package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/day/useBookingCalendarDayHourRemaining.js +0 -34
  723. package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/day/useBookingCalendarDaySelection.js +0 -38
  724. package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/resource/useBookingCalendarResourceCellToggle.js +0 -19
  725. package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/resource/useBookingCalendarResourceDayHeaderRemaining.js +0 -34
  726. package/lib/components/pisellRecordBoard/shellFrame/Calendar/view/useBookingCalendarGoToDayFromCell.js +0 -30
  727. package/lib/components/pisellRecordBoard/shellFrame/ResourceWall/NoteTicker.js +0 -45
  728. package/lib/components/pisellRecordBoard/shellFrame/ResourceWall/PisellRecordBoardResourceWallView.d.ts +0 -14
  729. package/lib/components/pisellRecordBoard/shellFrame/ResourceWall/PisellRecordBoardResourceWallView.js +0 -439
  730. package/lib/components/pisellRecordBoard/shellFrame/ResourceWall/RecordBoardResourceWall.d.ts +0 -11
  731. package/lib/components/pisellRecordBoard/shellFrame/ResourceWall/RecordBoardResourceWall.js +0 -9
  732. package/lib/components/pisellRecordBoard/shellFrame/ResourceWall/ResourceWallControlPanel.js +0 -181
  733. package/lib/components/pisellRecordBoard/shellFrame/ResourceWall/ResourceWallControlPanelColorTab.js +0 -64
  734. package/lib/components/pisellRecordBoard/shellFrame/ResourceWall/ResourceWallControlPanelLayoutTab.js +0 -57
  735. package/lib/components/pisellRecordBoard/shellFrame/ResourceWall/ResourceWallViewport.less +0 -45
  736. package/lib/components/pisellRecordBoard/shellFrame/ResourceWall/ResourceWallViewportToolbar.js +0 -93
  737. package/lib/components/pisellRecordBoard/shellFrame/ResourceWall/VenueWallCard.js +0 -220
  738. package/lib/components/pisellRecordBoard/shellFrame/ResourceWall/VenueWallCard.less +0 -339
  739. package/lib/components/pisellRecordBoard/shellFrame/ResourceWall/VenueWallMarquee.less +0 -52
  740. package/lib/components/pisellRecordBoard/shellFrame/ResourceWall/venueWallCardPresentation.js +0 -153
  741. package/lib/components/pisellRecordBoard/shellFrame/ResourceWall/venueWallUtils.d.ts +0 -32
  742. package/lib/components/pisellRecordBoard/shellFrame/ResourceWall/venueWallUtils.js +0 -181
  743. package/lib/components/pisellRecordBoard/shellFrame/ToolBar/recordBoardToolBarConstants.js +0 -14
  744. package/lib/components/pisellRecordBoard/shellFrame/ToolBar/recordBoardToolBarI18n.js +0 -63
  745. package/lib/components/pisellRecordBoard/types.js +0 -12
  746. package/lib/components/pisellTimeNavigator/timeNavigatorConstants.js +0 -7
  747. package/lib/components/productCard/cartSkuCard/components/Gift/index.js +0 -36
  748. package/lib/components/productCard/cartSkuCard/components/Gift/index.less +0 -84
  749. package/lib/components/productCard/cartSkuCard/components/Promotion/index.js +0 -25
  750. package/lib/components/productCard/cartSkuCard/components/Promotion/index.less +0 -16
  751. package/lib/components/productCard/cartSkuCard/components/weighing/index.js +0 -29
  752. package/lib/components/productCard/cartSkuCard/components/weighing/index.less +0 -25
  753. /package/es/components/pisellQuickFilter/{docs → doc}/PisellQuickFilter.$tab-design.md +0 -0
  754. /package/es/components/pisellQuickFilter/{docs → doc}/PisellQuickFilter.$tab-dev.md +0 -0
  755. /package/es/components/pisellQuickFilter/{docs → doc}/PisellQuickFilter.$tab-test.md +0 -0
  756. /package/lib/components/pisellQuickFilter/{docs → doc}/PisellQuickFilter.$tab-design.md +0 -0
  757. /package/lib/components/pisellQuickFilter/{docs → doc}/PisellQuickFilter.$tab-dev.md +0 -0
  758. /package/lib/components/pisellQuickFilter/{docs → doc}/PisellQuickFilter.$tab-test.md +0 -0
@@ -0,0 +1,3813 @@
1
+ const require_runtime = require("../../../../_virtual/_rolldown/runtime.js");
2
+ const require_objectSpread2 = require("../../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectSpread2.js");
3
+ const require_objectWithoutProperties = require("../../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectWithoutProperties.js");
4
+ const require_index = require("../../../pisellTimeNavigator/utils/index.js");
5
+ const require_calendarPersistGuard = require("./calendarPersistGuard.js");
6
+ let react = require("react");
7
+ react = require_runtime.__toESM(react);
8
+ let antd = require("antd");
9
+ let lucide_react = require("lucide-react");
10
+ //#region src/components/pisellRecordBoard/shellFrame/Calendar/BookingCalendarDemo.tsx
11
+ const _excluded = [
12
+ "initial",
13
+ "animate",
14
+ "exit",
15
+ "transition",
16
+ "layoutId",
17
+ "layout",
18
+ "whileHover",
19
+ "whileTap",
20
+ "variants"
21
+ ], _excluded2 = [
22
+ "children",
23
+ "mode",
24
+ "initial"
25
+ ];
26
+ /**
27
+ * 日历原型曾用 framer-motion 做过渡/共享布局动画;低代码 Webpack4 无法稳定打包 framer-motion → motion-dom 的 ESM。
28
+ * 此处用轻量 stub:去掉 motion 专用 props,保留 DOM 与交互(无 FLIP/退场动画)。
29
+ */
30
+ function omitMotionOnlyProps(props) {
31
+ const { initial: _i, animate: _a, exit: _e, transition: _t, layoutId: _lid, layout: _lay, whileHover: _wh, whileTap: _wt, variants: _v } = props;
32
+ return require_objectWithoutProperties._objectWithoutProperties(props, _excluded);
33
+ }
34
+ const motion = {
35
+ div: react.default.forwardRef((props, ref) => /* @__PURE__ */ react.default.createElement("div", require_objectSpread2._objectSpread2({ ref }, omitMotionOnlyProps(props)))),
36
+ button: react.default.forwardRef((props, ref) => /* @__PURE__ */ react.default.createElement("button", require_objectSpread2._objectSpread2({ ref }, omitMotionOnlyProps(props))))
37
+ };
38
+ function LayoutGroup({ children }) {
39
+ return /* @__PURE__ */ react.default.createElement(react.default.Fragment, null, children);
40
+ }
41
+ function AnimatePresence(_ref) {
42
+ let { children, mode: _m, initial: _init } = _ref;
43
+ require_objectWithoutProperties._objectWithoutProperties(_ref, _excluded2);
44
+ return /* @__PURE__ */ react.default.createElement(react.default.Fragment, null, children);
45
+ }
46
+ const DEFAULT_COURTS = [
47
+ {
48
+ id: "vip1",
49
+ name: "VIP Court 1",
50
+ type: "VIP"
51
+ },
52
+ {
53
+ id: "vip2",
54
+ name: "VIP Court 2",
55
+ type: "VIP"
56
+ },
57
+ {
58
+ id: "vip3",
59
+ name: "VIP Court 3",
60
+ type: "VIP"
61
+ },
62
+ {
63
+ id: "vip4",
64
+ name: "VIP Court 4",
65
+ type: "VIP"
66
+ },
67
+ {
68
+ id: "normal1",
69
+ name: "Standard Court 1",
70
+ type: "Standard"
71
+ },
72
+ {
73
+ id: "normal2",
74
+ name: "Standard Court 2",
75
+ type: "Standard"
76
+ },
77
+ {
78
+ id: "normal3",
79
+ name: "Standard Court 3",
80
+ type: "Standard"
81
+ },
82
+ {
83
+ id: "normal4",
84
+ name: "Standard Court 4",
85
+ type: "Standard"
86
+ },
87
+ {
88
+ id: "normal5",
89
+ name: "Standard Court 5",
90
+ type: "Standard"
91
+ },
92
+ {
93
+ id: "normal6",
94
+ name: "Standard Court 6",
95
+ type: "Standard"
96
+ }
97
+ ];
98
+ const monthNames = [
99
+ "Jan",
100
+ "Feb",
101
+ "Mar",
102
+ "Apr",
103
+ "May",
104
+ "Jun",
105
+ "Jul",
106
+ "Aug",
107
+ "Sep",
108
+ "Oct",
109
+ "Nov",
110
+ "Dec"
111
+ ];
112
+ const weekdayNames = [
113
+ "Mon",
114
+ "Tue",
115
+ "Wed",
116
+ "Thu",
117
+ "Fri",
118
+ "Sat",
119
+ "Sun"
120
+ ];
121
+ const weekdaysMap = [
122
+ 1,
123
+ 2,
124
+ 3,
125
+ 4,
126
+ 5,
127
+ 6,
128
+ 0
129
+ ];
130
+ const timeSliceMinutes = 60;
131
+ /** 未传 timelineRange 时日历日列与演示数据对齐的默认营业日界钟 */
132
+ const DEFAULT_CALENDAR_TIMELINE = {
133
+ start: "02:00",
134
+ end: "02:00"
135
+ };
136
+ const frozenColWidth = 132;
137
+ const dayColWidth = 92;
138
+ const dayRowHeight = 122;
139
+ const groupRowHeight = 54;
140
+ const dayHeaderHeight = 56;
141
+ const demoNow = {
142
+ date: "2026-03-31",
143
+ hour: 17.25
144
+ };
145
+ const seedHourlyBookings = [
146
+ {
147
+ id: "b1",
148
+ courtId: "vip1",
149
+ date: "2026-03-29",
150
+ startHour: 9,
151
+ endHour: 12,
152
+ name: "Mr Zhang",
153
+ kind: "booking",
154
+ phone: "0412 111 111",
155
+ statusTag: "new"
156
+ },
157
+ {
158
+ id: "b2",
159
+ courtId: "vip1",
160
+ date: "2026-03-31",
161
+ startHour: 14,
162
+ endHour: 18,
163
+ name: "Ms Li",
164
+ kind: "booking",
165
+ phone: "0412 222 222",
166
+ statusTag: "change"
167
+ },
168
+ {
169
+ id: "b3",
170
+ courtId: "vip2",
171
+ date: "2026-03-30",
172
+ startHour: 10,
173
+ endHour: 13,
174
+ name: "Coach Wang",
175
+ kind: "booking",
176
+ phone: "0412 333 333",
177
+ statusTag: "checked_in"
178
+ },
179
+ {
180
+ id: "b4",
181
+ courtId: "vip2",
182
+ date: "2026-04-01",
183
+ startHour: 9,
184
+ endHour: 20,
185
+ name: "Maintenance",
186
+ kind: "block",
187
+ note: "Equipment maintenance",
188
+ blockBy: "Allen",
189
+ blockedAt: "2026-03-31"
190
+ },
191
+ {
192
+ id: "b5",
193
+ courtId: "vip3",
194
+ date: "2026-04-02",
195
+ startHour: 15,
196
+ endHour: 18,
197
+ name: "Group Booking",
198
+ kind: "booking",
199
+ phone: "0412 555 555"
200
+ },
201
+ {
202
+ id: "b6",
203
+ courtId: "vip4",
204
+ date: "2026-04-03",
205
+ startHour: 11,
206
+ endHour: 14,
207
+ name: "Ms Chen",
208
+ kind: "booking",
209
+ phone: "0412 666 666",
210
+ statusTag: "pending"
211
+ },
212
+ {
213
+ id: "b7",
214
+ courtId: "normal1",
215
+ date: "2026-03-29",
216
+ startHour: 9,
217
+ endHour: 11,
218
+ name: "Trial Class",
219
+ kind: "booking"
220
+ },
221
+ {
222
+ id: "b8",
223
+ courtId: "normal1",
224
+ date: "2026-03-31",
225
+ startHour: 18,
226
+ endHour: 20,
227
+ name: "Full Court",
228
+ kind: "booking",
229
+ statusTag: "checked_in"
230
+ },
231
+ {
232
+ id: "b9",
233
+ courtId: "normal2",
234
+ date: "2026-03-30",
235
+ startHour: 9,
236
+ endHour: 20,
237
+ name: "Blocked",
238
+ kind: "block",
239
+ note: "Internal event",
240
+ blockBy: "Allen",
241
+ blockedAt: "2026-03-30"
242
+ },
243
+ {
244
+ id: "b10",
245
+ courtId: "normal3",
246
+ date: "2026-03-31",
247
+ startHour: 9,
248
+ endHour: 10,
249
+ name: "Member A",
250
+ kind: "booking",
251
+ statusTag: "cancel"
252
+ },
253
+ {
254
+ id: "b11",
255
+ courtId: "normal3",
256
+ date: "2026-03-31",
257
+ startHour: 10,
258
+ endHour: 11,
259
+ name: "Member B",
260
+ kind: "booking"
261
+ },
262
+ {
263
+ id: "b12",
264
+ courtId: "normal3",
265
+ date: "2026-03-31",
266
+ startHour: 11,
267
+ endHour: 12,
268
+ name: "Member C",
269
+ kind: "booking"
270
+ },
271
+ {
272
+ id: "b13",
273
+ courtId: "normal3",
274
+ date: "2026-03-31",
275
+ startHour: 13,
276
+ endHour: 14,
277
+ name: "Member D",
278
+ kind: "booking"
279
+ },
280
+ {
281
+ id: "b14",
282
+ courtId: "normal3",
283
+ date: "2026-03-31",
284
+ startHour: 15,
285
+ endHour: 16,
286
+ name: "Member E",
287
+ kind: "booking"
288
+ },
289
+ {
290
+ id: "b15",
291
+ courtId: "normal4",
292
+ date: "2026-04-04",
293
+ startHour: 16,
294
+ endHour: 19,
295
+ name: "Match",
296
+ kind: "booking",
297
+ statusTag: "new"
298
+ },
299
+ {
300
+ id: "b16",
301
+ courtId: "normal5",
302
+ date: "2026-04-04",
303
+ startHour: 9,
304
+ endHour: 20,
305
+ name: "Repair",
306
+ kind: "block",
307
+ note: "All-day closure",
308
+ blockBy: "Allen",
309
+ blockedAt: "2026-04-01"
310
+ },
311
+ {
312
+ id: "b17",
313
+ courtId: "normal6",
314
+ date: "2026-04-01",
315
+ startHour: 13,
316
+ endHour: 16,
317
+ name: "Walk-in",
318
+ kind: "booking",
319
+ statusTag: "pending"
320
+ },
321
+ {
322
+ id: "b18",
323
+ courtId: "vip3",
324
+ date: "2026-04-02",
325
+ endDate: "2026-04-03",
326
+ startHour: 19,
327
+ endHour: 10,
328
+ name: "Overnight Booking",
329
+ kind: "booking",
330
+ phone: "0412 777 777",
331
+ statusTag: "change"
332
+ },
333
+ {
334
+ id: "b19",
335
+ courtId: "vip4",
336
+ date: "2026-03-31",
337
+ startHour: 12,
338
+ endHour: 14,
339
+ name: "Lunch Peak",
340
+ kind: "booking",
341
+ statusTag: "pending"
342
+ },
343
+ {
344
+ id: "b20",
345
+ courtId: "normal4",
346
+ date: "2026-03-31",
347
+ startHour: 10,
348
+ endHour: 12,
349
+ name: "Open Court A",
350
+ kind: "booking"
351
+ },
352
+ {
353
+ id: "b21",
354
+ courtId: "normal5",
355
+ date: "2026-03-31",
356
+ startHour: 12,
357
+ endHour: 15,
358
+ name: "Open Court B",
359
+ kind: "booking",
360
+ statusTag: "new"
361
+ },
362
+ {
363
+ id: "b22",
364
+ courtId: "vip2",
365
+ date: "2026-03-31",
366
+ startHour: 16,
367
+ endHour: 18,
368
+ name: "Practice Lesson",
369
+ kind: "booking",
370
+ statusTag: "pending"
371
+ },
372
+ {
373
+ id: "b23",
374
+ courtId: "normal1",
375
+ date: "2026-03-31",
376
+ startHour: 14,
377
+ endHour: 17,
378
+ name: "Team Event",
379
+ kind: "booking"
380
+ }
381
+ ];
382
+ function fmtDate(date) {
383
+ return `${date.getFullYear()}-${`${date.getMonth() + 1}`.padStart(2, "0")}-${`${date.getDate()}`.padStart(2, "0")}`;
384
+ }
385
+ function parseDate(str) {
386
+ const [y, m, d] = str.split("-").map(Number);
387
+ return new Date(y, m - 1, d);
388
+ }
389
+ function addDays(date, n) {
390
+ const next = new Date(date);
391
+ next.setDate(next.getDate() + n);
392
+ return next;
393
+ }
394
+ function startOfWeek(date) {
395
+ const d = new Date(date);
396
+ const day = d.getDay();
397
+ const diff = day === 0 ? -6 : 1 - day;
398
+ d.setDate(d.getDate() + diff);
399
+ d.setHours(0, 0, 0, 0);
400
+ return d;
401
+ }
402
+ function rangeDays(anchor) {
403
+ const start = startOfWeek(anchor);
404
+ return Array.from({ length: 7 }, (_, i) => addDays(start, i));
405
+ }
406
+ function isHourInTimelineSlots(hour, hourSlots) {
407
+ if (!(hourSlots === null || hourSlots === void 0 ? void 0 : hourSlots.length)) return false;
408
+ return hourSlots.some((x) => Math.abs(x - hour) < 1e-6);
409
+ }
410
+ function formatHourLabel(hour) {
411
+ const totalMin = Math.round(hour * 60);
412
+ const h = Math.floor(totalMin / 60);
413
+ const m = totalMin % 60;
414
+ const clockH = (h % 24 + 24) % 24;
415
+ return `${String(clockH).padStart(2, "0")}:${String(m).padStart(2, "0")}`;
416
+ }
417
+ function buildTimeOptions(start = 8, end = 20, sliceMinutes = timeSliceMinutes) {
418
+ const out = [];
419
+ for (let m = start * 60; m <= end * 60; m += sliceMinutes) out.push(m / 60);
420
+ return out;
421
+ }
422
+ function monthGrid(date, bookings, courtsList = DEFAULT_COURTS, hourSlotsIn) {
423
+ const hourSlots = hourSlotsIn && hourSlotsIn.length ? hourSlotsIn : require_index.buildCalendarHourSlotsFromRange(DEFAULT_CALENDAR_TIMELINE, date);
424
+ const year = date.getFullYear();
425
+ const month = date.getMonth();
426
+ const start = startOfWeek(new Date(year, month, 1));
427
+ return Array.from({ length: 35 }, (_, i) => addDays(start, i)).map((day) => {
428
+ const key = fmtDate(day);
429
+ const dayBookings = bookings.filter((b) => b.date === key && b.kind === "booking");
430
+ const blocks = bookings.filter((b) => b.date === key && b.kind === "block");
431
+ const fullyBookedCourts = courtsList.filter((court) => {
432
+ var _hourSlots$length;
433
+ const items = bookings.filter((b) => b.courtId === court.id && b.date === key);
434
+ const occupied = /* @__PURE__ */ new Set();
435
+ items.forEach((b) => {
436
+ for (let h = b.startHour; h < b.endHour; h++) occupied.add(h);
437
+ });
438
+ const slotCount = (_hourSlots$length = hourSlots === null || hourSlots === void 0 ? void 0 : hourSlots.length) !== null && _hourSlots$length !== void 0 ? _hourSlots$length : 14;
439
+ return Array.from(occupied).filter((h) => isHourInTimelineSlots(h, hourSlots)).length >= slotCount;
440
+ }).length;
441
+ return {
442
+ date: day,
443
+ key,
444
+ inMonth: day.getMonth() === month,
445
+ bookingCount: dayBookings.length,
446
+ blockCount: blocks.length,
447
+ fullyBooked: fullyBookedCourts >= courtsList.length
448
+ };
449
+ });
450
+ }
451
+ function getBookingSegmentForDate(item, dateKey) {
452
+ if (!item.endDate || item.endDate === item.date) {
453
+ if (item.date !== dateKey) return null;
454
+ return {
455
+ startHour: item.startHour,
456
+ endHour: item.endHour,
457
+ continuesPrev: false,
458
+ continuesNext: false
459
+ };
460
+ }
461
+ if (dateKey < item.date || dateKey > item.endDate) return null;
462
+ if (dateKey === item.date) return {
463
+ startHour: item.startHour,
464
+ endHour: 24,
465
+ continuesPrev: false,
466
+ continuesNext: true
467
+ };
468
+ if (dateKey === item.endDate) return {
469
+ startHour: 0,
470
+ endHour: item.endHour,
471
+ continuesPrev: true,
472
+ continuesNext: false
473
+ };
474
+ return {
475
+ startHour: 0,
476
+ endHour: 24,
477
+ continuesPrev: true,
478
+ continuesNext: true
479
+ };
480
+ }
481
+ function dayOccupancy(courtId, dateKey, bookings, hourSlots) {
482
+ const items = bookings.filter((b) => b.courtId === courtId && getBookingSegmentForDate(b, dateKey));
483
+ const map = {};
484
+ (hourSlots || []).forEach((hour) => {
485
+ map[hour] = items.find((b) => {
486
+ const seg = getBookingSegmentForDate(b, dateKey);
487
+ return seg && seg.startHour < hour + 1 && seg.endHour > hour;
488
+ }) || null;
489
+ });
490
+ return map;
491
+ }
492
+ function groupSelectedSlots(slots) {
493
+ const sorted = [...slots].sort((a, b) => {
494
+ if (a.date !== b.date) return a.date.localeCompare(b.date);
495
+ if (a.courtId !== b.courtId) return a.courtId.localeCompare(b.courtId);
496
+ return a.hour - b.hour;
497
+ });
498
+ const groups = [];
499
+ sorted.forEach((slot) => {
500
+ const prev = groups[groups.length - 1];
501
+ if (prev && prev.courtId === slot.courtId && prev.date === slot.date && prev.endHour === slot.hour) prev.endHour = slot.hour + 1;
502
+ else groups.push({
503
+ courtId: slot.courtId,
504
+ date: slot.date,
505
+ startHour: slot.hour,
506
+ endHour: slot.hour + 1
507
+ });
508
+ });
509
+ return groups;
510
+ }
511
+ function hasConflict(bookings, courtId, date, startHour, endHour, ignoreId = null) {
512
+ return bookings.some((b) => {
513
+ if (b.id === ignoreId) return false;
514
+ if (b.kind !== "booking") return false;
515
+ if (b.courtId !== courtId || b.date !== date) return false;
516
+ return !(endHour <= b.startHour || startHour >= b.endHour);
517
+ });
518
+ }
519
+ function overlappingBookings(bookings, courtId, date, startHour, endHour) {
520
+ return bookings.filter((b) => {
521
+ if (b.kind !== "booking") return false;
522
+ if (b.courtId !== courtId || b.date !== date) return false;
523
+ return !(endHour <= b.startHour || startHour >= b.endHour);
524
+ });
525
+ }
526
+ function courtDaySummary(courtId, dateKey, bookings, hourSlots) {
527
+ var _hourSlots$length2;
528
+ const occ = dayOccupancy(courtId, dateKey, bookings, hourSlots);
529
+ const items = bookings.filter((b) => b.courtId === courtId && b.date === dateKey).sort((a, b) => a.startHour - b.startHour);
530
+ const occupiedHours = (hourSlots || []).filter((h) => occ[h] && isHourInTimelineSlots(h, hourSlots));
531
+ const hasBlock = occupiedHours.some((h) => {
532
+ var _occ$h;
533
+ return ((_occ$h = occ[h]) === null || _occ$h === void 0 ? void 0 : _occ$h.kind) === "block";
534
+ });
535
+ const slotCount = (_hourSlots$length2 = hourSlots === null || hourSlots === void 0 ? void 0 : hourSlots.length) !== null && _hourSlots$length2 !== void 0 ? _hourSlots$length2 : 0;
536
+ return {
537
+ occupiedHours,
538
+ hasBlock,
539
+ fullyBooked: slotCount > 0 && occupiedHours.length >= slotCount,
540
+ items
541
+ };
542
+ }
543
+ function sameSlot(a, b) {
544
+ return a.courtId === b.courtId && a.date === b.date && a.hour === b.hour;
545
+ }
546
+ function statusTagMeta(tag) {
547
+ switch (tag) {
548
+ case "cancel": return {
549
+ label: "Cancel",
550
+ className: "bg-red-600/88 text-white border border-red-300/35"
551
+ };
552
+ case "change": return {
553
+ label: "Change",
554
+ className: "bg-amber-500/88 text-white border border-amber-200/35"
555
+ };
556
+ case "checked_in": return {
557
+ label: "Checked-in",
558
+ className: "bg-zinc-500/88 text-white border border-zinc-300/30"
559
+ };
560
+ case "pending": return {
561
+ label: "Pending",
562
+ className: "bg-cyan-600/88 text-white border border-cyan-300/35"
563
+ };
564
+ case "new": return {
565
+ label: "New",
566
+ className: "bg-emerald-600/88 text-white border border-emerald-300/35"
567
+ };
568
+ case "late": return {
569
+ label: "Late",
570
+ className: "bg-amber-500/88 text-white border border-amber-200/35"
571
+ };
572
+ case "no_show": return {
573
+ label: "No-show",
574
+ className: "bg-red-700/92 text-white border border-red-300/35"
575
+ };
576
+ default: return null;
577
+ }
578
+ }
579
+ function getDisplayStatusTag(item, dateKey) {
580
+ if (item.kind !== "booking") return item.statusTag || null;
581
+ if (item.statusTag === "checked_in" || item.statusTag === "cancel") return item.statusTag;
582
+ if (dateKey !== demoNow.date) return item.statusTag || null;
583
+ const seg = getBookingSegmentForDate(item, dateKey);
584
+ if (!seg) return item.statusTag || null;
585
+ const lateThreshold = item.startHour + 5 / 60;
586
+ if (demoNow.hour > seg.endHour) return "no_show";
587
+ if (demoNow.hour > lateThreshold) return "late";
588
+ return item.statusTag || null;
589
+ }
590
+ function getBookingStateClasses(item, dateKey) {
591
+ const displayTag = getDisplayStatusTag(item, dateKey);
592
+ if (displayTag === "cancel") return "bg-zinc-700/55 border border-zinc-500/70 text-zinc-100 grayscale-[0.2]";
593
+ if (displayTag === "no_show") return "bg-zinc-700/55 border border-red-500/70 text-zinc-200 grayscale-[0.15]";
594
+ if (displayTag === "late") return "bg-violet-700/90 border border-amber-400/80 text-violet-50";
595
+ if (item.kind === "block") return "bg-red-700/70 text-red-100";
596
+ return "bg-violet-700/90 text-violet-50";
597
+ }
598
+ function getLateMinutes(item, dateKey) {
599
+ if (getDisplayStatusTag(item, dateKey) !== "late") return null;
600
+ const seg = getBookingSegmentForDate(item, dateKey);
601
+ if (!seg) return null;
602
+ const lateThreshold = seg.startHour + 5 / 60;
603
+ return Math.max(1, Math.floor((demoNow.hour - lateThreshold) * 60));
604
+ }
605
+ function currentTimeLabel() {
606
+ return `${String(Math.floor(demoNow.hour)).padStart(2, "0")}:${String(Math.floor(demoNow.hour % 1 * 60)).padStart(2, "0")}`;
607
+ }
608
+ function formatDateLoose(str) {
609
+ if (!str) return "";
610
+ const d = parseDate(str);
611
+ return `${d.getFullYear()} ${String(d.getMonth() + 1).padStart(2, "0")} ${String(d.getDate()).padStart(2, "0")}`;
612
+ }
613
+ function getBlockMetaLine(item) {
614
+ if (item.kind !== "block") return "";
615
+ const bits = [];
616
+ if (item.blockBy) bits.push(`by ${item.blockBy}`);
617
+ if (item.blockedAt) bits.push(formatDateLoose(item.blockedAt));
618
+ return bits.join(" · ");
619
+ }
620
+ function getDrawerStatusTheme(item, dateKey) {
621
+ const tag = getDisplayStatusTag(item, dateKey);
622
+ if (item.kind === "block") return "bg-red-700/88 border-b-4 border-red-300/55";
623
+ if (tag === "cancel") return "bg-zinc-700/88 border-b-4 border-zinc-400/45";
624
+ if (tag === "no_show") return "bg-zinc-700/88 border-b-4 border-red-400/75";
625
+ if (tag === "late") return "bg-violet-700/92 border-b-4 border-amber-400/95";
626
+ if (tag === "checked_in") return "bg-violet-700/92 border-b-4 border-zinc-300/45";
627
+ return "bg-violet-700/92 border-b-4 border-violet-300/30";
628
+ }
629
+ function getCompactBookingId(detail) {
630
+ const raw = String(detail.bookingId || detail.orderNumber || "B0000");
631
+ const numeric = raw.replace(/[^0-9]/g, "");
632
+ if (numeric) return `B${numeric.slice(-4).padStart(4, "0")}`;
633
+ return raw.startsWith("B") ? raw.slice(0, 5) : `B${raw.slice(-4).padStart(4, "0")}`;
634
+ }
635
+ function getFulfillmentDisplay(item, detail) {
636
+ var _detail$headerTags;
637
+ const guestCount = Number((detail === null || detail === void 0 ? void 0 : detail.guestCount) || 0);
638
+ const checkedInCount = Number((detail === null || detail === void 0 ? void 0 : detail.checkedInCount) || 0);
639
+ const tag = getDisplayStatusTag(item, item.date);
640
+ if (tag === "cancel") return "Cancelled";
641
+ if (tag === "no_show") return "No-show";
642
+ if (guestCount > 0) {
643
+ if (checkedInCount > 0) return "Arrived";
644
+ if (tag === "late") return "Late";
645
+ }
646
+ const raw = String((detail === null || detail === void 0 || (_detail$headerTags = detail.headerTags) === null || _detail$headerTags === void 0 ? void 0 : _detail$headerTags.fulfillmentTag) || "Open").toLowerCase();
647
+ if (raw.includes("complete")) return "Finished";
648
+ if (raw.includes("arriv")) return "Arrived";
649
+ return tag === "late" ? "Late" : "Arrived";
650
+ }
651
+ function getPaymentDisplay(detail) {
652
+ var _detail$paymentSummar, _detail$paymentSummar2;
653
+ const paid = Number(((_detail$paymentSummar = detail.paymentSummary) === null || _detail$paymentSummar === void 0 ? void 0 : _detail$paymentSummar.paidAmount) || 0);
654
+ const total = Number(((_detail$paymentSummar2 = detail.paymentSummary) === null || _detail$paymentSummar2 === void 0 ? void 0 : _detail$paymentSummar2.totalAmount) || 0);
655
+ if (String(detail.paymentStatus || "").toLowerCase().includes("refund")) return "Refunded";
656
+ if (paid <= 0) return "Unpaid";
657
+ if (total > 0 && paid < total) return "Partial paid";
658
+ return "Paid";
659
+ }
660
+ function paymentTagClass(label, isLight = false) {
661
+ switch (label) {
662
+ case "Paid": return isLight ? "theme-success-chip border" : "bg-emerald-500 text-white";
663
+ case "Partial paid": return isLight ? "theme-warning-chip border" : "bg-amber-500 text-white";
664
+ case "Refunded": return isLight ? "theme-info-chip border" : "bg-sky-500 text-white";
665
+ default: return isLight ? "theme-danger-chip border" : "bg-red-500 text-white";
666
+ }
667
+ }
668
+ function fulfillmentTagClass(label, isLight = false) {
669
+ switch (label) {
670
+ case "Finished": return isLight ? "theme-success-chip border" : "bg-emerald-600 text-white";
671
+ case "Arrived": return isLight ? "theme-info-chip border" : "bg-cyan-500 text-white";
672
+ case "Late": return isLight ? "theme-warning-chip border" : "bg-amber-500 text-white";
673
+ case "No-show": return isLight ? "theme-danger-chip border" : "bg-red-600 text-white";
674
+ case "Cancelled": return isLight ? "border border-[var(--border-strong)] bg-[var(--bg-input)] theme-text-soft" : "bg-zinc-600 text-white";
675
+ default: return isLight ? "border border-[var(--brand-light)] bg-[var(--brand-surface)] theme-brand-text" : "bg-violet-600 text-white";
676
+ }
677
+ }
678
+ const salesProtocolMockByBookingItemId = { b2: {
679
+ order_id: 1001,
680
+ order_number: "A00123",
681
+ shop_order_number: "A00123",
682
+ type: "appointment_booking",
683
+ business_code: "appointment_booking",
684
+ platform: "pos",
685
+ sales_channel: "my_pisel",
686
+ order_sales_channel: "pos",
687
+ status: "normal",
688
+ payment_status: "payment_processing",
689
+ shipping_status: "unfulfilled",
690
+ customer_id: 456,
691
+ customer_name: "Tina Wu",
692
+ country_calling_code: "+61",
693
+ phone: "0412888999",
694
+ email: "tina.wu@pisell.com",
695
+ is_price_include_tax: 1,
696
+ tax_title: "GST",
697
+ tax_country_code: "AU",
698
+ currency_code: "AUD",
699
+ currency_symbol: "$",
700
+ currency_format: "symbol_first",
701
+ is_deposit: 0,
702
+ deposit_amount: "0.00",
703
+ shop_discount: "0.00",
704
+ surcharge_fee: "10.00",
705
+ note: "Customer prefers a quieter court and may arrive slightly late.",
706
+ schedule_date: "2026-03-31 00:00:00",
707
+ created_at: "2026-03-18 10:00:00",
708
+ products: [{
709
+ order_detail_id: 789,
710
+ product_id: 101,
711
+ num: 1,
712
+ product_variant_id: 0,
713
+ product_option_item: [],
714
+ selling_price: "42.00",
715
+ original_price: "48.00",
716
+ payment_price: "42.00",
717
+ tax_fee: "4.20",
718
+ is_charge_tax: 1,
719
+ discount_list: [],
720
+ product_bundle: [],
721
+ metadata: { unique_identification_number: "local_prod_001" }
722
+ }],
723
+ bookings: [{
724
+ schedule_event_id: 301,
725
+ booking_id: "B20260318001",
726
+ appointment_status: "arrived",
727
+ start_date: "2026-03-31",
728
+ start_time: "14:00",
729
+ end_date: "2026-03-31",
730
+ end_time: "18:00",
731
+ select_date: "2026-03-31",
732
+ duration: 240,
733
+ arrived_at: null,
734
+ completed_at: null,
735
+ sub_type: "service",
736
+ like_status: "common",
737
+ number: 4,
738
+ resources: [{
739
+ form_id: 10,
740
+ relation_type: "form",
741
+ relation_id: 201,
742
+ capacity: 1,
743
+ like_status: "like",
744
+ metadata: null,
745
+ children: []
746
+ }],
747
+ product: {
748
+ order_detail_id: null,
749
+ product_id: 101,
750
+ num: 1,
751
+ discount_list: [],
752
+ product_bundle: [],
753
+ metadata: { unique_identification_number: "local_bk_prod_001" }
754
+ },
755
+ relation_products: [{
756
+ order_detail_id: 790,
757
+ product_id: 202,
758
+ num: 1,
759
+ product_variant_id: 0,
760
+ product_option_item: [],
761
+ selling_price: "8.00",
762
+ original_price: "8.00",
763
+ payment_price: "8.00",
764
+ tax_fee: "0.80",
765
+ is_charge_tax: 1,
766
+ discount_list: [],
767
+ product_bundle: [],
768
+ metadata: { unique_identification_number: "local_rel_001" }
769
+ }],
770
+ relation_forms: [],
771
+ holder: null,
772
+ metadata: { unique_identification_number: "local_booking_001" }
773
+ }],
774
+ payments: [{
775
+ order_payment_id: 501,
776
+ custom_payment_id: 1,
777
+ code: "card",
778
+ name: "Card",
779
+ type: "deposit",
780
+ voucher_id: null,
781
+ amount: "60.00",
782
+ origin_amount: "60.00",
783
+ rounding_amount: "0.00",
784
+ status: "paid",
785
+ payment_time: "2026-03-18 15:00:00",
786
+ service_charge: null,
787
+ wallet_pass_usage_unit: null,
788
+ wallet_pass_use_value: null,
789
+ metadata: { unique_payment_number: "local_pay_001" }
790
+ }, {
791
+ order_payment_id: 502,
792
+ custom_payment_id: 2,
793
+ code: "cash",
794
+ name: "Cash",
795
+ type: "balance",
796
+ voucher_id: null,
797
+ amount: "108.00",
798
+ origin_amount: "108.00",
799
+ rounding_amount: "0.00",
800
+ status: "paid",
801
+ payment_time: "2026-03-31 17:05:00",
802
+ service_charge: null,
803
+ wallet_pass_usage_unit: null,
804
+ wallet_pass_use_value: null,
805
+ metadata: { unique_payment_number: "local_pay_002" }
806
+ }],
807
+ surcharges: [{
808
+ order_surcharge_id: 701,
809
+ surcharge_id: 1,
810
+ type: "service_charge",
811
+ name: { en: "Service Charge" },
812
+ description: { en: "10% service charge" },
813
+ percentage: "0.10",
814
+ fixed: null,
815
+ amount: "10.00"
816
+ }],
817
+ discount_list: [],
818
+ relation_forms: [],
819
+ contacts: [],
820
+ contacts_info: [],
821
+ holder: null,
822
+ summary: {
823
+ product_quantity: 2,
824
+ product_original_amount: "56.00",
825
+ product_amount: "50.00",
826
+ product_expect_amount: "50.00",
827
+ product_tax_fee: "5.00",
828
+ shipping_fee: "0.00",
829
+ shipping_tax_fee: "0.00",
830
+ tax_fee: "5.00",
831
+ surcharge_fee: "10.00",
832
+ discount_amount: "6.00",
833
+ deposit_amount: "0.00",
834
+ expect_amount: "60.00",
835
+ total_amount: "168.00",
836
+ amount_gap: "0.00",
837
+ rounding_amount: "0.00",
838
+ pay_service_charge_amount: "0.00"
839
+ },
840
+ metadata: {}
841
+ } };
842
+ function fallbackSalesFromItem(item) {
843
+ return {
844
+ order_id: null,
845
+ order_number: item.id.toUpperCase(),
846
+ shop_order_number: item.id.toUpperCase(),
847
+ type: item.kind === "block" ? "court_block" : "appointment_booking",
848
+ business_code: item.kind === "block" ? "court_block" : "appointment_booking",
849
+ platform: "pos",
850
+ sales_channel: "my_pisel",
851
+ order_sales_channel: "pos",
852
+ status: "normal",
853
+ payment_status: "payment_processing",
854
+ shipping_status: "unfulfilled",
855
+ customer_id: null,
856
+ customer_name: item.kind === "block" ? item.blockBy || "Staff" : item.name,
857
+ country_calling_code: "+61",
858
+ phone: item.phone || "",
859
+ email: "",
860
+ is_price_include_tax: 1,
861
+ tax_title: "GST",
862
+ tax_country_code: "AU",
863
+ currency_code: "AUD",
864
+ currency_symbol: "$",
865
+ currency_format: "symbol_first",
866
+ is_deposit: 0,
867
+ deposit_amount: "0.00",
868
+ shop_discount: "0.00",
869
+ surcharge_fee: "0.00",
870
+ note: item.kind === "block" ? item.note || "Blocked by staff" : "No additional note.",
871
+ schedule_date: `${item.date} 00:00:00`,
872
+ created_at: `${item.date} 09:00:00`,
873
+ products: [],
874
+ bookings: [{
875
+ schedule_event_id: null,
876
+ booking_id: item.id.toUpperCase(),
877
+ appointment_status: item.kind === "block" ? "blocked" : "confirmed",
878
+ start_date: item.date,
879
+ start_time: formatHourLabel(item.startHour),
880
+ end_date: item.endDate || item.date,
881
+ end_time: formatHourLabel(item.endHour),
882
+ select_date: item.date,
883
+ duration: Math.max(60, (item.endHour - item.startHour) * 60),
884
+ arrived_at: null,
885
+ completed_at: null,
886
+ sub_type: item.kind === "block" ? "court_block" : "service",
887
+ like_status: "common",
888
+ number: 1,
889
+ resources: [{
890
+ form_id: 10,
891
+ relation_type: "form",
892
+ relation_id: 201,
893
+ capacity: 1,
894
+ like_status: "common",
895
+ metadata: null,
896
+ children: []
897
+ }],
898
+ product: null,
899
+ relation_products: [],
900
+ relation_forms: [],
901
+ holder: null,
902
+ metadata: { unique_identification_number: `local_${item.id}` }
903
+ }],
904
+ payments: [],
905
+ surcharges: [],
906
+ discount_list: [],
907
+ relation_forms: [],
908
+ contacts: [],
909
+ contacts_info: [],
910
+ holder: null,
911
+ summary: {
912
+ product_quantity: 0,
913
+ product_original_amount: "0.00",
914
+ product_amount: "0.00",
915
+ product_expect_amount: "0.00",
916
+ product_tax_fee: "0.00",
917
+ shipping_fee: "0.00",
918
+ shipping_tax_fee: "0.00",
919
+ tax_fee: "0.00",
920
+ surcharge_fee: "0.00",
921
+ discount_amount: "0.00",
922
+ deposit_amount: "0.00",
923
+ expect_amount: "0.00",
924
+ total_amount: "0.00",
925
+ amount_gap: "0.00",
926
+ rounding_amount: "0.00",
927
+ pay_service_charge_amount: "0.00"
928
+ },
929
+ metadata: {}
930
+ };
931
+ }
932
+ function buildResourceDisplay(resources = [], fallbackCourtName = "") {
933
+ const labels = resources.map((row) => {
934
+ const typeName = (row === null || row === void 0 ? void 0 : row.category_name) || (row === null || row === void 0 ? void 0 : row.resource_category_name) || (row === null || row === void 0 ? void 0 : row.type_name) || (row === null || row === void 0 ? void 0 : row.type) || (row === null || row === void 0 ? void 0 : row.relation_type_name) || (row === null || row === void 0 ? void 0 : row.relation_type_label) || (row === null || row === void 0 ? void 0 : row.relation_type) || "";
935
+ const resourceName = (row === null || row === void 0 ? void 0 : row.resource_name) || (row === null || row === void 0 ? void 0 : row.name) || (row === null || row === void 0 ? void 0 : row.relation_name) || (row === null || row === void 0 ? void 0 : row.label) || (row === null || row === void 0 ? void 0 : row.title) || "";
936
+ const childNames = Array.isArray(row === null || row === void 0 ? void 0 : row.children) ? row.children.map((child) => (child === null || child === void 0 ? void 0 : child.resource_name) || (child === null || child === void 0 ? void 0 : child.name) || (child === null || child === void 0 ? void 0 : child.relation_name) || (child === null || child === void 0 ? void 0 : child.label)).filter(Boolean) : [];
937
+ const mainName = resourceName || childNames[0] || "";
938
+ if (typeName && mainName) return `${typeName}: ${mainName}`;
939
+ if (mainName) return mainName;
940
+ return "";
941
+ }).filter(Boolean);
942
+ if (labels.length > 0) return labels.join(", ");
943
+ return fallbackCourtName || "Court";
944
+ }
945
+ function mapSalesToDetail(sales, item, courtsList = DEFAULT_COURTS) {
946
+ var _sales$bookings, _sales$summary, _courtsList$find;
947
+ const booking = ((_sales$bookings = sales.bookings) === null || _sales$bookings === void 0 ? void 0 : _sales$bookings[0]) || {};
948
+ const bookingProduct = booking.product ? [booking.product] : [];
949
+ const rootProducts = sales.products || [];
950
+ const relationProducts = booking.relation_products || [];
951
+ const itemPresetByIndex = [
952
+ {
953
+ name: "Private lesson · Practice",
954
+ specs: "Coach session 2h · Court included · 2 rackets",
955
+ note: "Beginner drills · Need quieter court"
956
+ },
957
+ {
958
+ name: "Milk tea",
959
+ specs: "Large · Less sugar · Less ice",
960
+ note: "Serve after first hour"
961
+ },
962
+ {
963
+ name: "Snack combo",
964
+ specs: "Chicken wrap · Fries",
965
+ note: "No spicy seasoning"
966
+ }
967
+ ];
968
+ const allItems = [
969
+ ...bookingProduct,
970
+ ...rootProducts,
971
+ ...relationProducts
972
+ ].map((row, index) => {
973
+ var _row$product_id, _row$product_variant_;
974
+ const qty = Number(row.num || 0);
975
+ const unitPrice = Number(row.payment_price || row.selling_price || 0);
976
+ const preset = itemPresetByIndex[index] || {
977
+ name: row.product_id ? `Product #${row.product_id}` : `Custom item #${index + 1}`,
978
+ specs: "Standard",
979
+ note: "No note"
980
+ };
981
+ return {
982
+ id: row.order_detail_id || `${sales.order_number || item.id}-item-${index}`,
983
+ name: preset.name,
984
+ specs: preset.specs,
985
+ note: preset.note,
986
+ price: unitPrice,
987
+ qty,
988
+ qtyLabel: `×${qty}`,
989
+ unitLabel: `${sales.currency_symbol || "$"}${unitPrice.toFixed(2)} each`,
990
+ total: unitPrice * qty,
991
+ productId: (_row$product_id = row.product_id) !== null && _row$product_id !== void 0 ? _row$product_id : null,
992
+ variantId: (_row$product_variant_ = row.product_variant_id) !== null && _row$product_variant_ !== void 0 ? _row$product_variant_ : null
993
+ };
994
+ });
995
+ const appointmentStatus = String(booking.appointment_status || "").toLowerCase();
996
+ const isArrivedBooking = [
997
+ "arrived",
998
+ "started",
999
+ "completed"
1000
+ ].includes(appointmentStatus) || Boolean(booking.arrived_at);
1001
+ const guestCount = Number(booking.number || 0);
1002
+ const guests = [
1003
+ ...Array.isArray(sales.contacts) ? sales.contacts : [],
1004
+ ...Array.isArray(sales.contacts_info) ? sales.contacts_info : [],
1005
+ ...Array.isArray(booking.contacts) ? booking.contacts : [],
1006
+ ...Array.isArray(booking.contacts_info) ? booking.contacts_info : [],
1007
+ ...Array.isArray(booking.guests) ? booking.guests : []
1008
+ ].map((row, index) => {
1009
+ const checked = Boolean((row === null || row === void 0 ? void 0 : row.checked_in) || (row === null || row === void 0 ? void 0 : row.checkedIn) || (row === null || row === void 0 ? void 0 : row.arrived_at) || (row === null || row === void 0 ? void 0 : row.arrivedAt) || (row === null || row === void 0 ? void 0 : row.is_checked_in));
1010
+ return {
1011
+ id: (row === null || row === void 0 ? void 0 : row.guest_id) || (row === null || row === void 0 ? void 0 : row.contact_id) || (row === null || row === void 0 ? void 0 : row.id) || `${sales.order_number || item.id}-guest-${index}`,
1012
+ name: (row === null || row === void 0 ? void 0 : row.name) || (row === null || row === void 0 ? void 0 : row.customer_name) || (row === null || row === void 0 ? void 0 : row.full_name) || (row === null || row === void 0 ? void 0 : row.nickname) || `Guest ${index + 1}`,
1013
+ note: [row === null || row === void 0 ? void 0 : row.phone, row === null || row === void 0 ? void 0 : row.email].filter(Boolean).join(" · ") || "",
1014
+ checkedIn: checked,
1015
+ noShow: Boolean((row === null || row === void 0 ? void 0 : row.no_show) || (row === null || row === void 0 ? void 0 : row.noShow)),
1016
+ removed: Boolean(row === null || row === void 0 ? void 0 : row.removed)
1017
+ };
1018
+ });
1019
+ const checkedInCount = guests.length > 0 ? guests.filter((g) => g.checkedIn).length : isArrivedBooking ? guestCount : 0;
1020
+ const topRelationForms = Array.isArray(sales.relation_forms) ? sales.relation_forms : [];
1021
+ const bookingRelationForms = Array.isArray(booking.relation_forms) ? booking.relation_forms : [];
1022
+ const files = {
1023
+ form: [...topRelationForms, ...bookingRelationForms].map((row, index) => ({
1024
+ id: (row === null || row === void 0 ? void 0 : row.id) || `${sales.order_number || item.id}-form-${index}`,
1025
+ name: (row === null || row === void 0 ? void 0 : row.name) || (row === null || row === void 0 ? void 0 : row.title) || `Form ${index + 1}`,
1026
+ time: (row === null || row === void 0 ? void 0 : row.updated_at) || (row === null || row === void 0 ? void 0 : row.created_at) || sales.created_at || "",
1027
+ type: (row === null || row === void 0 ? void 0 : row.relation_type) || "form"
1028
+ })),
1029
+ uploaded: (Array.isArray(sales.uploaded_files) ? sales.uploaded_files : []).map((row, index) => ({
1030
+ id: (row === null || row === void 0 ? void 0 : row.id) || `${sales.order_number || item.id}-uploaded-${index}`,
1031
+ name: (row === null || row === void 0 ? void 0 : row.name) || (row === null || row === void 0 ? void 0 : row.file_name) || `Upload ${index + 1}`,
1032
+ time: (row === null || row === void 0 ? void 0 : row.updated_at) || (row === null || row === void 0 ? void 0 : row.created_at) || sales.created_at || "",
1033
+ type: (row === null || row === void 0 ? void 0 : row.type) || "uploaded"
1034
+ })),
1035
+ invoice: (Array.isArray(sales.invoices) ? sales.invoices : []).map((row, index) => ({
1036
+ id: (row === null || row === void 0 ? void 0 : row.id) || `${sales.order_number || item.id}-invoice-${index}`,
1037
+ name: (row === null || row === void 0 ? void 0 : row.name) || (row === null || row === void 0 ? void 0 : row.invoice_number) || `Invoice ${index + 1}`,
1038
+ time: (row === null || row === void 0 ? void 0 : row.updated_at) || (row === null || row === void 0 ? void 0 : row.created_at) || sales.created_at || "",
1039
+ type: (row === null || row === void 0 ? void 0 : row.type) || "invoice"
1040
+ }))
1041
+ };
1042
+ const orderNotes = sales.note ? [{
1043
+ id: `${sales.order_number || item.id}-note-order`,
1044
+ label: "Order note",
1045
+ text: sales.note
1046
+ }] : [];
1047
+ const noteGroups = {
1048
+ internal: Array.isArray(sales.internal_notes) ? sales.internal_notes.map((row, index) => ({
1049
+ id: (row === null || row === void 0 ? void 0 : row.id) || `${sales.order_number || item.id}-note-internal-${index}`,
1050
+ label: (row === null || row === void 0 ? void 0 : row.label) || "Internal note",
1051
+ text: (row === null || row === void 0 ? void 0 : row.text) || (row === null || row === void 0 ? void 0 : row.note) || ""
1052
+ })) : [],
1053
+ order: orderNotes,
1054
+ item: allItems.filter((row) => row.note).map((row, index) => ({
1055
+ id: `${row.id}-item-note-${index}`,
1056
+ label: row.name,
1057
+ text: row.note,
1058
+ qtyLabel: row.qtyLabel,
1059
+ itemId: row.id
1060
+ }))
1061
+ };
1062
+ const payments = (sales.payments || []).map((payment, index) => ({
1063
+ id: payment.order_payment_id || `${sales.order_number || item.id}-payment-${index}`,
1064
+ label: payment.type === "deposit" ? "Deposit" : payment.type === "balance" ? "Balance" : payment.name || payment.code || payment.type || `Payment ${index + 1}`,
1065
+ amount: Number(payment.amount || 0),
1066
+ method: payment.code === "card" ? "Card •••• 1234" : payment.name || payment.code || "Unknown",
1067
+ time: payment.payment_time || "",
1068
+ status: payment.status || "unknown",
1069
+ type: payment.type || "",
1070
+ code: payment.code || ""
1071
+ }));
1072
+ const history = [
1073
+ sales.created_at ? {
1074
+ id: `${sales.order_number || item.id}-history-created`,
1075
+ actor: "System",
1076
+ text: "Order created",
1077
+ time: sales.created_at,
1078
+ kind: "system"
1079
+ } : null,
1080
+ ...payments.filter((row) => row.time).map((row, index) => ({
1081
+ id: `${row.id}-history-${index}`,
1082
+ actor: row.method || "Payment",
1083
+ text: `${row.label} ${sales.currency_symbol || "$"}${row.amount.toFixed(2)}`,
1084
+ time: row.time,
1085
+ kind: "payment"
1086
+ })),
1087
+ booking.arrived_at ? {
1088
+ id: `${sales.order_number || item.id}-history-arrived`,
1089
+ actor: "System",
1090
+ text: "Guest arrived",
1091
+ time: booking.arrived_at,
1092
+ kind: "status"
1093
+ } : null,
1094
+ booking.completed_at ? {
1095
+ id: `${sales.order_number || item.id}-history-completed`,
1096
+ actor: "System",
1097
+ text: "Booking completed",
1098
+ time: booking.completed_at,
1099
+ kind: "status"
1100
+ } : null
1101
+ ].filter(Boolean);
1102
+ const itemCount = allItems.length;
1103
+ const itemQtyTotal = allItems.reduce((sum, row) => sum + Number(row.qty || 0), 0);
1104
+ const totalAmount = Number(((_sales$summary = sales.summary) === null || _sales$summary === void 0 ? void 0 : _sales$summary.total_amount) || 0);
1105
+ const paidAmount = payments.filter((row) => String(row.status).toLowerCase() === "paid").reduce((sum, row) => sum + Number(row.amount || 0), 0);
1106
+ const balanceAmount = Math.max(0, totalAmount - paidAmount);
1107
+ const resourceLabel = buildResourceDisplay(booking.resources || [], ((_courtsList$find = courtsList.find((c) => c.id === item.courtId)) === null || _courtsList$find === void 0 ? void 0 : _courtsList$find.name) || "");
1108
+ const paymentTag = paidAmount <= 0 ? "Unpaid" : balanceAmount > 0 ? "Partial paid" : "Paid";
1109
+ const fulfillmentTag = appointmentStatus === "completed" ? "Finished" : isArrivedBooking ? "Arrived" : appointmentStatus === "cancelled" ? "Cancelled" : "Arrived";
1110
+ const hasNote = orderNotes.length > 0;
1111
+ return {
1112
+ rawSales: sales,
1113
+ bookingId: booking.booking_id || sales.order_number || item.id.toUpperCase(),
1114
+ orderNumber: sales.order_number || item.id.toUpperCase(),
1115
+ shopOrderNumber: sales.shop_order_number || sales.order_number || item.id.toUpperCase(),
1116
+ orderStatus: sales.status || "normal",
1117
+ appointmentStatus: booking.appointment_status || "new",
1118
+ paymentStatus: sales.payment_status || "payment_processing",
1119
+ customer: {
1120
+ id: sales.customer_id,
1121
+ name: sales.customer_name || "Unknown customer",
1122
+ email: sales.email || "",
1123
+ phone: `${sales.country_calling_code || ""} ${sales.phone || ""}`.trim()
1124
+ },
1125
+ guestCount,
1126
+ checkedInCount,
1127
+ guests,
1128
+ schedule: {
1129
+ startDate: booking.start_date || item.date,
1130
+ startTime: booking.start_time || formatHourLabel(item.startHour),
1131
+ endDate: booking.end_date || item.endDate || item.date,
1132
+ endTime: booking.end_time || formatHourLabel(item.endHour),
1133
+ duration: booking.duration || (item.endHour - item.startHour) * 60,
1134
+ arrivedAt: booking.arrived_at,
1135
+ completedAt: booking.completed_at
1136
+ },
1137
+ resources: booking.resources || [],
1138
+ summaryItems: allItems,
1139
+ items: allItems,
1140
+ note: sales.note || "",
1141
+ files,
1142
+ payments,
1143
+ history,
1144
+ summary: sales.summary || {},
1145
+ paymentSummary: {
1146
+ totalAmount,
1147
+ paidAmount,
1148
+ balanceAmount,
1149
+ currencySymbol: sales.currency_symbol || "$",
1150
+ isFullyPaid: balanceAmount <= 0 && totalAmount > 0
1151
+ },
1152
+ itemSummary: {
1153
+ itemCount,
1154
+ itemQtyTotal
1155
+ },
1156
+ headerSummary: {
1157
+ customerName: sales.customer_name || "Unknown customer",
1158
+ guestCount,
1159
+ checkedInCount,
1160
+ timeLabel: `${booking.start_date || item.date} · ${booking.start_time || formatHourLabel(item.startHour)} - ${booking.end_time || formatHourLabel(item.endHour)}`,
1161
+ resourceLabel
1162
+ },
1163
+ headerTags: {
1164
+ paymentTag,
1165
+ fulfillmentTag,
1166
+ hasNote,
1167
+ paymentStatus: sales.payment_status || "payment_processing",
1168
+ orderStatus: sales.status || "normal"
1169
+ },
1170
+ fileCount: files.form.length + files.uploaded.length + files.invoice.length,
1171
+ canChangeCustomer: true,
1172
+ noteCount: noteGroups.order.length,
1173
+ noteGroups,
1174
+ metaFlags: {
1175
+ itemsChanged: false,
1176
+ paymentsChanged: false,
1177
+ guestChanged: false,
1178
+ filesChanged: false,
1179
+ notesChanged: false,
1180
+ formChanged: false,
1181
+ uploadedChanged: false,
1182
+ invoiceChanged: false,
1183
+ historyChanged: false
1184
+ },
1185
+ actions: []
1186
+ };
1187
+ }
1188
+ function getNoteValue(noteOverrides, noteId, fallback) {
1189
+ var _noteOverrides$noteId;
1190
+ return (_noteOverrides$noteId = noteOverrides[noteId]) !== null && _noteOverrides$noteId !== void 0 ? _noteOverrides$noteId : fallback;
1191
+ }
1192
+ function formatTimelineStamp(value) {
1193
+ if (!value) return {
1194
+ date: "--",
1195
+ time: "--"
1196
+ };
1197
+ const [date = "--", time = "--"] = String(value).replace("T", " ").split(" ");
1198
+ return {
1199
+ date,
1200
+ time: time.slice(0, 5) || "--"
1201
+ };
1202
+ }
1203
+ const customerPickerMock = [
1204
+ {
1205
+ id: "c1",
1206
+ name: "Olivia Rhye",
1207
+ registeredAt: "2025/07/01",
1208
+ phone: "0487654321",
1209
+ email: "olivia@untitledui.com",
1210
+ membership: "Gold"
1211
+ },
1212
+ {
1213
+ id: "c2",
1214
+ name: "Phoenix Baker",
1215
+ registeredAt: "2025/06/23",
1216
+ phone: "0487654321",
1217
+ email: "phoenix@untitledui.com",
1218
+ membership: "Silver"
1219
+ },
1220
+ {
1221
+ id: "c3",
1222
+ name: "Liam Carter",
1223
+ registeredAt: "2025/06/18",
1224
+ phone: "0487654321",
1225
+ email: "liam@untitledui.com",
1226
+ membership: "Bronze"
1227
+ },
1228
+ {
1229
+ id: "c4",
1230
+ name: "Zoe Patel",
1231
+ registeredAt: "2025/06/15",
1232
+ phone: "0487654321",
1233
+ email: "zoe@untitledui.com",
1234
+ membership: "Platinum"
1235
+ },
1236
+ {
1237
+ id: "c5",
1238
+ name: "Noah Kim",
1239
+ registeredAt: "2025/05/30",
1240
+ phone: "0487654321",
1241
+ email: "noah@untitledui.com",
1242
+ membership: "Titanium"
1243
+ }
1244
+ ];
1245
+ function getBookingDetailData(item, courtsList = DEFAULT_COURTS) {
1246
+ return mapSalesToDetail(salesProtocolMockByBookingItemId[item.id] || fallbackSalesFromItem(item), item, courtsList);
1247
+ }
1248
+ function tabMeta(tab) {
1249
+ switch (tab) {
1250
+ case "summary": return {
1251
+ label: "Summary",
1252
+ icon: lucide_react.CircleEllipsis
1253
+ };
1254
+ case "items": return {
1255
+ label: "Items",
1256
+ icon: lucide_react.Receipt
1257
+ };
1258
+ case "guest": return {
1259
+ label: "Guests",
1260
+ icon: lucide_react.Users
1261
+ };
1262
+ case "files": return {
1263
+ label: "Files / Notes",
1264
+ icon: lucide_react.FileText
1265
+ };
1266
+ case "payments": return {
1267
+ label: "Payments",
1268
+ icon: lucide_react.CreditCard
1269
+ };
1270
+ case "history": return {
1271
+ label: "History",
1272
+ icon: lucide_react.History
1273
+ };
1274
+ default: return {
1275
+ label: tab,
1276
+ icon: lucide_react.CircleEllipsis
1277
+ };
1278
+ }
1279
+ }
1280
+ function tabBadgeValue(tab, detail) {
1281
+ var _detail$items;
1282
+ if (tab === "guest") return String(detail.guestCount || 0);
1283
+ if (tab === "items") return String(((_detail$items = detail.items) === null || _detail$items === void 0 ? void 0 : _detail$items.length) || 0);
1284
+ if (tab === "files") return String((detail.fileCount || 0) + (detail.noteCount || 0));
1285
+ if (tab === "payments") {
1286
+ var _detail$paymentSummar3, _detail$paymentSummar4;
1287
+ const total = Number(((_detail$paymentSummar3 = detail.paymentSummary) === null || _detail$paymentSummar3 === void 0 ? void 0 : _detail$paymentSummar3.totalAmount) || 0);
1288
+ const paid = Number(((_detail$paymentSummar4 = detail.paymentSummary) === null || _detail$paymentSummar4 === void 0 ? void 0 : _detail$paymentSummar4.paidAmount) || 0);
1289
+ if (total <= 0) return "0%";
1290
+ if (paid >= total) return "✓";
1291
+ return `${Math.round(paid / total * 100)}%`;
1292
+ }
1293
+ return "";
1294
+ }
1295
+ function tabHasChanges(tab, detail) {
1296
+ var _detail$metaFlags, _detail$metaFlags2, _detail$metaFlags3, _detail$metaFlags4, _detail$metaFlags5, _detail$metaFlags6;
1297
+ if (tab === "summary") return false;
1298
+ if (tab === "items") return Boolean((_detail$metaFlags = detail.metaFlags) === null || _detail$metaFlags === void 0 ? void 0 : _detail$metaFlags.itemsChanged);
1299
+ if (tab === "payments") return Boolean((_detail$metaFlags2 = detail.metaFlags) === null || _detail$metaFlags2 === void 0 ? void 0 : _detail$metaFlags2.paymentsChanged);
1300
+ if (tab === "guest") return Boolean((_detail$metaFlags3 = detail.metaFlags) === null || _detail$metaFlags3 === void 0 ? void 0 : _detail$metaFlags3.guestChanged);
1301
+ if (tab === "files") return Boolean(((_detail$metaFlags4 = detail.metaFlags) === null || _detail$metaFlags4 === void 0 ? void 0 : _detail$metaFlags4.filesChanged) || ((_detail$metaFlags5 = detail.metaFlags) === null || _detail$metaFlags5 === void 0 ? void 0 : _detail$metaFlags5.notesChanged));
1302
+ if (tab === "history") return Boolean((_detail$metaFlags6 = detail.metaFlags) === null || _detail$metaFlags6 === void 0 ? void 0 : _detail$metaFlags6.historyChanged);
1303
+ return false;
1304
+ }
1305
+ function tabBadgeClass(isUnread) {
1306
+ return isUnread ? "bg-violet-500 text-white" : "border border-white/55 bg-[#2a2048] text-white";
1307
+ }
1308
+ function subtabHasChanges(subtab, detail) {
1309
+ var _detail$metaFlags7, _detail$metaFlags8, _detail$metaFlags9, _detail$metaFlags10;
1310
+ if (subtab === "notes") return Boolean((_detail$metaFlags7 = detail.metaFlags) === null || _detail$metaFlags7 === void 0 ? void 0 : _detail$metaFlags7.notesChanged);
1311
+ if (subtab === "form") return Boolean((_detail$metaFlags8 = detail.metaFlags) === null || _detail$metaFlags8 === void 0 ? void 0 : _detail$metaFlags8.formChanged);
1312
+ if (subtab === "uploaded") return Boolean((_detail$metaFlags9 = detail.metaFlags) === null || _detail$metaFlags9 === void 0 ? void 0 : _detail$metaFlags9.uploadedChanged);
1313
+ if (subtab === "invoice") return Boolean((_detail$metaFlags10 = detail.metaFlags) === null || _detail$metaFlags10 === void 0 ? void 0 : _detail$metaFlags10.invoiceChanged);
1314
+ return false;
1315
+ }
1316
+ function isMainTabUnread(tab, detail, viewedForDetail = {}, viewedSubtabsForDetail = {}) {
1317
+ if (tab === "files") return [
1318
+ "notes",
1319
+ "form",
1320
+ "uploaded",
1321
+ "invoice"
1322
+ ].some((subtab) => subtabHasChanges(subtab, detail) && !viewedSubtabsForDetail[subtab]);
1323
+ return tabHasChanges(tab, detail) && !viewedForDetail[tab];
1324
+ }
1325
+ function showQuickActionLimit(setter) {
1326
+ setter("Maximum 12 quick actions. Please remove some before adding more.");
1327
+ window.clearTimeout(window.__pisellQuickActionLimitTimer);
1328
+ window.__pisellQuickActionLimitTimer = window.setTimeout(() => setter(""), 2200);
1329
+ }
1330
+ function createLongPressHandlers(callback, ms = 520) {
1331
+ let timer = null;
1332
+ let longPressed = false;
1333
+ const start = () => {
1334
+ longPressed = false;
1335
+ timer = setTimeout(() => {
1336
+ longPressed = true;
1337
+ callback();
1338
+ }, ms);
1339
+ };
1340
+ const clear = () => {
1341
+ if (timer) clearTimeout(timer);
1342
+ timer = null;
1343
+ };
1344
+ return {
1345
+ onMouseDown: start,
1346
+ onMouseUp: clear,
1347
+ onMouseLeave: clear,
1348
+ onTouchStart: start,
1349
+ onTouchEnd: clear,
1350
+ onTouchCancel: clear,
1351
+ wasLongPress: () => longPressed
1352
+ };
1353
+ }
1354
+ function getRemainingToneClass(ratio, isLight = false) {
1355
+ if (ratio <= .2) return isLight ? "text-red-600" : "text-red-300";
1356
+ if (ratio <= .4) return isLight ? "text-amber-600" : "text-amber-300";
1357
+ return isLight ? "theme-text-muted" : "text-zinc-400";
1358
+ }
1359
+ function buildGroupedCourtRows(courts, collapsedGroups = {}) {
1360
+ const predefined = ["VIP", "Standard"];
1361
+ const rows = [];
1362
+ const consumedIds = /* @__PURE__ */ new Set();
1363
+ predefined.forEach((group) => {
1364
+ const items = courts.filter((court) => court.type === group);
1365
+ if (items.length === 0) return;
1366
+ items.forEach((c) => consumedIds.add(c.id));
1367
+ rows.push({
1368
+ kind: "group",
1369
+ id: `group-${group}`,
1370
+ label: group,
1371
+ count: items.length,
1372
+ collapsed: !!collapsedGroups[group]
1373
+ });
1374
+ if (!collapsedGroups[group]) items.forEach((court) => rows.push(require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({ kind: "court" }, court), {}, { group })));
1375
+ });
1376
+ /** 低代码接入:桌位 type 多为 Resource / 自定义 groupType,不能只剩 VIP/Standard 两行否则日周视图为空 */
1377
+ const remainder = courts.filter((c) => !consumedIds.has(c.id));
1378
+ const byType = /* @__PURE__ */ new Map();
1379
+ for (const court of remainder) {
1380
+ const label = court.type && String(court.type).trim() !== "" ? String(court.type) : "Resource";
1381
+ const list = byType.get(label) || [];
1382
+ list.push(court);
1383
+ byType.set(label, list);
1384
+ }
1385
+ for (const [label, items] of byType) {
1386
+ if (!items.length) continue;
1387
+ const idSafe = String(label).replace(/\s+/g, "-");
1388
+ rows.push({
1389
+ kind: "group",
1390
+ id: `group-${idSafe}`,
1391
+ label,
1392
+ count: items.length,
1393
+ collapsed: !!collapsedGroups[label]
1394
+ });
1395
+ if (!collapsedGroups[label]) items.forEach((court) => rows.push(require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({ kind: "court" }, court), {}, { group: label })));
1396
+ }
1397
+ return rows;
1398
+ }
1399
+ function buildOverlayBookings(visibleCourtRows, dayKey, bookings, rowTopMap = {}, hourSlots) {
1400
+ const courtRowIndexMap = /* @__PURE__ */ new Map();
1401
+ visibleCourtRows.forEach((row, index) => {
1402
+ if (row.kind === "court") courtRowIndexMap.set(row.id, index);
1403
+ });
1404
+ const gridMin = (hourSlots === null || hourSlots === void 0 ? void 0 : hourSlots.length) ? hourSlots[0] : 0;
1405
+ const gridMaxExclusive = (hourSlots === null || hourSlots === void 0 ? void 0 : hourSlots.length) ? hourSlots[hourSlots.length - 1] + 1 : 24;
1406
+ return visibleCourtRows.flatMap((row) => {
1407
+ if (row.kind !== "court") return [];
1408
+ return bookings.filter((b) => b.courtId === row.id).map((item) => {
1409
+ const seg = getBookingSegmentForDate(item, dayKey);
1410
+ if (!seg) return null;
1411
+ const start = Math.max(seg.startHour, gridMin);
1412
+ const end = Math.min(seg.endHour, gridMaxExclusive);
1413
+ if (end <= start) return null;
1414
+ return {
1415
+ item,
1416
+ rowIndex: courtRowIndexMap.get(row.id) || 0,
1417
+ rowTop: rowTopMap[row.id] || 0,
1418
+ courtId: row.id,
1419
+ start,
1420
+ end,
1421
+ span: end - start,
1422
+ continuesNext: seg.continuesNext,
1423
+ continuesPrev: seg.continuesPrev
1424
+ };
1425
+ }).filter(Boolean);
1426
+ });
1427
+ }
1428
+ function BookingCard({ booking, dayKey, onOpenDetail, onDragStart, onJumpNext }) {
1429
+ const { item, span, start, continuesNext } = booking;
1430
+ const displayTag = getDisplayStatusTag(item, dayKey);
1431
+ const lateMinutes = getLateMinutes(item, dayKey);
1432
+ const stateClass = getBookingStateClasses(item, dayKey);
1433
+ if (item.kind === "block") return /* @__PURE__ */ react.default.createElement("button", {
1434
+ onClick: (e) => {
1435
+ e.stopPropagation();
1436
+ onOpenDetail(item);
1437
+ },
1438
+ className: `absolute inset-x-0 inset-y-0 rounded-2xl px-3 py-3 text-left overflow-hidden ${stateClass}`
1439
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "truncate text-sm font-medium" }, item.name), item.note && /* @__PURE__ */ react.default.createElement("div", { className: "mt-1 truncate text-xs text-zinc-200/90" }, item.note), getBlockMetaLine(item) && /* @__PURE__ */ react.default.createElement("div", { className: "mt-1 truncate text-[10px] text-zinc-300/80" }, getBlockMetaLine(item)));
1440
+ return /* @__PURE__ */ react.default.createElement("button", {
1441
+ draggable: true,
1442
+ onDragStart: (e) => {
1443
+ e.stopPropagation();
1444
+ onDragStart(item);
1445
+ },
1446
+ onClick: (e) => {
1447
+ e.stopPropagation();
1448
+ onOpenDetail(item);
1449
+ },
1450
+ className: `absolute inset-x-0 inset-y-0 rounded-2xl px-4 py-3 text-left overflow-hidden ${stateClass}`
1451
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "pr-24" }, /* @__PURE__ */ react.default.createElement("div", { className: "truncate text-sm font-medium" }, item.name), /* @__PURE__ */ react.default.createElement("div", { className: "mt-1 text-xs opacity-90" }, formatHourLabel(start), " - ", formatHourLabel(start + span)), continuesNext && /* @__PURE__ */ react.default.createElement("button", {
1452
+ onClick: (e) => {
1453
+ e.stopPropagation();
1454
+ onJumpNext();
1455
+ },
1456
+ className: "mt-2 rounded-lg bg-white/10 px-2 py-1 text-[11px] text-violet-100 hover:bg-white/20 w-fit"
1457
+ }, "→ Continues next day")), (displayTag || lateMinutes) && /* @__PURE__ */ react.default.createElement("div", { className: "absolute bottom-3 right-3 flex items-center gap-1.5" }, lateMinutes && displayTag === "late" && /* @__PURE__ */ react.default.createElement("span", { className: "rounded-md bg-black/25 px-2 py-0.5 text-[10px] font-semibold text-white/90 backdrop-blur-[2px] opacity-80" }, lateMinutes, "min"), displayTag && statusTagMeta(displayTag) && /* @__PURE__ */ react.default.createElement("span", { className: `rounded-lg px-2 py-0.5 text-[10px] font-semibold backdrop-blur-[2px] ${statusTagMeta(displayTag).className} ${lateMinutes ? "opacity-80" : ""}` }, statusTagMeta(displayTag).label)));
1458
+ }
1459
+ function BookingCalendarDemo(props = {}) {
1460
+ var _hourSlots$, _groupSelectedSlots$, _groupSelectedSlots$2, _courts$find4, _checkinDraft$startHo, _checkinDraft$endHour2, _checkinDraft$startHo4, _checkinDraft$endHour3, _courts$find5;
1461
+ const allowPersist = require_calendarPersistGuard.useCalendarPersist();
1462
+ const courts = (0, react.useMemo)(() => {
1463
+ const r = props.resources;
1464
+ if (Array.isArray(r) && r.length > 0) return r.map((x) => ({
1465
+ id: x.id,
1466
+ name: x.name,
1467
+ type: x.groupType && String(x.groupType).trim() !== "" ? String(x.groupType) : "Resource"
1468
+ }));
1469
+ return DEFAULT_COURTS;
1470
+ }, [props.resources]);
1471
+ /** 顶栏受控:有 props 用 props,无则回退本地 state(便于 Story 单测) */
1472
+ const isLight = false;
1473
+ const [internalView, setInternalView] = (0, react.useState)("month");
1474
+ const [internalAnchor, setInternalAnchor] = (0, react.useState)(new Date(2026, 2, 31));
1475
+ const view = props.calendarView != null ? props.calendarView : internalView;
1476
+ const anchorDate = (0, react.useMemo)(() => {
1477
+ if (props.anchorDate != null) return new Date(props.anchorDate);
1478
+ return internalAnchor;
1479
+ }, [props.anchorDate != null ? props.anchorDate.getTime() : null, internalAnchor]);
1480
+ const commitView = (v) => {
1481
+ var _props$onCalendarView;
1482
+ (_props$onCalendarView = props.onCalendarViewChange) === null || _props$onCalendarView === void 0 || _props$onCalendarView.call(props, v);
1483
+ if (!props.onCalendarViewChange) setInternalView(v);
1484
+ };
1485
+ const commitAnchor = (d) => {
1486
+ var _props$onAnchorDateCh;
1487
+ (_props$onAnchorDateCh = props.onAnchorDateChange) === null || _props$onAnchorDateCh === void 0 || _props$onAnchorDateCh.call(props, d);
1488
+ if (!props.onAnchorDateChange) setInternalAnchor(d);
1489
+ };
1490
+ const [internalBookings, setBookings] = (0, react.useState)(seedHourlyBookings);
1491
+ const bookings = props.bookings != null ? props.bookings : internalBookings;
1492
+ (0, react.useEffect)(() => {
1493
+ if (!props.onViewportChange) return;
1494
+ const a = new Date(anchorDate);
1495
+ let rangeStart;
1496
+ let rangeEnd;
1497
+ if (view === "month") {
1498
+ rangeStart = new Date(a.getFullYear(), a.getMonth(), 1);
1499
+ rangeEnd = new Date(a.getFullYear(), a.getMonth() + 1, 0);
1500
+ } else if (view === "week") {
1501
+ rangeStart = startOfWeek(a);
1502
+ rangeEnd = addDays(rangeStart, 6);
1503
+ } else {
1504
+ rangeStart = new Date(a);
1505
+ rangeEnd = new Date(a);
1506
+ }
1507
+ props.onViewportChange({
1508
+ view,
1509
+ anchorDate: a,
1510
+ rangeStart,
1511
+ rangeEnd
1512
+ });
1513
+ }, [
1514
+ view,
1515
+ anchorDate,
1516
+ props.onViewportChange
1517
+ ]);
1518
+ const [selectedFreeSlots, setSelectedFreeSlots] = (0, react.useState)([]);
1519
+ const [selectedBlockSlots, setSelectedBlockSlots] = (0, react.useState)([]);
1520
+ const [focusedCourtId, setFocusedCourtId] = (0, react.useState)(null);
1521
+ const [showBlockPanel, setShowBlockPanel] = (0, react.useState)(false);
1522
+ const [blockNote, setBlockNote] = (0, react.useState)("");
1523
+ const [blockBy, setBlockBy] = (0, react.useState)("Allen");
1524
+ const [blockMode, setBlockMode] = (0, react.useState)("single");
1525
+ const [blockRangeStart, setBlockRangeStart] = (0, react.useState)("2026-03-31");
1526
+ const [blockRangeEnd, setBlockRangeEnd] = (0, react.useState)("2026-04-30");
1527
+ const [blockWeekdays, setBlockWeekdays] = (0, react.useState)([3]);
1528
+ const [transitioningToDay, setTransitioningToDay] = (0, react.useState)(null);
1529
+ const [navDirection, setNavDirection] = (0, react.useState)(0);
1530
+ const [detailItem, setDetailItem] = (0, react.useState)(null);
1531
+ const [detailMode, setDetailMode] = (0, react.useState)("quick");
1532
+ const [detailTab, setDetailTab] = (0, react.useState)("summary");
1533
+ const [filesSubtab, setFilesSubtab] = (0, react.useState)("notes");
1534
+ const [preferDrawerOpen, setPreferDrawerOpen] = (0, react.useState)(false);
1535
+ const [defaultDetailTab, setDefaultDetailTab] = (0, react.useState)("summary");
1536
+ const [preferQuickPopup, setPreferQuickPopup] = (0, react.useState)(true);
1537
+ const [calendarShiftedForDrawer, setCalendarShiftedForDrawer] = (0, react.useState)(false);
1538
+ const [viewedTabState, setViewedTabState] = (0, react.useState)({});
1539
+ const [viewedSubtabState, setViewedSubtabState] = (0, react.useState)({});
1540
+ const [quickActionLimitMessage, setQuickActionLimitMessage] = (0, react.useState)("");
1541
+ const [pinnedActionLabels, setPinnedActionLabels] = (0, react.useState)([
1542
+ "Check in",
1543
+ "Order detail",
1544
+ "Reschedule",
1545
+ "Pay now",
1546
+ "Send reminder",
1547
+ "Print receipt"
1548
+ ]);
1549
+ const [overflowPopover, setOverflowPopover] = (0, react.useState)(null);
1550
+ const [overflowListModal, setOverflowListModal] = (0, react.useState)(null);
1551
+ const [draggingItem, setDraggingItem] = (0, react.useState)(null);
1552
+ const [moveConfirm, setMoveConfirm] = (0, react.useState)(null);
1553
+ const [moveDraft, setMoveDraft] = (0, react.useState)(null);
1554
+ const [conflictPicker, setConflictPicker] = (0, react.useState)(null);
1555
+ const [blockConflict, setBlockConflict] = (0, react.useState)(null);
1556
+ const [checkinModal, setCheckinModal] = (0, react.useState)(null);
1557
+ const [checkinDraft, setCheckinDraft] = (0, react.useState)(null);
1558
+ const [summaryPayMenuOpen, setSummaryPayMenuOpen] = (0, react.useState)(false);
1559
+ const [showActionsOverlay, setShowActionsOverlay] = (0, react.useState)(false);
1560
+ const [guestRowMenu, setGuestRowMenu] = (0, react.useState)(null);
1561
+ const [guestBulkActionOpen, setGuestBulkActionOpen] = (0, react.useState)(false);
1562
+ const [guestMockRows, setGuestMockRows] = (0, react.useState)([]);
1563
+ const [selectedFileIds, setSelectedFileIds] = (0, react.useState)([]);
1564
+ const [filePreviewItem, setFilePreviewItem] = (0, react.useState)(null);
1565
+ const [mergeOrderModal, setMergeOrderModal] = (0, react.useState)(null);
1566
+ const [mergeOrderDraft, setMergeOrderDraft] = (0, react.useState)({
1567
+ targetBookingId: "",
1568
+ keepSourceOpen: false
1569
+ });
1570
+ const [customerPickerOpen, setCustomerPickerOpen] = (0, react.useState)(false);
1571
+ const [customerSearch, setCustomerSearch] = (0, react.useState)("");
1572
+ const [selectedCustomer, setSelectedCustomer] = (0, react.useState)(null);
1573
+ const [detailPrefOpen, setDetailPrefOpen] = (0, react.useState)(false);
1574
+ const [summaryChangeMenuOpen, setSummaryChangeMenuOpen] = (0, react.useState)(false);
1575
+ const [noteOverrides, setNoteOverrides] = (0, react.useState)({});
1576
+ const [noteEditor, setNoteEditor] = (0, react.useState)(null);
1577
+ const [dayViewport, setDayViewport] = (0, react.useState)({
1578
+ scrollLeft: 0,
1579
+ scrollTop: 0,
1580
+ clientWidth: 0,
1581
+ clientHeight: 0
1582
+ });
1583
+ const [collapsedGroups, setCollapsedGroups] = (0, react.useState)({
1584
+ VIP: false,
1585
+ Standard: false
1586
+ });
1587
+ const [dayDragging, setDayDragging] = (0, react.useState)(false);
1588
+ (0, react.useEffect)(() => {
1589
+ if (!detailItem) return;
1590
+ const detail = getBookingDetailData(detailItem, courts);
1591
+ const baseCount = Math.max(detail.guestCount || 0, 3);
1592
+ setGuestMockRows(Array.from({ length: baseCount }, (_, index) => {
1593
+ var _detail$customer;
1594
+ return {
1595
+ id: `guest-mock-${detailItem.id}-${index + 1}`,
1596
+ name: index === 0 ? ((_detail$customer = detail.customer) === null || _detail$customer === void 0 ? void 0 : _detail$customer.name) || `Guest ${index + 1}` : `Guest ${index + 1}`,
1597
+ note: index === 0 ? "Primary booking guest" : "Guest list",
1598
+ checkedIn: index < (detail.checkedInCount || 0),
1599
+ noShow: false,
1600
+ removed: false
1601
+ };
1602
+ }));
1603
+ setGuestRowMenu(null);
1604
+ setGuestBulkActionOpen(false);
1605
+ setSummaryChangeMenuOpen(false);
1606
+ setSelectedFileIds([]);
1607
+ setFilePreviewItem(null);
1608
+ }, [detailItem]);
1609
+ (0, react.useEffect)(() => {
1610
+ setSelectedFileIds([]);
1611
+ setFilePreviewItem(null);
1612
+ }, [filesSubtab]);
1613
+ const dayScrollRef = (0, react.useRef)(null);
1614
+ const dayDragRef = (0, react.useRef)({
1615
+ dragging: false,
1616
+ startX: 0,
1617
+ startY: 0,
1618
+ startLeft: 0,
1619
+ startTop: 0,
1620
+ moved: false
1621
+ });
1622
+ const blockPanelRef = (0, react.useRef)(null);
1623
+ const detailPanelRef = (0, react.useRef)(null);
1624
+ const guestBulkActionRef = (0, react.useRef)(null);
1625
+ const overflowPanelRef = (0, react.useRef)(null);
1626
+ const moveConfirmRef = (0, react.useRef)(null);
1627
+ const conflictPickerRef = (0, react.useRef)(null);
1628
+ const blockConflictRef = (0, react.useRef)(null);
1629
+ const checkinModalRef = (0, react.useRef)(null);
1630
+ const mergeOrderModalRef = (0, react.useRef)(null);
1631
+ const customerPickerRef = (0, react.useRef)(null);
1632
+ const detailPrefRef = (0, react.useRef)(null);
1633
+ const summaryChangeMenuRef = (0, react.useRef)(null);
1634
+ const noteEditorRef = (0, react.useRef)(null);
1635
+ const blockStartInputRef = (0, react.useRef)(null);
1636
+ const blockEndInputRef = (0, react.useRef)(null);
1637
+ const visibleCourts = (0, react.useMemo)(() => courts, [courts]);
1638
+ const visibleCourtRows = (0, react.useMemo)(() => buildGroupedCourtRows(visibleCourts, collapsedGroups), [visibleCourts, collapsedGroups]);
1639
+ const dayRowHeights = (0, react.useMemo)(() => visibleCourtRows.map((row) => row.kind === "group" ? groupRowHeight : dayRowHeight), [visibleCourtRows]);
1640
+ const dayRowTopMap = (0, react.useMemo)(() => {
1641
+ let acc = 0;
1642
+ const map = {};
1643
+ visibleCourtRows.forEach((row, index) => {
1644
+ map[row.id] = acc;
1645
+ acc += dayRowHeights[index] || dayRowHeight;
1646
+ });
1647
+ return map;
1648
+ }, [visibleCourtRows, dayRowHeights]);
1649
+ const weekDays = (0, react.useMemo)(() => rangeDays(anchorDate), [anchorDate]);
1650
+ (0, react.useMemo)(() => new Set(weekDays.map((d) => fmtDate(d))), [weekDays]);
1651
+ const dayKey = fmtDate(anchorDate);
1652
+ const hourSlots = (0, react.useMemo)(() => {
1653
+ var _props$timelineRange;
1654
+ return require_index.buildCalendarHourSlotsFromRange((_props$timelineRange = props.timelineRange) !== null && _props$timelineRange !== void 0 ? _props$timelineRange : DEFAULT_CALENDAR_TIMELINE, anchorDate);
1655
+ }, [props.timelineRange, anchorDate]);
1656
+ const firstTimelineHour = (_hourSlots$ = hourSlots[0]) !== null && _hourSlots$ !== void 0 ? _hourSlots$ : 0;
1657
+ const endTimelineExclusive = hourSlots.length ? hourSlots[hourSlots.length - 1] + 1 : 24;
1658
+ const isBusinessHour = (h) => isHourInTimelineSlots(h, hourSlots);
1659
+ const monthDays = (0, react.useMemo)(() => monthGrid(anchorDate, bookings, courts, hourSlots), [
1660
+ anchorDate,
1661
+ bookings,
1662
+ courts,
1663
+ hourSlots
1664
+ ]);
1665
+ const timeOptions = (0, react.useMemo)(() => {
1666
+ var _hourSlots$2;
1667
+ return buildTimeOptions((_hourSlots$2 = hourSlots[0]) !== null && _hourSlots$2 !== void 0 ? _hourSlots$2 : 8, hourSlots.length ? hourSlots[hourSlots.length - 1] + 1 : 20);
1668
+ }, [hourSlots]);
1669
+ const overlayBookings = (0, react.useMemo)(() => buildOverlayBookings(visibleCourtRows, dayKey, bookings, dayRowTopMap, hourSlots), [
1670
+ visibleCourtRows,
1671
+ dayKey,
1672
+ bookings,
1673
+ dayRowTopMap,
1674
+ hourSlots
1675
+ ]);
1676
+ const dayRowRemainingByCourt = (0, react.useMemo)(() => {
1677
+ const total = hourSlots.length;
1678
+ return Object.fromEntries(visibleCourtRows.filter((row) => row.kind === "court").map((court) => {
1679
+ const occupied = hourSlots.filter((hour) => isBusinessHour(hour) && dayOccupancy(court.id, dayKey, bookings, hourSlots)[hour]).length;
1680
+ const remaining = Math.max(0, total - occupied);
1681
+ const ratio = total > 0 ? remaining / total : 0;
1682
+ return [court.id, {
1683
+ remaining,
1684
+ total,
1685
+ ratio
1686
+ }];
1687
+ }));
1688
+ }, [
1689
+ visibleCourtRows,
1690
+ dayKey,
1691
+ bookings,
1692
+ hourSlots
1693
+ ]);
1694
+ const dayHourRemaining = (0, react.useMemo)(() => {
1695
+ const total = visibleCourtRows.filter((row) => row.kind === "court").length;
1696
+ return Object.fromEntries(hourSlots.map((hour) => {
1697
+ if (!isBusinessHour(hour)) return [hour, {
1698
+ remaining: 0,
1699
+ total,
1700
+ ratio: 0
1701
+ }];
1702
+ const remaining = visibleCourtRows.filter((row) => row.kind === "court").filter((court) => !dayOccupancy(court.id, dayKey, bookings, hourSlots)[hour]).length;
1703
+ return [hour, {
1704
+ remaining,
1705
+ total,
1706
+ ratio: total > 0 ? remaining / total : 0
1707
+ }];
1708
+ }));
1709
+ }, [
1710
+ visibleCourtRows,
1711
+ dayKey,
1712
+ bookings,
1713
+ hourSlots
1714
+ ]);
1715
+ const dayContentWidth = frozenColWidth + hourSlots.length * dayColWidth;
1716
+ const dayContentHeight = dayHeaderHeight + dayRowHeights.reduce((sum, h) => sum + h, 0);
1717
+ const dayEdgeStats = (0, react.useMemo)(() => {
1718
+ const viewportLeft = dayViewport.scrollLeft;
1719
+ const viewportRight = dayViewport.scrollLeft + dayViewport.clientWidth;
1720
+ const viewportTop = dayViewport.scrollTop;
1721
+ const viewportBottom = dayViewport.scrollTop + dayViewport.clientHeight;
1722
+ const stats = {
1723
+ left: 0,
1724
+ right: 0,
1725
+ top: 0,
1726
+ bottom: 0,
1727
+ showLeft: false,
1728
+ showRight: false,
1729
+ showTop: false,
1730
+ showBottom: false
1731
+ };
1732
+ if (!dayViewport.clientWidth || !dayViewport.clientHeight) return stats;
1733
+ stats.showLeft = viewportLeft > 8;
1734
+ stats.showRight = viewportRight < dayContentWidth - 8;
1735
+ stats.showTop = viewportTop > 8;
1736
+ stats.showBottom = viewportBottom < dayContentHeight - 8;
1737
+ overlayBookings.forEach((booking) => {
1738
+ const bookingLeft = frozenColWidth + (booking.start - firstTimelineHour) * dayColWidth;
1739
+ const bookingRight = bookingLeft + booking.span * dayColWidth;
1740
+ const bookingTop = booking.rowIndex * dayRowHeight + 10;
1741
+ const bookingBottom = bookingTop + (dayRowHeight - 20);
1742
+ if (stats.showLeft && bookingRight < viewportLeft) stats.left += 1;
1743
+ if (stats.showRight && bookingLeft > viewportRight) stats.right += 1;
1744
+ if (stats.showTop && bookingBottom < viewportTop) stats.top += 1;
1745
+ if (stats.showBottom && bookingTop > viewportBottom) stats.bottom += 1;
1746
+ });
1747
+ return stats;
1748
+ }, [
1749
+ dayViewport,
1750
+ overlayBookings,
1751
+ dayContentWidth,
1752
+ dayContentHeight,
1753
+ firstTimelineHour
1754
+ ]);
1755
+ (0, react.useEffect)(() => {
1756
+ function handleOutside(e) {
1757
+ var _target$closest;
1758
+ const target = e.target;
1759
+ const hasOverlayOpen = Boolean(noteEditor || customerPickerOpen || moveConfirm || conflictPicker || blockConflict || checkinModal || mergeOrderModal || filePreviewItem || overflowListModal || showActionsOverlay || guestBulkActionOpen);
1760
+ if (showBlockPanel && blockPanelRef.current && !blockPanelRef.current.contains(target)) setShowBlockPanel(false);
1761
+ if (showActionsOverlay) {
1762
+ if (detailPanelRef.current && !detailPanelRef.current.contains(target) && !(noteEditorRef.current && noteEditorRef.current.contains(target))) setShowActionsOverlay(false);
1763
+ } else if (detailItem && detailPanelRef.current && !detailPanelRef.current.contains(target) && !hasOverlayOpen && !(noteEditorRef.current && noteEditorRef.current.contains(target))) setDetailItem(null);
1764
+ if (overflowPopover && overflowPanelRef.current && !overflowPanelRef.current.contains(target)) setOverflowPopover(null);
1765
+ if (overflowListModal && overflowPanelRef.current && !overflowPanelRef.current.contains(target)) setOverflowListModal(null);
1766
+ if (moveConfirm && moveConfirmRef.current && !moveConfirmRef.current.contains(target)) setMoveConfirm(null);
1767
+ if (conflictPicker && conflictPickerRef.current && !conflictPickerRef.current.contains(target)) setConflictPicker(null);
1768
+ if (blockConflict && blockConflictRef.current && !blockConflictRef.current.contains(target)) setBlockConflict(null);
1769
+ if (checkinModal && checkinModalRef.current && !checkinModalRef.current.contains(target)) setCheckinModal(null);
1770
+ if (mergeOrderModal && mergeOrderModalRef.current && !mergeOrderModalRef.current.contains(target)) setMergeOrderModal(null);
1771
+ if (customerPickerOpen && customerPickerRef.current && !customerPickerRef.current.contains(target)) setCustomerPickerOpen(false);
1772
+ if (detailPrefOpen && detailPrefRef.current && !detailPrefRef.current.contains(target)) setDetailPrefOpen(false);
1773
+ if (summaryChangeMenuOpen && summaryChangeMenuRef.current && !summaryChangeMenuRef.current.contains(target)) setSummaryChangeMenuOpen(false);
1774
+ if (guestBulkActionOpen && guestBulkActionRef.current && !guestBulkActionRef.current.contains(target)) setGuestBulkActionOpen(false);
1775
+ if (guestRowMenu && !((_target$closest = target.closest) === null || _target$closest === void 0 ? void 0 : _target$closest.call(target, "[data-guest-row-menu]"))) setGuestRowMenu(null);
1776
+ }
1777
+ document.addEventListener("mousedown", handleOutside);
1778
+ return () => document.removeEventListener("mousedown", handleOutside);
1779
+ }, [
1780
+ showBlockPanel,
1781
+ detailItem,
1782
+ showActionsOverlay,
1783
+ overflowPopover,
1784
+ overflowListModal,
1785
+ moveConfirm,
1786
+ conflictPicker,
1787
+ blockConflict,
1788
+ checkinModal,
1789
+ mergeOrderModal,
1790
+ customerPickerOpen,
1791
+ detailPrefOpen,
1792
+ summaryChangeMenuOpen,
1793
+ guestBulkActionOpen,
1794
+ guestRowMenu,
1795
+ noteEditor
1796
+ ]);
1797
+ (0, react.useEffect)(() => {
1798
+ if (view !== "day" || !focusedCourtId || !dayScrollRef.current) return;
1799
+ const timer = setTimeout(() => {
1800
+ var _dayScrollRef$current;
1801
+ const el = (_dayScrollRef$current = dayScrollRef.current) === null || _dayScrollRef$current === void 0 ? void 0 : _dayScrollRef$current.querySelector(`[data-court-row="${focusedCourtId}"]`);
1802
+ if (el) el.scrollIntoView({
1803
+ behavior: "smooth",
1804
+ block: "start"
1805
+ });
1806
+ }, 180);
1807
+ return () => clearTimeout(timer);
1808
+ }, [
1809
+ view,
1810
+ focusedCourtId,
1811
+ anchorDate
1812
+ ]);
1813
+ (0, react.useEffect)(() => {
1814
+ if (!showBlockPanel) return;
1815
+ setBlockRangeStart(dayKey);
1816
+ setBlockRangeEnd(dayKey);
1817
+ }, [showBlockPanel, dayKey]);
1818
+ (0, react.useEffect)(() => {
1819
+ if (!transitioningToDay) return;
1820
+ const timer = setTimeout(() => setTransitioningToDay(null), 280);
1821
+ return () => clearTimeout(timer);
1822
+ }, [transitioningToDay]);
1823
+ (0, react.useEffect)(() => {
1824
+ if (view !== "day" || !dayScrollRef.current) return;
1825
+ const el = dayScrollRef.current;
1826
+ const update = () => setDayViewport({
1827
+ scrollLeft: el.scrollLeft,
1828
+ scrollTop: el.scrollTop,
1829
+ clientWidth: el.clientWidth,
1830
+ clientHeight: el.clientHeight
1831
+ });
1832
+ update();
1833
+ el.addEventListener("scroll", update, { passive: true });
1834
+ window.addEventListener("resize", update);
1835
+ window.addEventListener("mousemove", handleDayMouseMove);
1836
+ window.addEventListener("mouseup", handleDayMouseUp);
1837
+ return () => {
1838
+ el.removeEventListener("scroll", update);
1839
+ window.removeEventListener("resize", update);
1840
+ window.removeEventListener("mousemove", handleDayMouseMove);
1841
+ window.removeEventListener("mouseup", handleDayMouseUp);
1842
+ };
1843
+ }, [
1844
+ view,
1845
+ anchorDate,
1846
+ visibleCourts.length
1847
+ ]);
1848
+ function isFreeSelected(courtId, hour) {
1849
+ return selectedFreeSlots.some((slot) => slot.courtId === courtId && slot.date === dayKey && slot.hour === hour);
1850
+ }
1851
+ function isBlockSelected(courtId, hour) {
1852
+ return selectedBlockSlots.some((slot) => slot.courtId === courtId && slot.date === dayKey && slot.hour === hour);
1853
+ }
1854
+ function goToDayFromCell(day, courtId, source) {
1855
+ setNavDirection(day > anchorDate ? 1 : -1);
1856
+ setTransitioningToDay({ source });
1857
+ commitAnchor(day);
1858
+ setFocusedCourtId(courtId || null);
1859
+ commitView("day");
1860
+ }
1861
+ function openBookingDetail(item) {
1862
+ var _props$onBookingClick;
1863
+ if (((_props$onBookingClick = props.onBookingClick) === null || _props$onBookingClick === void 0 ? void 0 : _props$onBookingClick.call(props, item)) === true) return;
1864
+ setDetailItem(item);
1865
+ setOverflowPopover(null);
1866
+ setDetailTab(defaultDetailTab);
1867
+ setFilesSubtab("notes");
1868
+ const nextMode = preferDrawerOpen && !preferQuickPopup ? "drawer" : "quick";
1869
+ setDetailMode(nextMode);
1870
+ setCalendarShiftedForDrawer(nextMode === "drawer");
1871
+ const key = item.id || item.bookingId || item.orderNumber;
1872
+ const initialTab = defaultDetailTab;
1873
+ setViewedTabState((prev) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev), {}, { [key]: require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev[key] || {}), {}, { [initialTab]: true }) }));
1874
+ setViewedSubtabState((prev) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev), {}, { [key]: require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev[key] || {}), {}, { form: true }) }));
1875
+ }
1876
+ function toggleSlot(courtId, hour) {
1877
+ const existing = dayOccupancy(courtId, dayKey, bookings, hourSlots)[hour];
1878
+ const court = courts.find((c) => c.id === courtId);
1879
+ const slot = {
1880
+ courtId,
1881
+ court: court === null || court === void 0 ? void 0 : court.name,
1882
+ date: dayKey,
1883
+ hour
1884
+ };
1885
+ if (!existing) {
1886
+ setSelectedFreeSlots((prev) => prev.some((s) => sameSlot(s, slot)) ? prev.filter((s) => !sameSlot(s, slot)) : [...prev, slot]);
1887
+ return;
1888
+ }
1889
+ if (existing.kind === "block") setSelectedBlockSlots((prev) => prev.some((s) => sameSlot(s, slot)) ? prev.filter((s) => !sameSlot(s, slot)) : [...prev, slot]);
1890
+ }
1891
+ function deselectAll() {
1892
+ setSelectedFreeSlots([]);
1893
+ setSelectedBlockSlots([]);
1894
+ }
1895
+ function createBookingFromSelection() {
1896
+ if (!allowPersist("createBooking")) return;
1897
+ if (selectedFreeSlots.length === 0) return;
1898
+ const newBookings = groupSelectedSlots(selectedFreeSlots).map((slot, idx) => ({
1899
+ id: `new-${slot.courtId}-${slot.date}-${slot.startHour}-${idx}`,
1900
+ courtId: slot.courtId,
1901
+ date: slot.date,
1902
+ startHour: slot.startHour,
1903
+ endHour: slot.endHour,
1904
+ name: "New Booking",
1905
+ kind: "booking"
1906
+ }));
1907
+ setBookings((prev) => [...newBookings, ...prev]);
1908
+ setSelectedFreeSlots([]);
1909
+ }
1910
+ function openSelectedBlocks() {
1911
+ if (!allowPersist("removeBlocks")) return;
1912
+ if (selectedBlockSlots.length === 0) return;
1913
+ const selectedSet = new Set(selectedBlockSlots.map((s) => `${s.courtId}-${s.date}-${s.hour}`));
1914
+ setBookings((prev) => prev.filter((item) => {
1915
+ if (item.kind !== "block") return true;
1916
+ getBookingSegmentForDate(item, item.date);
1917
+ return !Array.from({ length: item.endHour - item.startHour }, (_, i) => item.startHour + i).some((h) => selectedSet.has(`${item.courtId}-${item.date}-${h}`));
1918
+ }));
1919
+ setSelectedBlockSlots([]);
1920
+ }
1921
+ function toggleBlockWeekday(day) {
1922
+ setBlockWeekdays((prev) => prev.includes(day) ? prev.filter((d) => d !== day) : [...prev, day]);
1923
+ }
1924
+ function createBlockFromSelection() {
1925
+ if (selectedFreeSlots.length === 0) return;
1926
+ const baseGroups = groupSelectedSlots(selectedFreeSlots);
1927
+ const nextBlocks = [];
1928
+ if (blockMode === "single") baseGroups.forEach((slot, idx) => {
1929
+ nextBlocks.push({
1930
+ id: `block-single-${slot.courtId}-${slot.date}-${slot.startHour}-${idx}`,
1931
+ courtId: slot.courtId,
1932
+ date: slot.date,
1933
+ startHour: slot.startHour,
1934
+ endHour: slot.endHour,
1935
+ name: blockNote || "Block",
1936
+ note: blockNote || "",
1937
+ blockBy,
1938
+ blockedAt: dayKey,
1939
+ kind: "block"
1940
+ });
1941
+ });
1942
+ else {
1943
+ const start = parseDate(blockRangeStart);
1944
+ const end = parseDate(blockRangeEnd);
1945
+ const baseByKey = /* @__PURE__ */ new Map();
1946
+ baseGroups.forEach((slot) => baseByKey.set(`${slot.courtId}-${slot.startHour}-${slot.endHour}`, slot));
1947
+ for (let d = new Date(start); d <= end; d = addDays(d, 1)) {
1948
+ if (!blockWeekdays.includes(d.getDay())) continue;
1949
+ const dateKey = fmtDate(d);
1950
+ baseByKey.forEach((slot) => {
1951
+ nextBlocks.push({
1952
+ id: `block-repeat-${slot.courtId}-${dateKey}-${slot.startHour}-${slot.endHour}`,
1953
+ courtId: slot.courtId,
1954
+ date: dateKey,
1955
+ startHour: slot.startHour,
1956
+ endHour: slot.endHour,
1957
+ name: blockNote || "Block",
1958
+ note: blockNote || "",
1959
+ blockBy,
1960
+ blockedAt: dayKey,
1961
+ kind: "block"
1962
+ });
1963
+ });
1964
+ }
1965
+ }
1966
+ const conflicts = nextBlocks.flatMap((blk) => overlappingBookings(bookings, blk.courtId, blk.date, blk.startHour, blk.endHour));
1967
+ if (conflicts.length > 0) {
1968
+ setBlockConflict({
1969
+ nextBlocks,
1970
+ conflicts
1971
+ });
1972
+ return;
1973
+ }
1974
+ if (!allowPersist("createBlock")) return;
1975
+ setBookings((prev) => [...nextBlocks, ...prev]);
1976
+ setSelectedFreeSlots([]);
1977
+ setShowBlockPanel(false);
1978
+ setBlockNote("");
1979
+ }
1980
+ function confirmBlockWithUnsetCourts() {
1981
+ if (!blockConflict) return;
1982
+ if (!allowPersist("confirmBlockWithConflicts")) return;
1983
+ const conflictIds = new Set(blockConflict.conflicts.map((b) => b.id));
1984
+ setBookings((prev) => [...blockConflict.nextBlocks, ...prev.map((b) => conflictIds.has(b.id) ? require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, b), {}, {
1985
+ courtId: null,
1986
+ name: `${b.name}(待重新指定资源)`
1987
+ }) : b)]);
1988
+ setBlockConflict(null);
1989
+ setSelectedFreeSlots([]);
1990
+ setShowBlockPanel(false);
1991
+ }
1992
+ function handleDropMove(targetCourtId, targetDate, targetHour) {
1993
+ if (!draggingItem) return;
1994
+ const duration = draggingItem.endHour - draggingItem.startHour;
1995
+ const nextStart = targetHour;
1996
+ const nextEnd = targetHour + duration;
1997
+ if (!isBusinessHour(nextStart) || nextEnd > endTimelineExclusive) return;
1998
+ const targetCourt = targetCourtId !== null && targetCourtId !== void 0 ? targetCourtId : draggingItem.courtId;
1999
+ if (hasConflict(bookings, targetCourt, targetDate, nextStart, nextEnd, draggingItem.id)) {
2000
+ setConflictPicker({
2001
+ item: draggingItem,
2002
+ targetCourtId: targetCourt,
2003
+ targetDate,
2004
+ targetHour
2005
+ });
2006
+ setDraggingItem(null);
2007
+ return;
2008
+ }
2009
+ setMoveConfirm({
2010
+ item: draggingItem,
2011
+ targetCourtId: targetCourt,
2012
+ targetDate,
2013
+ targetHour
2014
+ });
2015
+ setMoveDraft({
2016
+ targetCourtId: targetCourt,
2017
+ targetDate,
2018
+ targetHour
2019
+ });
2020
+ setDraggingItem(null);
2021
+ }
2022
+ function handleGridDropMove(targetDate, targetCourtId = null) {
2023
+ if (!draggingItem || draggingItem.kind === "block") return;
2024
+ handleDropMove(targetCourtId !== null && targetCourtId !== void 0 ? targetCourtId : draggingItem.courtId, targetDate, draggingItem.startHour);
2025
+ }
2026
+ function confirmMove() {
2027
+ if (!moveConfirm || !moveDraft) return;
2028
+ if (!allowPersist("moveBooking")) return;
2029
+ const { item } = moveConfirm;
2030
+ const { targetCourtId, targetDate, targetHour } = moveDraft;
2031
+ const duration = item.endHour - item.startHour;
2032
+ setBookings((prev) => prev.map((b) => b.id === item.id ? require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, b), {}, {
2033
+ courtId: targetCourtId,
2034
+ date: targetDate,
2035
+ startHour: targetHour,
2036
+ endHour: targetHour + duration
2037
+ }) : b));
2038
+ setMoveConfirm(null);
2039
+ setMoveDraft(null);
2040
+ }
2041
+ function applyConflictMove(newCourtId, newHour) {
2042
+ if (!conflictPicker) return;
2043
+ if (!allowPersist("applyConflictMove")) return;
2044
+ const { item, targetDate } = conflictPicker;
2045
+ const duration = item.endHour - item.startHour;
2046
+ setBookings((prev) => prev.map((b) => b.id === item.id ? require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, b), {}, {
2047
+ courtId: newCourtId,
2048
+ date: targetDate,
2049
+ startHour: newHour,
2050
+ endHour: newHour + duration
2051
+ }) : b));
2052
+ setConflictPicker(null);
2053
+ }
2054
+ function handleDayMouseDown(e) {
2055
+ if (!dayScrollRef.current) return;
2056
+ if (e.target.closest("button, input, select, textarea, a, label")) return;
2057
+ const el = dayScrollRef.current;
2058
+ dayDragRef.current = {
2059
+ dragging: true,
2060
+ startX: e.clientX,
2061
+ startY: e.clientY,
2062
+ startLeft: el.scrollLeft,
2063
+ startTop: el.scrollTop,
2064
+ moved: false
2065
+ };
2066
+ setDayDragging(true);
2067
+ e.preventDefault();
2068
+ }
2069
+ function handleDayMouseMove(e) {
2070
+ if (!dayDragRef.current.dragging || !dayScrollRef.current) return;
2071
+ const dx = e.clientX - dayDragRef.current.startX;
2072
+ const dy = e.clientY - dayDragRef.current.startY;
2073
+ if (Math.abs(dx) > 3 || Math.abs(dy) > 3) dayDragRef.current.moved = true;
2074
+ dayScrollRef.current.scrollLeft = dayDragRef.current.startLeft - dx;
2075
+ dayScrollRef.current.scrollTop = dayDragRef.current.startTop - dy;
2076
+ }
2077
+ function handleDayMouseUp() {
2078
+ dayDragRef.current.dragging = false;
2079
+ setDayDragging(false);
2080
+ }
2081
+ function scrollDayBy(dx, dy) {
2082
+ if (!dayScrollRef.current) return;
2083
+ dayScrollRef.current.scrollBy({
2084
+ left: dx,
2085
+ top: dy,
2086
+ behavior: "smooth"
2087
+ });
2088
+ }
2089
+ (0, react.useEffect)(() => {
2090
+ if (!detailItem || detailMode !== "drawer") return;
2091
+ const key = detailItem.id;
2092
+ setViewedTabState((prev) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev), {}, { [key]: require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev[key] || {}), {}, { [detailTab]: true }) }));
2093
+ }, [
2094
+ detailItem,
2095
+ detailMode,
2096
+ detailTab
2097
+ ]);
2098
+ (0, react.useEffect)(() => {
2099
+ if (!detailItem || detailMode !== "drawer" || detailTab !== "files") return;
2100
+ const key = detailItem.id;
2101
+ setViewedSubtabState((prev) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev), {}, { [key]: require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev[key] || {}), {}, { [filesSubtab]: true }) }));
2102
+ }, [
2103
+ detailItem,
2104
+ detailMode,
2105
+ detailTab,
2106
+ filesSubtab
2107
+ ]);
2108
+ return /* @__PURE__ */ react.default.createElement(antd.Spin, {
2109
+ spinning: Boolean(props.loading),
2110
+ wrapperClassName: "pisell-rb-cal-spin-wrap flex min-h-0 flex-1 flex-col"
2111
+ }, /* @__PURE__ */ react.default.createElement(LayoutGroup, null, /* @__PURE__ */ react.default.createElement("style", null, `
2112
+ .pisell-scroll-hidden {
2113
+ scrollbar-width: none;
2114
+ -ms-overflow-style: none;
2115
+ }
2116
+ .pisell-scroll-hidden::-webkit-scrollbar {
2117
+ width: 0;
2118
+ height: 0;
2119
+ display: none;
2120
+ }
2121
+
2122
+ /* RecordBoard 嵌入:Spin 包装须把 flex-1/min-h-0 传到 theme-root */
2123
+ .pisell-rb-cal-spin-wrap {
2124
+ flex: 1 1 0%;
2125
+ min-height: 0;
2126
+ display: flex;
2127
+ flex-direction: column;
2128
+ }
2129
+ .pisell-rb-cal-spin-wrap .pisell-lowcode-spin-container,
2130
+ .pisell-rb-cal-spin-wrap .ant-spin-container {
2131
+ flex: 1 1 0%;
2132
+ min-height: 0;
2133
+ display: flex;
2134
+ flex-direction: column;
2135
+ }
2136
+
2137
+ .theme-root {
2138
+ --bg-app: #060913;
2139
+ --bg-shell: #080D1B;
2140
+ --bg-header: #10172A;
2141
+ --bg-toolbar: #0D1325;
2142
+ --bg-panel: #0D1325;
2143
+ --bg-panel-soft: #10172A;
2144
+ --bg-panel-alt: #10172A;
2145
+ --bg-elevated: #09101D;
2146
+ --bg-grid-cell: #0A0F1D;
2147
+ --bg-grid-muted: #080D1B;
2148
+ --bg-sticky: #09101D;
2149
+ --bg-input: #0D1325;
2150
+ --border-soft: rgba(255,255,255,0.10);
2151
+ --border-strong: rgba(255,255,255,0.16);
2152
+ --text-main: #FFFFFF;
2153
+ --text-soft: rgba(255,255,255,0.72);
2154
+ --text-muted: rgba(255,255,255,0.45);
2155
+ --text-faint: rgba(255,255,255,0.15);
2156
+ --shadow-heavy: 0 24px 80px rgba(0,0,0,0.42);
2157
+ --brand-primary: #7F56DA;
2158
+ --brand-deep: #6941C6;
2159
+ --brand-light: #B692F6;
2160
+ --brand-surface: rgba(127, 86, 218, 0.12);
2161
+ --success-text: #32D583;
2162
+ --success-surface: rgba(18, 183, 106, 0.10);
2163
+ --success-border: rgba(50, 213, 131, 0.22);
2164
+ --warning-text: #FDB022;
2165
+ --warning-surface: rgba(247, 144, 9, 0.10);
2166
+ --warning-border: rgba(253, 176, 34, 0.22);
2167
+ --danger-text: #F97066;
2168
+ --danger-surface: rgba(240, 68, 56, 0.10);
2169
+ --danger-border: rgba(240, 68, 56, 0.22);
2170
+ --info-text: #53B1FD;
2171
+ --info-surface: rgba(46, 144, 250, 0.10);
2172
+ --info-border: rgba(83, 177, 253, 0.24);
2173
+ --pickup-text: #F670C7;
2174
+ --pickup-surface: rgba(238, 70, 188, 0.10);
2175
+ --pickup-border: rgba(246, 112, 199, 0.24);
2176
+ --disabled-value: rgba(255,255,255,0.15);
2177
+ --side-brand-bg: #2B165C;
2178
+ --side-brand-border: rgba(182, 146, 246, 0.26);
2179
+ }
2180
+
2181
+ .theme-root.theme-light {
2182
+ --bg-app: #E9EEF5;
2183
+ --bg-shell: #F8FAFC;
2184
+ --bg-header: #E2E8F4;
2185
+ --bg-toolbar: #F8FAFC;
2186
+ --bg-panel: #FFFFFF;
2187
+ --bg-panel-soft: #FFFFFF;
2188
+ --bg-panel-alt: #F2F5F9;
2189
+ --bg-elevated: #EEF3F8;
2190
+ --bg-grid-cell: #FFFFFF;
2191
+ --bg-grid-muted: #F8FAFC;
2192
+ --bg-sticky: #EEF3F8;
2193
+ --bg-input: #F2F5F9;
2194
+ --border-soft: #CBD5E1;
2195
+ --border-strong: #B8C4D3;
2196
+ --text-main: #101828;
2197
+ --text-soft: #344054;
2198
+ --text-muted: #667085;
2199
+ --text-faint: #98A2B3;
2200
+ --shadow-heavy: 0 18px 48px rgba(89, 61, 132, 0.08);
2201
+ --brand-primary: #7F56DA;
2202
+ --brand-deep: #6941C6;
2203
+ --brand-light: #B692F6;
2204
+ --brand-surface: #F4EBFF;
2205
+ --success-text: #067647;
2206
+ --success-surface: #D1FADF;
2207
+ --success-border: #A6F4C5;
2208
+ --warning-text: #B54708;
2209
+ --warning-surface: #FEF0C7;
2210
+ --warning-border: #FEDF89;
2211
+ --danger-text: #B42318;
2212
+ --danger-surface: #FEE4E2;
2213
+ --danger-border: #F04438;
2214
+ --info-text: #175CD3;
2215
+ --info-surface: #D1E9FF;
2216
+ --info-border: #2E90FA;
2217
+ --pickup-text: #C11574;
2218
+ --pickup-surface: #FCCEEE;
2219
+ --pickup-border: #EE46BC;
2220
+ --disabled-value: #98A2B3;
2221
+ --side-brand-bg: #6941C6;
2222
+ --side-brand-border: rgba(127, 86, 218, 0.32);
2223
+ }
2224
+
2225
+ .theme-app { background: var(--bg-app); color: var(--text-main); }
2226
+ .theme-shell { background: var(--bg-shell); color: var(--text-main); border-color: var(--border-soft); box-shadow: var(--shadow-heavy); }
2227
+ .theme-header { background: var(--bg-header); border-color: var(--border-soft); }
2228
+ .theme-toolbar { background: var(--bg-toolbar); border-color: var(--border-soft); }
2229
+ .theme-panel { background: var(--bg-panel); border-color: var(--border-soft); }
2230
+ .theme-panel-soft { background: var(--bg-panel-soft); border-color: var(--border-soft); }
2231
+ .theme-panel-alt { background: var(--bg-panel-alt); border-color: var(--border-soft); }
2232
+ .theme-elevated { background: var(--bg-elevated); }
2233
+ .theme-grid-cell { background: var(--bg-grid-cell); }
2234
+ .theme-grid-muted { background: var(--bg-grid-muted); }
2235
+ .theme-sticky { background: var(--bg-sticky); }
2236
+ .theme-input { background: var(--bg-input); border-color: var(--border-strong); color: var(--text-main); }
2237
+ .theme-text { color: var(--text-main); }
2238
+ .theme-text-soft { color: var(--text-soft); }
2239
+ .theme-text-muted { color: var(--text-muted); }
2240
+ .theme-text-faint { color: var(--text-faint); }
2241
+ .theme-border { border-color: var(--border-soft); }
2242
+ .theme-border-strong { border-color: var(--border-strong); }
2243
+ .theme-brand-surface { background: var(--brand-surface); }
2244
+ .theme-brand-text { color: var(--brand-deep); }
2245
+ .theme-success-chip { color: var(--success-text); background: var(--success-surface); border-color: var(--success-border); }
2246
+ .theme-warning-chip { color: var(--warning-text); background: var(--warning-surface); border-color: var(--warning-border); }
2247
+ .theme-danger-chip { color: var(--danger-text); background: var(--danger-surface); border-color: var(--danger-border); }
2248
+ .theme-info-chip { color: var(--info-text); background: var(--info-surface); border-color: var(--info-border); }
2249
+ .theme-pickup-chip { color: var(--pickup-text); background: var(--pickup-surface); border-color: var(--pickup-border); }
2250
+ .theme-disabled-value { color: var(--disabled-value); }
2251
+ .theme-light .soft-shadow { box-shadow: 0 12px 34px rgba(15,23,42,0.08); }
2252
+ .btn-brand { background: var(--brand-primary); color: #fff; border: 1px solid var(--brand-primary); }
2253
+ .btn-brand:hover { background: var(--brand-deep); border-color: var(--brand-deep); }
2254
+ .btn-neutral { background: var(--bg-input); color: var(--text-main); border: 1px solid var(--border-strong); }
2255
+ .btn-neutral:hover { background: var(--bg-panel-alt); }
2256
+ .btn-success { background: var(--success-surface); color: var(--success-text); border: 1px solid var(--success-border); }
2257
+ .btn-warning { background: var(--warning-surface); color: var(--warning-text); border: 1px solid var(--warning-border); }
2258
+ .btn-danger { background: var(--danger-surface); color: var(--danger-text); border: 1px solid var(--danger-border); }
2259
+ .btn-info { background: var(--info-surface); color: var(--info-text); border: 1px solid var(--info-border); }
2260
+ .surface-muted { background: var(--bg-panel-alt); border: 1px solid var(--border-soft); }
2261
+ .surface-card { background: var(--bg-panel); border: 1px solid var(--border-soft); }
2262
+ .text-disabled-token { color: var(--disabled-value); }
2263
+ .btn-pill-active { background: var(--brand-primary); color: #fff; border: 1px solid var(--brand-primary); }
2264
+ .btn-pill-active:hover { background: var(--brand-deep); border-color: var(--brand-deep); }
2265
+ .btn-pill-neutral { background: var(--bg-input); color: var(--text-soft); border: 1px solid var(--border-strong); }
2266
+ .btn-pill-neutral:hover { background: var(--bg-panel-alt); color: var(--text-main); }
2267
+ .surface-overlay { background: color-mix(in srgb, var(--bg-panel) 88%, transparent); border: 1px solid var(--border-soft); }
2268
+ .panel-dark-adapt { background: var(--bg-panel); border: 1px solid var(--border-soft); color: var(--text-main); }
2269
+ .panel-soft-adapt { background: var(--bg-panel-alt); border: 1px solid var(--border-soft); color: var(--text-main); }
2270
+ .input-adapt { background: var(--bg-input); border: 1px solid var(--border-strong); color: var(--text-main); }
2271
+ .caption-adapt { color: var(--text-muted); }
2272
+ .ghost-adapt:hover { background: var(--bg-panel-alt); }
2273
+ .surface-brand-side { background: var(--side-brand-bg); color: #fff; border-color: var(--side-brand-border); }
2274
+ .surface-brand-side-muted { background: color-mix(in srgb, var(--side-brand-bg) 88%, white 12%); color: #fff; border-color: var(--side-brand-border); }
2275
+ .badge-brand-dot { background: var(--brand-primary); color: #fff; }
2276
+ `), /* @__PURE__ */ react.default.createElement("div", { className: `theme-root theme-app flex h-full min-h-0 flex-col p-2 md:p-3 theme-dark` }, /* @__PURE__ */ react.default.createElement("div", {
2277
+ className: "theme-shell soft-shadow mx-0 flex h-full min-h-0 w-full max-w-none flex-1 flex-col rounded-[28px] border overflow-hidden transition-[padding-right] duration-200",
2278
+ style: { paddingRight: 0 }
2279
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "flex min-h-0 flex-1 flex-col" }, /* @__PURE__ */ react.default.createElement(AnimatePresence, {
2280
+ mode: "wait",
2281
+ initial: false
2282
+ }, view === "month" && /* @__PURE__ */ react.default.createElement(motion.div, {
2283
+ key: `month-${anchorDate.getFullYear()}-${anchorDate.getMonth()}`,
2284
+ className: "flex min-h-0 flex-1 flex-col",
2285
+ initial: {
2286
+ x: navDirection > 0 ? 36 : -36,
2287
+ opacity: .78
2288
+ },
2289
+ animate: {
2290
+ x: 0,
2291
+ opacity: 1
2292
+ },
2293
+ exit: {
2294
+ x: navDirection > 0 ? -36 : 36,
2295
+ opacity: .78
2296
+ },
2297
+ transition: {
2298
+ duration: .22,
2299
+ ease: [
2300
+ .22,
2301
+ .8,
2302
+ .22,
2303
+ 1
2304
+ ]
2305
+ }
2306
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "p-2 md:p-4 relative flex min-h-0 flex-1 flex-col" }, /* @__PURE__ */ react.default.createElement("div", { className: "theme-panel rounded-3xl border min-w-[980px] min-h-0 max-h-none flex-1 overflow-auto" }, /* @__PURE__ */ react.default.createElement("div", { className: "theme-panel-alt sticky top-0 z-20 grid grid-cols-7 border-b theme-border shadow-[0_6px_12px_rgba(0,0,0,0.08)]" }, weekdayNames.map((d, i) => /* @__PURE__ */ react.default.createElement("div", {
2307
+ key: d,
2308
+ className: `px-4 py-3 text-center font-medium ${i >= 5 ? "bg-violet-900" : ""}`
2309
+ }, d))), /* @__PURE__ */ react.default.createElement("div", { className: "grid grid-cols-7 auto-rows-[255px]" }, monthDays.map((day) => {
2310
+ const allItems = bookings.filter((b) => b.date === day.key);
2311
+ const dayItems = allItems.slice(0, 3);
2312
+ const moreItems = allItems.slice(3);
2313
+ const moreCount = moreItems.length;
2314
+ const showMoreTile = moreCount > 0 && dayItems.length > 0;
2315
+ return /* @__PURE__ */ react.default.createElement(motion.button, {
2316
+ layoutId: `zoom-month-${day.key}`,
2317
+ key: day.key,
2318
+ onClick: () => goToDayFromCell(day.date, null, `month-${day.key}`),
2319
+ onDragOver: (e) => e.preventDefault(),
2320
+ onDrop: (e) => {
2321
+ e.preventDefault();
2322
+ handleGridDropMove(day.key);
2323
+ },
2324
+ className: `relative flex flex-col justify-start border-r border-b theme-border p-3 text-left align-top ${day.inMonth ? "bg-[#1a1b21]" : "bg-[#111217] text-zinc-600"} hover:bg-zinc-900`
2325
+ }, /* @__PURE__ */ react.default.createElement("div", { className: `absolute left-3 top-3 text-4xl font-semibold leading-none ` }, day.date.getDate()), /* @__PURE__ */ react.default.createElement("div", { className: "absolute right-3 top-3 flex gap-1 pt-1" }, day.bookingCount > 0 && /* @__PURE__ */ react.default.createElement("span", { className: "h-3 w-3 rounded-full bg-violet-500" }), (day.blockCount > 0 || day.fullyBooked) && /* @__PURE__ */ react.default.createElement("span", { className: "h-3 w-3 rounded-full bg-red-500" })), /* @__PURE__ */ react.default.createElement("div", { className: "mt-10 flex flex-col items-start gap-1.5 w-full" }, dayItems.map((item, i) => {
2326
+ const isLastVisible = i === dayItems.length - 1;
2327
+ const shrinkForMore = showMoreTile && isLastVisible;
2328
+ const displayTag = getDisplayStatusTag(item, day.key);
2329
+ return /* @__PURE__ */ react.default.createElement("div", {
2330
+ key: i,
2331
+ className: "flex w-full items-stretch gap-2"
2332
+ }, /* @__PURE__ */ react.default.createElement("button", {
2333
+ draggable: item.kind !== "block",
2334
+ onDragStart: (e) => {
2335
+ if (item.kind !== "block") {
2336
+ e.stopPropagation();
2337
+ setDraggingItem(item);
2338
+ }
2339
+ },
2340
+ onClick: (e) => {
2341
+ e.stopPropagation();
2342
+ openBookingDetail(item);
2343
+ },
2344
+ className: `block rounded-md px-2 py-2 text-xs text-left ${getBookingStateClasses(item, day.key)} ${shrinkForMore ? "flex-1 min-w-0" : "w-full"}`
2345
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "truncate" }, item.name), /* @__PURE__ */ react.default.createElement("div", { className: "mt-1 opacity-80" }, formatHourLabel(item.startHour), " -", " ", formatHourLabel(item.endHour)), displayTag && statusTagMeta(displayTag) && /* @__PURE__ */ react.default.createElement("div", { className: "mt-2 flex justify-end" }, /* @__PURE__ */ react.default.createElement("span", { className: `rounded-lg px-2 py-0.5 text-[10px] font-semibold ${statusTagMeta(displayTag).className} backdrop-blur-[2px]` }, statusTagMeta(displayTag).label))), shrinkForMore && /* @__PURE__ */ react.default.createElement("div", {
2346
+ className: "relative h-[52px] w-[52px] shrink-0",
2347
+ ref: (overflowPopover === null || overflowPopover === void 0 ? void 0 : overflowPopover.courtId) === "month" && (overflowPopover === null || overflowPopover === void 0 ? void 0 : overflowPopover.date) === day.key ? overflowPanelRef : null
2348
+ }, /* @__PURE__ */ react.default.createElement("button", {
2349
+ onMouseEnter: (e) => {
2350
+ e.stopPropagation();
2351
+ setOverflowPopover({
2352
+ courtId: "month",
2353
+ date: day.key,
2354
+ items: moreItems,
2355
+ pinned: false
2356
+ });
2357
+ },
2358
+ onClick: (e) => {
2359
+ e.stopPropagation();
2360
+ setOverflowPopover(null);
2361
+ setOverflowListModal((prev) => prev && prev.scope === "month" && prev.date === day.key ? null : {
2362
+ scope: "month",
2363
+ date: day.key,
2364
+ title: `${day.key} 预约列表`,
2365
+ items: allItems.filter((x) => x.kind === "booking")
2366
+ });
2367
+ },
2368
+ className: "flex h-[52px] w-[52px] items-center justify-center rounded-xl bg-violet-700/90 text-sm font-semibold text-white"
2369
+ }, "+", moreCount), (overflowPopover === null || overflowPopover === void 0 ? void 0 : overflowPopover.courtId) === "month" && (overflowPopover === null || overflowPopover === void 0 ? void 0 : overflowPopover.date) === day.key && !overflowListModal && /* @__PURE__ */ react.default.createElement("div", {
2370
+ onMouseLeave: () => {
2371
+ if (!(overflowPopover === null || overflowPopover === void 0 ? void 0 : overflowPopover.pinned)) setOverflowPopover(null);
2372
+ },
2373
+ className: `absolute right-0 top-[60px] z-20 min-w-[240px] rounded-xl border p-3 shadow-2xl border-zinc-700 bg-[#111218]`
2374
+ }, /* @__PURE__ */ react.default.createElement("div", { className: `mb-3 text-xs font-semibold text-zinc-300` }, "Bookings for this day"), /* @__PURE__ */ react.default.createElement("div", { className: "flex flex-col gap-2.5" }, overflowPopover.items.map((extraItem, moreIdx) => /* @__PURE__ */ react.default.createElement("button", {
2375
+ key: moreIdx,
2376
+ onClick: (e) => {
2377
+ e.stopPropagation();
2378
+ openBookingDetail(extraItem);
2379
+ },
2380
+ className: `block w-full shrink-0 rounded-lg px-3 py-2.5 text-xs text-left ${extraItem.kind === "block" ? "bg-red-700/70 text-red-100" : "bg-violet-700/90 text-violet-50"}`
2381
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "truncate" }, extraItem.name), /* @__PURE__ */ react.default.createElement("div", { className: "mt-1 opacity-80" }, formatHourLabel(extraItem.startHour), " ", "-", " ", formatHourLabel(extraItem.endHour))))))));
2382
+ })));
2383
+ }))))), view === "week" && /* @__PURE__ */ react.default.createElement(motion.div, {
2384
+ key: `week-${fmtDate(weekDays[0])}`,
2385
+ className: "flex min-h-0 flex-1 flex-col",
2386
+ initial: {
2387
+ x: navDirection > 0 ? 36 : -36,
2388
+ opacity: .78
2389
+ },
2390
+ animate: {
2391
+ x: 0,
2392
+ opacity: 1
2393
+ },
2394
+ exit: {
2395
+ x: navDirection > 0 ? -36 : 36,
2396
+ opacity: .78
2397
+ },
2398
+ transition: {
2399
+ duration: .22,
2400
+ ease: [
2401
+ .22,
2402
+ .8,
2403
+ .22,
2404
+ 1
2405
+ ]
2406
+ }
2407
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "p-2 md:p-4 relative flex min-h-0 flex-1 flex-col" }, /* @__PURE__ */ react.default.createElement("div", { className: "theme-panel rounded-3xl border min-w-[980px] min-h-0 max-h-none flex-1 overflow-auto" }, /* @__PURE__ */ react.default.createElement("div", {
2408
+ className: "grid",
2409
+ style: { gridTemplateColumns: `${frozenColWidth}px repeat(${weekDays.length}, minmax(150px, 1fr))` }
2410
+ }, /* @__PURE__ */ react.default.createElement("div", {
2411
+ className: "grid sticky top-0 z-50",
2412
+ style: {
2413
+ gridColumn: "1 / -1",
2414
+ gridTemplateColumns: `${frozenColWidth}px repeat(${weekDays.length}, minmax(150px, 1fr))`,
2415
+ isolation: "isolate"
2416
+ }
2417
+ }, /* @__PURE__ */ react.default.createElement("div", { className: `sticky left-0 z-30 w-[132px] min-w-[132px] max-w-[132px] px-3 py-4 font-semibold border-b shadow-[8px_0_16px_rgba(0,0,0,0.08)] bg-[#241d40] border-zinc-800` }, "Court / Date"), weekDays.map((day, i) => {
2418
+ const key = fmtDate(day);
2419
+ const dayItems = bookings.filter((b) => b.date === key);
2420
+ const fullyBooked = courts.every((court) => hourSlots.filter(isBusinessHour).every((h) => dayOccupancy(court.id, key, bookings, hourSlots)[h]));
2421
+ return /* @__PURE__ */ react.default.createElement("div", {
2422
+ key,
2423
+ className: `relative z-20 border-b border-l p-3 text-center shadow-[0_8px_16px_rgba(0,0,0,0.06)] border-zinc-800 ${i >= 5 ? "bg-violet-900" : "bg-[#1a1a22]"}`
2424
+ }, /* @__PURE__ */ react.default.createElement("div", { className: `text-sm text-zinc-400` }, weekdayNames[i]), /* @__PURE__ */ react.default.createElement("div", { className: "mt-1 text-3xl font-semibold" }, day.getDate()), /* @__PURE__ */ react.default.createElement("div", { className: "mt-2 flex items-center justify-center gap-1" }, dayItems.some((b) => b.kind === "booking") && /* @__PURE__ */ react.default.createElement("span", { className: "h-2.5 w-2.5 rounded-full bg-violet-500" }), (dayItems.some((b) => b.kind === "block") || fullyBooked) && /* @__PURE__ */ react.default.createElement("span", { className: "h-2.5 w-2.5 rounded-full bg-red-500" })));
2425
+ })), visibleCourtRows.map((row) => /* @__PURE__ */ react.default.createElement(react.default.Fragment, { key: row.id }, row.kind === "group" ? /* @__PURE__ */ react.default.createElement(react.default.Fragment, null, /* @__PURE__ */ react.default.createElement("div", { className: `sticky left-0 z-20 w-[132px] min-w-[132px] max-w-[132px] border-b px-2.5 py-2 shadow-[8px_0_16px_rgba(0,0,0,0.08)] border-zinc-800/80 bg-gradient-to-b from-[#252038] to-[#1a1628]` }, /* @__PURE__ */ react.default.createElement("button", {
2426
+ type: "button",
2427
+ "aria-expanded": !row.collapsed,
2428
+ onClick: () => setCollapsedGroups((prev) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev), {}, { [row.label]: !prev[row.label] })),
2429
+ className: `flex w-full items-center gap-2 rounded-lg px-1 py-1 text-left transition-colors hover:bg-white/[0.04] active:bg-white/[0.07]`
2430
+ }, /* @__PURE__ */ react.default.createElement(lucide_react.ChevronDown, {
2431
+ size: 15,
2432
+ strokeWidth: 2.25,
2433
+ className: `shrink-0 transition-transform duration-200 text-zinc-500 ${row.collapsed ? "-rotate-90" : "rotate-0"}`,
2434
+ "aria-hidden": true
2435
+ }), /* @__PURE__ */ react.default.createElement("div", { className: "flex min-w-0 flex-1 items-center gap-1.5" }, /* @__PURE__ */ react.default.createElement("span", { className: `truncate text-[13px] font-semibold leading-snug text-zinc-100` }, row.label), /* @__PURE__ */ react.default.createElement("span", { className: `shrink-0 rounded-md px-1.5 py-0.5 text-[10px] font-semibold tabular-nums bg-zinc-800/90 text-zinc-300 ring-1 ring-zinc-600/40` }, row.count)))), weekDays.map((day) => {
2436
+ const key = fmtDate(day);
2437
+ const groupCourts = visibleCourts.filter((court) => court.type === row.label);
2438
+ /** 分子:当日时间轴上无任何占用(无预约、无锁台)的资源数;分母:该类型下资源总数 */
2439
+ const idleCount = groupCourts.filter((court) => {
2440
+ return courtDaySummary(court.id, key, bookings, hourSlots).occupiedHours.length === 0;
2441
+ }).length;
2442
+ const ratio = groupCourts.length > 0 ? idleCount / groupCourts.length : 0;
2443
+ return /* @__PURE__ */ react.default.createElement("div", {
2444
+ key: `${row.id}-${key}`,
2445
+ className: `border-b border-l p-3 text-center border-zinc-800 bg-[#151a2f]`
2446
+ }, /* @__PURE__ */ react.default.createElement("div", { className: `text-xs font-semibold ${getRemainingToneClass(ratio, isLight)}` }, idleCount, "/", groupCourts.length));
2447
+ })) : /* @__PURE__ */ react.default.createElement(react.default.Fragment, null, /* @__PURE__ */ react.default.createElement("div", { className: `sticky left-0 z-20 w-[132px] min-w-[132px] max-w-[132px] border-b px-3 py-3 align-top shadow-[8px_0_16px_rgba(0,0,0,0.06)] border-zinc-800 bg-[#1a1a22]` }, /* @__PURE__ */ react.default.createElement("div", { className: "font-semibold text-[16px] leading-tight break-all" }, row.name)), weekDays.map((day) => {
2448
+ const key = fmtDate(day);
2449
+ const summary = courtDaySummary(row.id, key, bookings, hourSlots);
2450
+ const previewItems = summary.items.slice(0, 3);
2451
+ const moreItems = summary.items.slice(3);
2452
+ const moreCount = moreItems.length;
2453
+ const showMoreTile = moreCount > 0 && previewItems.length > 0;
2454
+ return /* @__PURE__ */ react.default.createElement(motion.button, {
2455
+ layoutId: `zoom-week-${row.id}-${key}`,
2456
+ key: `${row.id}-${key}`,
2457
+ onClick: () => goToDayFromCell(day, row.id, `week-${row.id}-${key}`),
2458
+ onDragOver: (e) => e.preventDefault(),
2459
+ onDrop: (e) => {
2460
+ e.preventDefault();
2461
+ handleGridDropMove(key, row.id);
2462
+ },
2463
+ className: `relative flex flex-col justify-start min-h-[148px] border-b border-l p-3 text-left align-top transition ${summary.fullyBooked ? "bg-zinc-800 text-zinc-500" : summary.hasBlock ? "bg-red-950/30 border-red-800/40" : summary.occupiedHours.length > 0 ? "bg-[#1c1630] hover:bg-[#241c3f]" : "bg-zinc-900 hover:bg-zinc-800"}`
2464
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "absolute left-3 top-3 text-[13px] text-zinc-400" }, key), /* @__PURE__ */ react.default.createElement("div", { className: "absolute right-3 top-3 flex gap-1" }, summary.occupiedHours.length > 0 && /* @__PURE__ */ react.default.createElement("span", { className: "h-2.5 w-2.5 rounded-full bg-violet-500" }), (summary.hasBlock || summary.fullyBooked) && /* @__PURE__ */ react.default.createElement("span", { className: "h-2.5 w-2.5 rounded-full bg-red-500" })), summary.fullyBooked ? /* @__PURE__ */ react.default.createElement("div", { className: "mt-8 rounded-lg bg-zinc-700/70 px-2 py-1 text-xs" }, "Fully booked") : summary.items.length > 0 ? /* @__PURE__ */ react.default.createElement("div", { className: "mt-8 flex flex-col items-start gap-1.5 w-full" }, previewItems.map((item, idx) => {
2465
+ const isLastVisible = idx === previewItems.length - 1;
2466
+ const shrinkForMore = showMoreTile && isLastVisible;
2467
+ const displayTag = getDisplayStatusTag(item, key);
2468
+ return /* @__PURE__ */ react.default.createElement("div", {
2469
+ key: idx,
2470
+ className: "flex w-full items-stretch gap-2"
2471
+ }, /* @__PURE__ */ react.default.createElement("button", {
2472
+ onClick: (e) => {
2473
+ e.stopPropagation();
2474
+ openBookingDetail(item);
2475
+ },
2476
+ className: `rounded-lg px-3 py-2 text-xs text-left ${getBookingStateClasses(item, key)} ${shrinkForMore ? "flex-1 min-w-0" : "w-full"}`
2477
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "truncate" }, item.name), /* @__PURE__ */ react.default.createElement("div", { className: "mt-1 opacity-80" }, formatHourLabel(item.startHour), " ", "-", " ", formatHourLabel(item.endHour)), displayTag && statusTagMeta(displayTag) && /* @__PURE__ */ react.default.createElement("div", { className: "mt-2 flex justify-end" }, /* @__PURE__ */ react.default.createElement("span", { className: `rounded-lg px-2 py-0.5 text-[10px] font-semibold ${statusTagMeta(displayTag).className} backdrop-blur-[2px]` }, statusTagMeta(displayTag).label))), shrinkForMore && /* @__PURE__ */ react.default.createElement("div", {
2478
+ className: "relative h-[52px] w-[52px] shrink-0",
2479
+ ref: (overflowPopover === null || overflowPopover === void 0 ? void 0 : overflowPopover.courtId) === row.id && (overflowPopover === null || overflowPopover === void 0 ? void 0 : overflowPopover.date) === key ? overflowPanelRef : null
2480
+ }, /* @__PURE__ */ react.default.createElement("button", {
2481
+ onMouseEnter: (e) => {
2482
+ e.stopPropagation();
2483
+ setOverflowPopover({
2484
+ courtId: row.id,
2485
+ date: key,
2486
+ items: moreItems,
2487
+ pinned: false
2488
+ });
2489
+ },
2490
+ onClick: (e) => {
2491
+ e.stopPropagation();
2492
+ setOverflowPopover(null);
2493
+ setOverflowListModal((prev) => prev && prev.scope === row.id && prev.date === key ? null : {
2494
+ scope: row.id,
2495
+ date: key,
2496
+ title: `${key} All bookings`,
2497
+ items: summary.items.filter((x) => x.kind === "booking")
2498
+ });
2499
+ },
2500
+ className: "flex h-[52px] w-[52px] items-center justify-center rounded-xl bg-violet-700/90 text-sm font-semibold text-white"
2501
+ }, "+", moreCount)));
2502
+ })) : /* @__PURE__ */ react.default.createElement("div", { className: "mt-8 rounded-lg border border-dashed border-zinc-700 px-2 py-2 text-xs text-zinc-500" }, "Available"));
2503
+ })))))))), view === "day" && /* @__PURE__ */ react.default.createElement(motion.div, {
2504
+ key: `day-${dayKey}`,
2505
+ className: "flex min-h-0 flex-1 flex-col",
2506
+ initial: {
2507
+ x: navDirection > 0 ? 36 : -36,
2508
+ opacity: .78
2509
+ },
2510
+ animate: {
2511
+ x: 0,
2512
+ opacity: 1
2513
+ },
2514
+ exit: {
2515
+ x: navDirection > 0 ? -36 : 36,
2516
+ opacity: .78
2517
+ },
2518
+ transition: {
2519
+ duration: .22,
2520
+ ease: [
2521
+ .22,
2522
+ .8,
2523
+ .22,
2524
+ 1
2525
+ ]
2526
+ }
2527
+ }, /* @__PURE__ */ react.default.createElement(motion.div, {
2528
+ layoutId: transitioningToDay ? `zoom-${transitioningToDay.source}` : void 0,
2529
+ transition: { layout: {
2530
+ duration: .2,
2531
+ ease: [
2532
+ .2,
2533
+ .85,
2534
+ .2,
2535
+ 1
2536
+ ]
2537
+ } },
2538
+ className: "p-2 md:p-4 relative flex min-h-0 flex-1 flex-col"
2539
+ }, /* @__PURE__ */ react.default.createElement("div", {
2540
+ ref: dayScrollRef,
2541
+ onMouseDown: handleDayMouseDown,
2542
+ onMouseMove: handleDayMouseMove,
2543
+ onMouseUp: handleDayMouseUp,
2544
+ onMouseLeave: handleDayMouseUp,
2545
+ className: `pisell-scroll-hidden relative rounded-3xl border min-h-0 max-h-none flex-1 overflow-auto overscroll-contain touch-pan-x touch-pan-y select-none border-zinc-800 bg-[#121217] ${dayDragging ? "cursor-grabbing" : "cursor-grab"}`
2546
+ }, /* @__PURE__ */ react.default.createElement("div", { style: {
2547
+ minWidth: `${frozenColWidth + hourSlots.length * dayColWidth}px`,
2548
+ minHeight: `${dayContentHeight}px`
2549
+ } }, dayEdgeStats.showTop && /* @__PURE__ */ react.default.createElement("button", {
2550
+ onClick: () => scrollDayBy(0, -dayRowHeight * 2),
2551
+ className: "absolute left-1/2 top-3 z-[45] -translate-x-1/2 rounded-full border border-white/10 bg-black/35 px-3 py-1.5 text-xs text-white backdrop-blur-md hover:bg-black/50"
2552
+ }, "↑", dayEdgeStats.top > 0 ? ` ${dayEdgeStats.top}` : ""), dayEdgeStats.showBottom && /* @__PURE__ */ react.default.createElement("button", {
2553
+ onClick: () => scrollDayBy(0, dayRowHeight * 2),
2554
+ className: "absolute bottom-3 left-1/2 z-[45] -translate-x-1/2 rounded-full border border-white/10 bg-black/35 px-3 py-1.5 text-xs text-white backdrop-blur-md hover:bg-black/50"
2555
+ }, "↓", dayEdgeStats.bottom > 0 ? ` ${dayEdgeStats.bottom}` : ""), dayEdgeStats.showLeft && /* @__PURE__ */ react.default.createElement("button", {
2556
+ onClick: () => scrollDayBy(-dayColWidth * 3, 0),
2557
+ className: "absolute left-[144px] top-1/2 z-[45] -translate-y-1/2 rounded-full border border-white/10 bg-black/35 px-3 py-1.5 text-xs text-white backdrop-blur-md hover:bg-black/50"
2558
+ }, "←", dayEdgeStats.left > 0 ? ` ${dayEdgeStats.left}` : ""), dayEdgeStats.showRight && /* @__PURE__ */ react.default.createElement("button", {
2559
+ onClick: () => scrollDayBy(dayColWidth * 3, 0),
2560
+ className: "absolute right-3 top-1/2 z-[45] -translate-y-1/2 rounded-full border border-white/10 bg-black/35 px-3 py-1.5 text-xs text-white backdrop-blur-md hover:bg-black/50"
2561
+ }, dayEdgeStats.right > 0 ? `${dayEdgeStats.right} ` : "", "→"), /* @__PURE__ */ react.default.createElement("div", {
2562
+ className: "grid sticky top-0 z-50",
2563
+ style: { gridTemplateColumns: `${frozenColWidth}px repeat(${hourSlots.length}, ${dayColWidth}px)` }
2564
+ }, /* @__PURE__ */ react.default.createElement("div", { className: `sticky left-0 top-0 z-[60] w-[132px] min-w-[132px] max-w-[132px] px-3 py-4 font-semibold border-b shadow-[8px_0_16px_rgba(0,0,0,0.08)] bg-[#241d40] border-zinc-800` }, anchorDate.getFullYear(), "年", " ", monthNames[anchorDate.getMonth()], " ", anchorDate.getDate(), "日"), hourSlots.map((hour) => /* @__PURE__ */ react.default.createElement("div", {
2565
+ key: hour,
2566
+ className: `border-b border-l px-2 py-2.5 text-center text-sm font-medium border-zinc-800 ${isBusinessHour(hour) ? "bg-[#1a1a22] text-zinc-300" : "bg-zinc-800/80 text-zinc-500"}`
2567
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-center justify-center gap-1" }, /* @__PURE__ */ react.default.createElement(lucide_react.Clock3, { size: 14 }), " ", formatHourLabel(hour)), isBusinessHour(hour) && dayHourRemaining[hour] && /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-[11px] font-semibold ${getRemainingToneClass(dayHourRemaining[hour].ratio, isLight)}` }, dayHourRemaining[hour].remaining, "/", dayHourRemaining[hour].total, " free")))), dayKey === demoNow.date && /* @__PURE__ */ react.default.createElement("div", {
2568
+ className: "pointer-events-none absolute inset-y-0 z-20",
2569
+ style: { left: `${frozenColWidth + (demoNow.hour - firstTimelineHour) * dayColWidth}px` }
2570
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "relative h-full" }, /* @__PURE__ */ react.default.createElement("div", { className: "absolute inset-y-0 w-[2px] bg-emerald-400/95 shadow-[0_0_10px_rgba(16,185,129,0.65)]" }), /* @__PURE__ */ react.default.createElement("div", { className: "sticky top-2 z-30 -translate-x-1/2 rounded-full bg-emerald-500 px-2 py-0.5 text-[10px] font-semibold text-white shadow-lg w-fit" }, currentTimeLabel()))), /* @__PURE__ */ react.default.createElement("div", {
2571
+ className: "grid relative",
2572
+ style: {
2573
+ gridTemplateColumns: `${frozenColWidth}px repeat(${hourSlots.length}, ${dayColWidth}px)`,
2574
+ gridTemplateRows: dayRowHeights.map((h) => `${h}px`).join(" ")
2575
+ }
2576
+ }, visibleCourtRows.map((row) => /* @__PURE__ */ react.default.createElement(react.default.Fragment, { key: row.id }, row.kind === "group" ? /* @__PURE__ */ react.default.createElement(react.default.Fragment, null, /* @__PURE__ */ react.default.createElement("div", { className: `sticky left-0 z-30 w-[132px] min-w-[132px] max-w-[132px] border-b px-2.5 py-2 shadow-[8px_0_16px_rgba(0,0,0,0.08)] border-zinc-800/80 bg-gradient-to-b from-[#252038] to-[#1a1628]` }, /* @__PURE__ */ react.default.createElement("button", {
2577
+ type: "button",
2578
+ "aria-expanded": !row.collapsed,
2579
+ onClick: () => setCollapsedGroups((prev) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev), {}, { [row.label]: !prev[row.label] })),
2580
+ className: `flex w-full items-center gap-2 rounded-lg px-1 py-1 text-left transition-colors hover:bg-white/[0.04] active:bg-white/[0.07]`
2581
+ }, /* @__PURE__ */ react.default.createElement(lucide_react.ChevronDown, {
2582
+ size: 15,
2583
+ strokeWidth: 2.25,
2584
+ className: `shrink-0 transition-transform duration-200 text-zinc-500 ${row.collapsed ? "-rotate-90" : "rotate-0"}`,
2585
+ "aria-hidden": true
2586
+ }), /* @__PURE__ */ react.default.createElement("div", { className: "flex min-w-0 flex-1 items-center gap-1.5" }, /* @__PURE__ */ react.default.createElement("span", { className: `truncate text-[13px] font-semibold leading-snug text-zinc-100` }, row.label), /* @__PURE__ */ react.default.createElement("span", { className: `shrink-0 rounded-md px-1.5 py-0.5 text-[10px] font-semibold tabular-nums bg-zinc-800/90 text-zinc-300 ring-1 ring-zinc-600/40` }, row.count)))), hourSlots.map((hour) => {
2587
+ const groupCourts = visibleCourts.filter((court) => court.type === row.label);
2588
+ const remaining = groupCourts.filter((court) => !dayOccupancy(court.id, dayKey, bookings, hourSlots)[hour]).length;
2589
+ const ratio = groupCourts.length > 0 ? remaining / groupCourts.length : 0;
2590
+ const outsideBusiness = !isBusinessHour(hour);
2591
+ return /* @__PURE__ */ react.default.createElement("div", {
2592
+ key: `${row.id}-${hour}`,
2593
+ className: `border-b border-l px-2 py-1.5 text-center text-sm font-medium border-zinc-800 ${outsideBusiness ? "bg-zinc-800/80 text-zinc-500" : "bg-[#151a2f] text-zinc-300"}`
2594
+ }, outsideBusiness ? /* @__PURE__ */ react.default.createElement("div", { className: "text-xs opacity-60" }, "—") : /* @__PURE__ */ react.default.createElement("div", { className: `text-xs font-semibold ${getRemainingToneClass(ratio, isLight)}` }, remaining, "/", groupCourts.length, " free"));
2595
+ })) : /* @__PURE__ */ react.default.createElement(react.default.Fragment, null, /* @__PURE__ */ react.default.createElement("div", {
2596
+ "data-court-row": row.id,
2597
+ className: `sticky left-0 z-30 w-[132px] min-w-[132px] max-w-[132px] border-b px-3 py-3 shadow-[8px_0_16px_rgba(0,0,0,0.06)] ${focusedCourtId === row.id ? "ring-2 ring-violet-400/70 bg-violet-900/20 border-zinc-800" : "bg-[#1a1a22] border-zinc-800"}`
2598
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "font-semibold text-base leading-tight break-all" }, row.name), dayRowRemainingByCourt[row.id] && /* @__PURE__ */ react.default.createElement("div", { className: `mt-2 text-xs font-semibold ${getRemainingToneClass(dayRowRemainingByCourt[row.id].ratio, isLight)}` }, dayRowRemainingByCourt[row.id].remaining, "/", dayRowRemainingByCourt[row.id].total, " ", "slots free")), hourSlots.map((hour) => {
2599
+ const item = dayOccupancy(row.id, dayKey, bookings, hourSlots)[hour];
2600
+ const isBlock = (item === null || item === void 0 ? void 0 : item.kind) === "block";
2601
+ const isOccupied = !!item;
2602
+ const freeSelected = isFreeSelected(row.id, hour);
2603
+ const blockSelected = isBlockSelected(row.id, hour);
2604
+ const outsideBusiness = !isBusinessHour(hour);
2605
+ return /* @__PURE__ */ react.default.createElement("button", {
2606
+ key: `${row.id}-${hour}`,
2607
+ onClick: () => !outsideBusiness && toggleSlot(row.id, hour),
2608
+ onDragOver: (e) => {
2609
+ if (!outsideBusiness) e.preventDefault();
2610
+ },
2611
+ onDrop: (e) => {
2612
+ if (!outsideBusiness) {
2613
+ e.preventDefault();
2614
+ handleDropMove(row.id, dayKey, hour);
2615
+ }
2616
+ },
2617
+ className: `relative h-[${dayRowHeight}px] min-h-[${dayRowHeight}px] p-2 text-left transition outline-none ${isOccupied && !outsideBusiness ? "border-l-transparent border-b-transparent" : `border-b border-l border-zinc-700`} ${outsideBusiness ? "bg-zinc-800/80 text-zinc-500 border-zinc-700" : isBlock ? blockSelected ? "bg-red-500/25 border-red-400 ring-2 ring-red-400/60" : "bg-red-900/50 border-red-700/50" : isOccupied ? "bg-transparent" : freeSelected ? "bg-white/10 border-violet-400 ring-2 ring-violet-400/60" : "bg-zinc-900 border-zinc-700 hover:bg-zinc-800"}`
2618
+ }, outsideBusiness ? /* @__PURE__ */ react.default.createElement("div", { className: "flex h-full items-center justify-center rounded-xl border border-dashed border-zinc-700 text-xs text-zinc-500" }, "Outside hours") : (item === null || item === void 0 ? void 0 : item.kind) === "block" ? /* @__PURE__ */ react.default.createElement("div", { className: "flex h-full w-full flex-col justify-center rounded-xl px-3 text-sm font-medium" }, /* @__PURE__ */ react.default.createElement("div", { className: "truncate" }, blockSelected ? "Selected Block" : item.name), item.note && /* @__PURE__ */ react.default.createElement("div", { className: "mt-1 text-xs text-zinc-300/90 truncate" }, item.note), getBlockMetaLine(item) && /* @__PURE__ */ react.default.createElement("div", { className: "mt-1 text-[10px] text-zinc-400 truncate" }, getBlockMetaLine(item))) : !item ? /* @__PURE__ */ react.default.createElement("div", { className: `flex h-full items-center justify-center rounded-xl border border-dashed border-zinc-600 text-zinc-500 hover:border-violet-500 hover:text-violet-300` }, freeSelected ? "Selected" : "Tap to select") : null);
2619
+ })))), overlayBookings.map((booking) => {
2620
+ const left = frozenColWidth + (booking.start - firstTimelineHour) * dayColWidth;
2621
+ const width = booking.span * dayColWidth;
2622
+ const top = booking.rowTop + 10;
2623
+ const height = dayRowHeight - 20;
2624
+ return /* @__PURE__ */ react.default.createElement("div", {
2625
+ key: `${booking.item.id}-${dayKey}`,
2626
+ className: "absolute z-20",
2627
+ style: {
2628
+ left,
2629
+ top,
2630
+ width,
2631
+ height
2632
+ }
2633
+ }, /* @__PURE__ */ react.default.createElement(BookingCard, {
2634
+ booking,
2635
+ dayKey,
2636
+ onOpenDetail: openBookingDetail,
2637
+ onDragStart: setDraggingItem,
2638
+ onJumpNext: () => {
2639
+ const nextDay = parseDate(dayKey);
2640
+ nextDay.setDate(nextDay.getDate() + 1);
2641
+ setNavDirection(1);
2642
+ commitAnchor(nextDay);
2643
+ setFocusedCourtId(booking.courtId);
2644
+ }
2645
+ }));
2646
+ })))), (selectedFreeSlots.length > 0 || selectedBlockSlots.length > 0) && /* @__PURE__ */ react.default.createElement("div", { className: "fixed bottom-6 left-1/2 z-50 -translate-x-1/2" }, /* @__PURE__ */ react.default.createElement("div", { className: "flex flex-wrap items-center justify-center gap-3 rounded-2xl border border-white/10 bg-black/55 px-4 py-3 backdrop-blur-xl shadow-2xl shadow-black/40 max-w-[92vw]" }, /* @__PURE__ */ react.default.createElement("button", {
2647
+ onClick: deselectAll,
2648
+ className: "rounded-xl bg-red-500/85 px-4 py-2 text-sm font-semibold text-white hover:bg-red-500"
2649
+ }, "Deselect All"), selectedBlockSlots.length > 0 && /* @__PURE__ */ react.default.createElement("button", {
2650
+ onClick: openSelectedBlocks,
2651
+ className: "rounded-xl bg-zinc-500/90 px-5 py-3 text-sm font-semibold text-white hover:bg-zinc-400"
2652
+ }, "Open Slot"), selectedFreeSlots.length > 0 && /* @__PURE__ */ react.default.createElement("button", {
2653
+ onClick: () => setShowBlockPanel(true),
2654
+ className: "rounded-xl bg-zinc-500/90 px-5 py-3 text-sm font-semibold text-white hover:bg-zinc-400"
2655
+ }, "Block"), selectedFreeSlots.length > 0 && /* @__PURE__ */ react.default.createElement("button", {
2656
+ onClick: createBookingFromSelection,
2657
+ className: "rounded-xl bg-violet-600 px-6 py-3 text-sm font-semibold text-white hover:bg-violet-500"
2658
+ }, "Create a Booking")))))))), /* @__PURE__ */ react.default.createElement(AnimatePresence, null, showBlockPanel && selectedFreeSlots.length > 0 && /* @__PURE__ */ react.default.createElement(motion.div, {
2659
+ initial: { opacity: 0 },
2660
+ animate: { opacity: 1 },
2661
+ exit: { opacity: 0 },
2662
+ className: "fixed inset-0 z-50 bg-black/55 backdrop-blur-sm flex items-end md:items-center justify-center p-2 md:p-4"
2663
+ }, /* @__PURE__ */ react.default.createElement(motion.div, {
2664
+ ref: blockPanelRef,
2665
+ initial: {
2666
+ scale: .96,
2667
+ y: 10
2668
+ },
2669
+ animate: {
2670
+ scale: 1,
2671
+ y: 0
2672
+ },
2673
+ exit: {
2674
+ scale: .96,
2675
+ y: 10
2676
+ },
2677
+ className: `w-full max-w-[720px] max-h-[92vh] overflow-y-auto rounded-t-3xl md:rounded-3xl border p-4 md:p-6 shadow-2xl border-zinc-700 bg-[#121217]`
2678
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "mb-4 flex items-center justify-between" }, /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("div", { className: "text-xl font-semibold" }, "Block settings"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-sm text-zinc-400` }, "Selected time range:", " ", selectedFreeSlots.length > 0 ? `${formatHourLabel((_groupSelectedSlots$ = groupSelectedSlots(selectedFreeSlots)[0]) === null || _groupSelectedSlots$ === void 0 ? void 0 : _groupSelectedSlots$.startHour)} - ${formatHourLabel((_groupSelectedSlots$2 = groupSelectedSlots(selectedFreeSlots)[0]) === null || _groupSelectedSlots$2 === void 0 ? void 0 : _groupSelectedSlots$2.endHour)}` : "-")), /* @__PURE__ */ react.default.createElement("button", {
2679
+ onClick: () => setShowBlockPanel(false),
2680
+ className: `rounded-xl px-3 py-2 border border-zinc-700 text-zinc-300 hover:bg-zinc-800`
2681
+ }, "Close")), /* @__PURE__ */ react.default.createElement("div", { className: "mb-5 grid gap-3 md:gap-4 md:grid-cols-2" }, /* @__PURE__ */ react.default.createElement("button", {
2682
+ onClick: () => setBlockMode("single"),
2683
+ className: `rounded-2xl border p-4 text-left ${blockMode === "single" ? "border-violet-500 bg-violet-500/10" : "border-zinc-700 bg-[#171820]"}`
2684
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "font-semibold" }, "Only selected date"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-sm text-zinc-400` }, "Create a block only for the currently selected date and time range.")), /* @__PURE__ */ react.default.createElement("button", {
2685
+ onClick: () => setBlockMode("repeat"),
2686
+ className: `rounded-2xl border p-4 text-left ${blockMode === "repeat" ? "border-violet-500 bg-violet-500/10" : "border-zinc-700 bg-[#171820]"}`
2687
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "font-semibold" }, "Every matching date"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-sm text-zinc-400` }, "Create repeating blocks by date range and weekday rules."))), /* @__PURE__ */ react.default.createElement("div", { className: `space-y-4 rounded-2xl border p-4 border-zinc-700 bg-[#171820]` }, /* @__PURE__ */ react.default.createElement("div", { className: "grid gap-3 md:grid-cols-2" }, /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("label", { className: `mb-2 block text-sm text-zinc-400` }, "Block note"), /* @__PURE__ */ react.default.createElement("input", {
2688
+ value: blockNote,
2689
+ onChange: (e) => setBlockNote(e.target.value),
2690
+ placeholder: "For example: Team event",
2691
+ className: `w-full rounded-xl px-3 py-2 outline-none border border-zinc-700 bg-[#111218] text-white`
2692
+ })), /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("label", { className: `mb-2 block text-sm text-zinc-400` }, "Blocked by"), /* @__PURE__ */ react.default.createElement("input", {
2693
+ value: blockBy,
2694
+ onChange: (e) => setBlockBy(e.target.value),
2695
+ placeholder: "For example: Allen",
2696
+ className: "w-full rounded-xl border border-zinc-700 bg-[#111218] px-3 py-2 text-white outline-none"
2697
+ }))), blockMode === "repeat" && /* @__PURE__ */ react.default.createElement(react.default.Fragment, null, /* @__PURE__ */ react.default.createElement("div", { className: "grid gap-3 md:gap-4 md:grid-cols-2" }, /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("label", { className: `mb-2 block text-sm text-zinc-400` }, "Date range - start"), /* @__PURE__ */ react.default.createElement("div", { className: `flex items-center gap-2 rounded-xl border px-3 py-2 border-zinc-700 bg-[#111218]` }, /* @__PURE__ */ react.default.createElement("input", {
2698
+ ref: blockStartInputRef,
2699
+ type: "date",
2700
+ value: blockRangeStart,
2701
+ onChange: (e) => setBlockRangeStart(e.target.value),
2702
+ className: "w-full bg-transparent outline-none"
2703
+ }), /* @__PURE__ */ react.default.createElement("button", {
2704
+ type: "button",
2705
+ onClick: () => {
2706
+ var _blockStartInputRef$c;
2707
+ return (_blockStartInputRef$c = blockStartInputRef.current) === null || _blockStartInputRef$c === void 0 ? void 0 : _blockStartInputRef$c.focus();
2708
+ },
2709
+ className: "rounded-lg p-1 hover:bg-zinc-800"
2710
+ }, /* @__PURE__ */ react.default.createElement(lucide_react.CalendarDays, {
2711
+ size: 18,
2712
+ className: "text-zinc-400"
2713
+ })))), /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("label", { className: `mb-2 block text-sm text-zinc-400` }, "Date range - end"), /* @__PURE__ */ react.default.createElement("div", { className: "flex items-center gap-2 rounded-xl border border-zinc-700 bg-[#111218] px-3 py-2" }, /* @__PURE__ */ react.default.createElement("input", {
2714
+ ref: blockEndInputRef,
2715
+ type: "date",
2716
+ value: blockRangeEnd,
2717
+ onChange: (e) => setBlockRangeEnd(e.target.value),
2718
+ className: "w-full bg-transparent outline-none"
2719
+ }), /* @__PURE__ */ react.default.createElement("button", {
2720
+ type: "button",
2721
+ onClick: () => {
2722
+ var _blockEndInputRef$cur;
2723
+ return (_blockEndInputRef$cur = blockEndInputRef.current) === null || _blockEndInputRef$cur === void 0 ? void 0 : _blockEndInputRef$cur.focus();
2724
+ },
2725
+ className: "rounded-lg p-1 hover:bg-zinc-800"
2726
+ }, /* @__PURE__ */ react.default.createElement(lucide_react.CalendarDays, {
2727
+ size: 18,
2728
+ className: "text-zinc-400"
2729
+ }))))), /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("label", { className: `mb-2 block text-sm text-zinc-400` }, "Weekdays in range"), /* @__PURE__ */ react.default.createElement("div", { className: "grid grid-cols-2 gap-2 sm:flex sm:flex-wrap" }, weekdayNames.map((name, idx) => /* @__PURE__ */ react.default.createElement("button", {
2730
+ key: name,
2731
+ onClick: () => toggleBlockWeekday(weekdaysMap[idx]),
2732
+ className: `rounded-xl px-4 py-2 text-sm ${blockWeekdays.includes(weekdaysMap[idx]) ? "btn-pill-active" : "bg-zinc-800 text-zinc-300"}`
2733
+ }, name)))), /* @__PURE__ */ react.default.createElement("div", { className: `rounded-xl px-3 py-3 text-sm bg-zinc-900/80 text-zinc-300` }, "Example: choose 1 Sep to 1 Oct, then select every Wednesday. The chosen time range will be blocked on all matching Wednesdays."))), /* @__PURE__ */ react.default.createElement("div", { className: "mt-6 flex flex-col-reverse sm:flex-row items-stretch sm:items-center justify-end gap-3" }, /* @__PURE__ */ react.default.createElement("button", {
2734
+ onClick: () => setShowBlockPanel(false),
2735
+ className: `rounded-xl px-4 py-2 border border-zinc-700 text-zinc-300 hover:bg-zinc-800`
2736
+ }, "Cancel"), /* @__PURE__ */ react.default.createElement("button", {
2737
+ onClick: createBlockFromSelection,
2738
+ className: `rounded-xl px-5 py-3 text-sm font-semibold bg-zinc-500/90 text-white hover:bg-zinc-400`
2739
+ }, "Confirm block"))))), /* @__PURE__ */ react.default.createElement(AnimatePresence, null, overflowListModal && /* @__PURE__ */ react.default.createElement(motion.div, {
2740
+ initial: { opacity: 0 },
2741
+ animate: { opacity: 1 },
2742
+ exit: { opacity: 0 },
2743
+ className: "fixed inset-0 z-[69] bg-black/45 backdrop-blur-sm flex items-center justify-center p-4"
2744
+ }, /* @__PURE__ */ react.default.createElement(motion.div, {
2745
+ ref: overflowPanelRef,
2746
+ initial: {
2747
+ scale: .96,
2748
+ y: 8
2749
+ },
2750
+ animate: {
2751
+ scale: 1,
2752
+ y: 0
2753
+ },
2754
+ exit: {
2755
+ scale: .96,
2756
+ y: 8
2757
+ },
2758
+ className: `w-full max-w-[520px] max-h-[72vh] overflow-auto rounded-3xl border p-5 shadow-2xl border-zinc-700 bg-[#121217]`
2759
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "mb-4 flex items-start justify-between" }, /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("div", { className: "text-xl font-semibold" }, "Bookings for this day"), /* @__PURE__ */ react.default.createElement("div", { className: "mt-1 text-sm text-zinc-400" }, overflowListModal.title)), /* @__PURE__ */ react.default.createElement("button", {
2760
+ onClick: () => setOverflowListModal(null),
2761
+ className: "rounded-xl border border-zinc-700 px-3 py-2 text-zinc-300 hover:bg-zinc-800"
2762
+ }, "Close")), /* @__PURE__ */ react.default.createElement("div", { className: "flex flex-col gap-3" }, overflowListModal.items.map((extraItem, idx) => {
2763
+ const displayTag = getDisplayStatusTag(extraItem, overflowListModal.date);
2764
+ return /* @__PURE__ */ react.default.createElement("button", {
2765
+ key: `${extraItem.id}-${idx}`,
2766
+ onClick: () => {
2767
+ setOverflowListModal(null);
2768
+ openBookingDetail(extraItem);
2769
+ },
2770
+ className: `block w-full shrink-0 rounded-xl px-4 py-3 text-left text-white hover:bg-violet-600 ${getBookingStateClasses(extraItem, overflowListModal.date)}`
2771
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "font-medium" }, extraItem.name), /* @__PURE__ */ react.default.createElement("div", { className: "mt-1 text-sm opacity-85" }, formatHourLabel(extraItem.startHour), " -", " ", formatHourLabel(extraItem.endHour)), displayTag && statusTagMeta(displayTag) && /* @__PURE__ */ react.default.createElement("div", { className: "mt-2 flex justify-end" }, /* @__PURE__ */ react.default.createElement("span", { className: `rounded-lg px-2 py-0.5 text-[10px] font-semibold ${statusTagMeta(displayTag).className} backdrop-blur-[2px]` }, statusTagMeta(displayTag).label)));
2772
+ }))))), /* @__PURE__ */ react.default.createElement(AnimatePresence, null, detailItem && detailMode === "quick" && /* @__PURE__ */ react.default.createElement(motion.div, {
2773
+ initial: { opacity: 0 },
2774
+ animate: { opacity: 1 },
2775
+ exit: { opacity: 0 },
2776
+ className: "fixed inset-0 z-[70] flex items-center justify-center bg-black/35 p-4 backdrop-blur-sm"
2777
+ }, /* @__PURE__ */ react.default.createElement(motion.div, {
2778
+ initial: {
2779
+ scale: .97,
2780
+ y: 8
2781
+ },
2782
+ animate: {
2783
+ scale: 1,
2784
+ y: 0
2785
+ },
2786
+ exit: {
2787
+ scale: .97,
2788
+ y: 8
2789
+ },
2790
+ className: `w-full max-w-[520px] rounded-[28px] border p-4 shadow-2xl border-zinc-700 bg-[#121217]`,
2791
+ ref: detailPanelRef
2792
+ }, (() => {
2793
+ const detail = getBookingDetailData(detailItem, courts);
2794
+ return /* @__PURE__ */ react.default.createElement(react.default.Fragment, null, /* @__PURE__ */ react.default.createElement("div", { className: "mb-4 flex items-start justify-between gap-3" }, /* @__PURE__ */ react.default.createElement("div", { className: "min-w-0 flex-1" }, /* @__PURE__ */ react.default.createElement("div", { className: `flex items-center gap-2 text-[11px] text-zinc-500` }, /* @__PURE__ */ react.default.createElement("span", null, getCompactBookingId(detail)), /* @__PURE__ */ react.default.createElement("span", null, "·"), /* @__PURE__ */ react.default.createElement("span", null, detail.headerSummary.customerName)), /* @__PURE__ */ react.default.createElement("div", { className: `mt-2 text-lg font-semibold leading-none text-white` }, detail.headerSummary.customerName), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-sm text-zinc-400` }, detail.headerSummary.resourceLabel), /* @__PURE__ */ react.default.createElement("div", { className: `mt-2 text-sm text-zinc-400` }, detail.headerSummary.timeLabel)), /* @__PURE__ */ react.default.createElement("div", { className: "flex shrink-0 flex-col items-end gap-3" }, /* @__PURE__ */ react.default.createElement("button", {
2795
+ onClick: () => setDetailItem(null),
2796
+ className: `rounded-2xl border p-2 border-zinc-700 text-zinc-300 hover:bg-zinc-800`
2797
+ }, /* @__PURE__ */ react.default.createElement(lucide_react.X, { size: 16 })), /* @__PURE__ */ react.default.createElement("label", { className: `inline-flex cursor-pointer items-center gap-2 rounded-2xl border px-2.5 py-2 text-xs whitespace-nowrap border-zinc-700 bg-white/5 text-zinc-200` }, /* @__PURE__ */ react.default.createElement("input", {
2798
+ type: "checkbox",
2799
+ checked: preferDrawerOpen && !preferQuickPopup,
2800
+ onChange: (e) => {
2801
+ const checked = e.target.checked;
2802
+ setPreferDrawerOpen(checked);
2803
+ setPreferQuickPopup(!checked);
2804
+ }
2805
+ }), /* @__PURE__ */ react.default.createElement("span", null, "Full details next time")))), /* @__PURE__ */ react.default.createElement("div", { className: "grid grid-cols-[1.02fr_1fr] gap-2" }, /* @__PURE__ */ react.default.createElement("button", {
2806
+ onClick: () => {
2807
+ setCheckinModal(detailItem);
2808
+ setCheckinDraft(null);
2809
+ },
2810
+ className: `row-span-2 min-h-[110px] rounded-3xl border px-4 py-3 text-left text-[18px] font-semibold border-emerald-500/40 bg-emerald-600/20 text-white hover:bg-emerald-600/30`
2811
+ }, /* @__PURE__ */ react.default.createElement("div", null, "Check-in")), /* @__PURE__ */ react.default.createElement("button", {
2812
+ onClick: () => {
2813
+ setShowActionsOverlay(false);
2814
+ setDetailMode("drawer");
2815
+ setCalendarShiftedForDrawer(true);
2816
+ },
2817
+ className: `min-h-[52px] rounded-3xl border px-3 py-2.5 text-left text-[16px] font-semibold border-amber-500/40 bg-amber-500/20 text-white hover:bg-amber-500/30`
2818
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ react.default.createElement("span", null, "Detail"), /* @__PURE__ */ react.default.createElement(lucide_react.ExternalLink, {
2819
+ size: 15,
2820
+ className: "opacity-85"
2821
+ }))), /* @__PURE__ */ react.default.createElement("div", { className: "grid grid-cols-2 gap-2" }, /* @__PURE__ */ react.default.createElement("button", {
2822
+ onClick: () => {
2823
+ var _visibleCourts$, _visibleCourts$2;
2824
+ setMoveConfirm({
2825
+ item: detailItem,
2826
+ targetCourtId: detailItem.courtId || ((_visibleCourts$ = visibleCourts[0]) === null || _visibleCourts$ === void 0 ? void 0 : _visibleCourts$.id) || courts[0].id,
2827
+ targetDate: detailItem.date,
2828
+ targetHour: detailItem.startHour
2829
+ });
2830
+ setMoveDraft({
2831
+ targetCourtId: detailItem.courtId || ((_visibleCourts$2 = visibleCourts[0]) === null || _visibleCourts$2 === void 0 ? void 0 : _visibleCourts$2.id) || courts[0].id,
2832
+ targetDate: detailItem.date,
2833
+ targetHour: detailItem.startHour
2834
+ });
2835
+ },
2836
+ className: `min-h-[52px] rounded-3xl border px-3 py-2.5 text-left text-[14px] font-semibold border-cyan-500/40 bg-cyan-500/20 text-white hover:bg-cyan-500/30`
2837
+ }, /* @__PURE__ */ react.default.createElement("div", null, "Move")), /* @__PURE__ */ react.default.createElement("button", {
2838
+ onClick: () => {
2839
+ setShowActionsOverlay(true);
2840
+ },
2841
+ className: `min-h-[52px] rounded-3xl border px-3 py-2.5 text-left text-[14px] font-semibold border-zinc-700 bg-white/5 text-white hover:bg-white/10`
2842
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-center justify-between gap-2" }, /* @__PURE__ */ react.default.createElement("span", null, "More"), /* @__PURE__ */ react.default.createElement(lucide_react.CircleEllipsis, {
2843
+ size: 15,
2844
+ className: "opacity-85"
2845
+ }))))));
2846
+ })())), detailItem && showActionsOverlay && /* @__PURE__ */ react.default.createElement(motion.div, {
2847
+ initial: { opacity: 0 },
2848
+ animate: { opacity: 1 },
2849
+ exit: { opacity: 0 },
2850
+ className: "fixed inset-0 z-[86] flex items-center justify-center bg-black/40 p-4 backdrop-blur-sm"
2851
+ }, /* @__PURE__ */ react.default.createElement(motion.div, {
2852
+ initial: {
2853
+ scale: .97,
2854
+ y: 8
2855
+ },
2856
+ animate: {
2857
+ scale: 1,
2858
+ y: 0
2859
+ },
2860
+ exit: {
2861
+ scale: .97,
2862
+ y: 8
2863
+ },
2864
+ className: `relative z-[87] flex max-h-[90vh] w-full max-w-[760px] flex-col rounded-3xl border p-5 shadow-2xl border-zinc-700 bg-[#121217]`,
2865
+ ref: detailPanelRef
2866
+ }, (() => {
2867
+ const allActions = [
2868
+ {
2869
+ label: "Order detail",
2870
+ icon: lucide_react.FileText,
2871
+ section: "Info"
2872
+ },
2873
+ {
2874
+ label: "View customer",
2875
+ icon: lucide_react.User,
2876
+ section: "Info"
2877
+ },
2878
+ {
2879
+ label: "View venue / court detail",
2880
+ icon: lucide_react.MapPinned,
2881
+ section: "Info"
2882
+ },
2883
+ {
2884
+ label: "Check in",
2885
+ icon: lucide_react.CheckCircle2,
2886
+ section: "Status"
2887
+ },
2888
+ {
2889
+ label: "Mark as complete",
2890
+ icon: lucide_react.BadgeCheck,
2891
+ section: "Status"
2892
+ },
2893
+ {
2894
+ label: "Mark no-show",
2895
+ icon: lucide_react.AlertCircle,
2896
+ section: "Status"
2897
+ },
2898
+ {
2899
+ label: "Reopen booking",
2900
+ icon: lucide_react.History,
2901
+ section: "Status"
2902
+ },
2903
+ {
2904
+ label: "Cancel booking",
2905
+ icon: lucide_react.X,
2906
+ section: "Status"
2907
+ },
2908
+ {
2909
+ label: "Edit detail",
2910
+ icon: lucide_react.NotebookPen,
2911
+ section: "Change"
2912
+ },
2913
+ {
2914
+ label: "Reschedule",
2915
+ icon: lucide_react.CalendarDays,
2916
+ section: "Change"
2917
+ },
2918
+ {
2919
+ label: "Extend booking",
2920
+ icon: lucide_react.Clock4,
2921
+ section: "Change"
2922
+ },
2923
+ {
2924
+ label: "Change item",
2925
+ icon: lucide_react.Receipt,
2926
+ section: "Change"
2927
+ },
2928
+ {
2929
+ label: "Move item",
2930
+ icon: lucide_react.Receipt,
2931
+ section: "Change"
2932
+ },
2933
+ {
2934
+ label: "Transfer item to another booking",
2935
+ icon: lucide_react.ExternalLink,
2936
+ section: "Change"
2937
+ },
2938
+ {
2939
+ label: "Change customer",
2940
+ icon: lucide_react.User,
2941
+ section: "Change"
2942
+ },
2943
+ {
2944
+ label: "Change booking customer",
2945
+ icon: lucide_react.User,
2946
+ section: "Change"
2947
+ },
2948
+ {
2949
+ label: "Change guest",
2950
+ icon: lucide_react.Users,
2951
+ section: "Change"
2952
+ },
2953
+ {
2954
+ label: "Change venue / court",
2955
+ icon: lucide_react.MapPinned,
2956
+ section: "Change"
2957
+ },
2958
+ {
2959
+ label: "Change staff",
2960
+ icon: lucide_react.Wand2,
2961
+ section: "Change"
2962
+ },
2963
+ {
2964
+ label: "Pay now",
2965
+ icon: lucide_react.CreditCard,
2966
+ section: "Pay"
2967
+ },
2968
+ {
2969
+ label: "Send payment link",
2970
+ icon: lucide_react.ExternalLink,
2971
+ section: "Pay"
2972
+ },
2973
+ {
2974
+ label: "Refund",
2975
+ icon: lucide_react.Wallet,
2976
+ section: "Pay"
2977
+ },
2978
+ {
2979
+ label: "Mark as paid",
2980
+ icon: lucide_react.BadgeCheck,
2981
+ section: "Pay"
2982
+ },
2983
+ {
2984
+ label: "Merge order",
2985
+ icon: lucide_react.GitMerge,
2986
+ section: "More"
2987
+ },
2988
+ {
2989
+ label: "Send confirmation",
2990
+ icon: lucide_react.FileText,
2991
+ section: "Communication"
2992
+ },
2993
+ {
2994
+ label: "Send reminder",
2995
+ icon: lucide_react.AlertCircle,
2996
+ section: "Communication"
2997
+ },
2998
+ {
2999
+ label: "Print receipt",
3000
+ icon: lucide_react.Printer,
3001
+ section: "Print"
3002
+ },
3003
+ {
3004
+ label: "Print receipt",
3005
+ icon: lucide_react.Receipt,
3006
+ section: "Print"
3007
+ },
3008
+ {
3009
+ label: "Print invoice",
3010
+ icon: lucide_react.FileText,
3011
+ section: "Print"
3012
+ },
3013
+ {
3014
+ label: "Print wristband",
3015
+ icon: lucide_react.Printer,
3016
+ section: "Print"
3017
+ },
3018
+ {
3019
+ label: "Print drink voucher",
3020
+ icon: lucide_react.Printer,
3021
+ section: "Print"
3022
+ },
3023
+ {
3024
+ label: "Duplicate booking",
3025
+ icon: lucide_react.CircleEllipsis,
3026
+ section: "More"
3027
+ }
3028
+ ];
3029
+ const pinnedActions = pinnedActionLabels.map((label) => allActions.find((action) => action.label === label)).filter(Boolean).slice(0, 12);
3030
+ return /* @__PURE__ */ react.default.createElement(react.default.Fragment, null, /* @__PURE__ */ react.default.createElement("div", { className: "mb-4 flex shrink-0 items-start justify-between gap-4" }, /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("div", { className: `text-[11px] uppercase tracking-[0.18em] text-zinc-500` }, "All actions")), /* @__PURE__ */ react.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ react.default.createElement("button", {
3031
+ onClick: () => setShowActionsOverlay(false),
3032
+ className: `rounded-xl p-2 border border-zinc-700 text-zinc-300 hover:bg-zinc-800`
3033
+ }, /* @__PURE__ */ react.default.createElement(lucide_react.X, { size: 16 })))), /* @__PURE__ */ react.default.createElement("div", { className: "pisell-scroll-hidden flex-1 overflow-y-auto pr-1 relative" }, /* @__PURE__ */ react.default.createElement("div", { className: "space-y-4 pb-10" }, /* @__PURE__ */ react.default.createElement("div", { className: `rounded-2xl border p-4 border-violet-500/35 bg-violet-500/8` }, /* @__PURE__ */ react.default.createElement("div", { className: "mb-3 flex items-center justify-between gap-3" }, /* @__PURE__ */ react.default.createElement("div", { className: `text-xs font-semibold uppercase tracking-[0.16em] text-violet-300` }, "Quick actions"), /* @__PURE__ */ react.default.createElement("div", { className: `inline-flex items-center gap-1.5 text-xs font-medium text-violet-300/95` }, /* @__PURE__ */ react.default.createElement(lucide_react.Hand, {
3034
+ size: 12,
3035
+ className: "opacity-80"
3036
+ }), /* @__PURE__ */ react.default.createElement("span", null, "Long press to pin here or unpin"))), /* @__PURE__ */ react.default.createElement("div", { className: "grid gap-2 sm:grid-cols-2 lg:grid-cols-3" }, pinnedActions.map((action) => {
3037
+ const Icon = action.icon;
3038
+ const handlers = createLongPressHandlers(() => {
3039
+ setPinnedActionLabels((prev) => prev.filter((label) => label !== action.label));
3040
+ });
3041
+ return /* @__PURE__ */ react.default.createElement("button", require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({ key: `quick-${action.label}` }, handlers), {}, { className: `flex items-center justify-between gap-3 rounded-xl border px-3 py-3 text-left text-sm border-zinc-700 bg-white/5 text-white hover:bg-white/10` }), /* @__PURE__ */ react.default.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ react.default.createElement(Icon, {
3042
+ size: 16,
3043
+ className: "text-zinc-300"
3044
+ }), /* @__PURE__ */ react.default.createElement("span", null, action.label)), /* @__PURE__ */ react.default.createElement(lucide_react.Pin, {
3045
+ size: 14,
3046
+ className: "text-violet-300"
3047
+ }));
3048
+ }))), [
3049
+ { label: "Info" },
3050
+ { label: "Status" },
3051
+ { label: "Change" },
3052
+ { label: "Pay" },
3053
+ { label: "Communication" },
3054
+ { label: "Print" },
3055
+ { label: "More" }
3056
+ ].map((section) => {
3057
+ const sectionItems = allActions.filter((action) => action.section === section.label);
3058
+ return /* @__PURE__ */ react.default.createElement("div", {
3059
+ key: section.label,
3060
+ className: `rounded-2xl border p-4 border-zinc-800 bg-[#171820]`
3061
+ }, /* @__PURE__ */ react.default.createElement("div", { className: `mb-3 text-xs font-semibold uppercase tracking-[0.16em] text-zinc-500` }, section.label), /* @__PURE__ */ react.default.createElement("div", { className: "grid grid-cols-[repeat(auto-fit,minmax(220px,1fr))] gap-2" }, sectionItems.map((action) => {
3062
+ const Icon = action.icon;
3063
+ const isPinned = pinnedActionLabels.includes(action.label);
3064
+ const handlers = createLongPressHandlers(() => {
3065
+ setPinnedActionLabels((prev) => {
3066
+ if (prev.includes(action.label)) return prev.filter((label) => label !== action.label);
3067
+ if (prev.length >= 12) {
3068
+ showQuickActionLimit(setQuickActionLimitMessage);
3069
+ return prev;
3070
+ }
3071
+ return [...prev, action.label];
3072
+ });
3073
+ });
3074
+ return /* @__PURE__ */ react.default.createElement("button", require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({ key: action.label }, handlers), {}, {
3075
+ onClick: () => {
3076
+ if (action.label === "Merge order") {
3077
+ var _candidates$;
3078
+ const candidates = bookings.filter((b) => b.kind === "booking" && b.id !== detailItem.id);
3079
+ setMergeOrderDraft({
3080
+ targetBookingId: ((_candidates$ = candidates[0]) === null || _candidates$ === void 0 ? void 0 : _candidates$.id) || "",
3081
+ keepSourceOpen: false
3082
+ });
3083
+ setMergeOrderModal({
3084
+ item: detailItem,
3085
+ candidates
3086
+ });
3087
+ }
3088
+ },
3089
+ className: `flex items-center justify-between gap-3 rounded-xl border px-3 py-3 text-left text-sm border-zinc-700 bg-white/5 text-white hover:bg-white/10`
3090
+ }), /* @__PURE__ */ react.default.createElement("div", { className: "flex items-center gap-3" }, /* @__PURE__ */ react.default.createElement(Icon, {
3091
+ size: 16,
3092
+ className: "text-zinc-300"
3093
+ }), /* @__PURE__ */ react.default.createElement("span", null, action.label)), /* @__PURE__ */ react.default.createElement(lucide_react.Pin, {
3094
+ size: 14,
3095
+ className: isPinned ? "text-violet-300" : "text-zinc-500"
3096
+ }));
3097
+ })));
3098
+ }))));
3099
+ })())), detailItem && detailMode === "drawer" && /* @__PURE__ */ react.default.createElement(motion.div, {
3100
+ initial: { opacity: 0 },
3101
+ animate: { opacity: 1 },
3102
+ exit: { opacity: 0 },
3103
+ className: "fixed inset-y-4 right-4 z-[71] w-[min(520px,calc(100vw-32px))] bg-transparent pointer-events-none"
3104
+ }, /* @__PURE__ */ react.default.createElement(motion.div, {
3105
+ initial: { x: 420 },
3106
+ animate: { x: 0 },
3107
+ exit: { x: 420 },
3108
+ transition: { duration: .18 },
3109
+ className: `absolute right-0 top-0 h-full w-full max-w-[520px] rounded-[28px] border shadow-2xl pointer-events-auto overflow-hidden border-zinc-800 bg-[#0f121b]`,
3110
+ ref: detailPanelRef
3111
+ }, (() => {
3112
+ var _detail$noteGroups, _detail$noteGroups2, _detail$noteGroups3, _detail$customer2, _detail$customer3, _detail$customer4, _detail$history, _detail$history2, _detail$history3, _detail$noteGroups4, _detail$noteGroups5, _detail$noteGroups6, _detail$itemSummary, _detail$itemSummary2, _detail$itemSummary3;
3113
+ const detail = getBookingDetailData(detailItem, courts);
3114
+ const detailWithNoteOverrides = require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, detail), {}, { noteGroups: require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, detail.noteGroups), {}, {
3115
+ internal: (((_detail$noteGroups = detail.noteGroups) === null || _detail$noteGroups === void 0 ? void 0 : _detail$noteGroups.internal) || []).map((note) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, note), {}, { text: getNoteValue(noteOverrides, note.id, note.text) })),
3116
+ order: (((_detail$noteGroups2 = detail.noteGroups) === null || _detail$noteGroups2 === void 0 ? void 0 : _detail$noteGroups2.order) || []).map((note) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, note), {}, { text: getNoteValue(noteOverrides, note.id, note.text) })),
3117
+ item: (((_detail$noteGroups3 = detail.noteGroups) === null || _detail$noteGroups3 === void 0 ? void 0 : _detail$noteGroups3.item) || []).map((note) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, note), {}, { text: getNoteValue(noteOverrides, note.id, note.text) }))
3118
+ }) });
3119
+ selectedCustomer || (!((_detail$customer2 = detail.customer) === null || _detail$customer2 === void 0) && _detail$customer2.name || detail.headerSummary.customerName, (((_detail$customer3 = detail.customer) === null || _detail$customer3 === void 0 ? void 0 : _detail$customer3.phone) || "").split(" ").slice(-1)[0], !((_detail$customer4 = detail.customer) === null || _detail$customer4 === void 0) && _detail$customer4.email, (((_detail$history = detail.history) === null || _detail$history === void 0 || (_detail$history = _detail$history[0]) === null || _detail$history === void 0 ? void 0 : _detail$history.time) || "2026-03-18").slice(0, 10).split("-").join("/"));
3120
+ const tabs = [
3121
+ "summary",
3122
+ "items",
3123
+ "payments",
3124
+ "guest",
3125
+ "files",
3126
+ "history"
3127
+ ];
3128
+ const detailKey = detailItem.id;
3129
+ const viewedForDetail = viewedTabState[detailKey] || {};
3130
+ const viewedSubtabsForDetail = viewedSubtabState[detailKey] || {};
3131
+ return /* @__PURE__ */ react.default.createElement(react.default.Fragment, null, /* @__PURE__ */ react.default.createElement("div", { className: `relative px-4 py-3 ${getDrawerStatusTheme(detailItem, detailItem.date)}` }, /* @__PURE__ */ react.default.createElement("button", {
3132
+ onClick: () => {
3133
+ setDetailItem(null);
3134
+ setCalendarShiftedForDrawer(false);
3135
+ },
3136
+ className: `absolute -left-16 top-4 flex h-12 w-12 items-center justify-center rounded-full border shadow-xl border-white/25 bg-[#101117] text-white hover:bg-[#1a1d29]`
3137
+ }, /* @__PURE__ */ react.default.createElement(lucide_react.X, { size: 20 })), /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start justify-between gap-4 pr-3" }, /* @__PURE__ */ react.default.createElement("div", { className: "min-w-0 flex-1 pr-3" }, /* @__PURE__ */ react.default.createElement("div", { className: `text-[11px] font-medium uppercase tracking-[0.18em] text-white/50` }, "Booking ID"), /* @__PURE__ */ react.default.createElement("div", { className: "mt-0.5 flex flex-wrap items-end gap-x-3 gap-y-1 leading-none" }, /* @__PURE__ */ react.default.createElement("span", { className: "text-[36px] font-semibold text-white" }, getCompactBookingId(detail)), /* @__PURE__ */ react.default.createElement("span", { className: `pb-[3px] text-[22px] font-medium text-white/88` }, "· ", detail.headerSummary.resourceLabel)), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1.5 text-[15px] text-white/82` }, detail.headerSummary.timeLabel), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1.5 flex flex-wrap items-center gap-x-4 gap-y-1.5 text-sm text-white/84` }, /* @__PURE__ */ react.default.createElement("div", { className: "inline-flex items-center gap-2" }, /* @__PURE__ */ react.default.createElement(lucide_react.User, {
3138
+ size: 14,
3139
+ className: "text-white/50"
3140
+ }), /* @__PURE__ */ react.default.createElement("span", null, detail.headerSummary.customerName)), /* @__PURE__ */ react.default.createElement("div", { className: "inline-flex items-center gap-2" }, /* @__PURE__ */ react.default.createElement(lucide_react.Users, {
3141
+ size: 14,
3142
+ className: "text-white/50"
3143
+ }), /* @__PURE__ */ react.default.createElement("span", null, detail.headerSummary.guestCount, " guests")))), /* @__PURE__ */ react.default.createElement("div", { className: "flex shrink-0 items-center justify-end gap-2 pt-[14px]" }, /* @__PURE__ */ react.default.createElement("span", { className: `rounded-full px-3 py-1 text-[16px] leading-none font-semibold shadow-lg ${paymentTagClass(getPaymentDisplay(detail), isLight)}` }, getPaymentDisplay(detail)), /* @__PURE__ */ react.default.createElement("span", { className: `rounded-full px-3 py-1 text-[16px] leading-none font-semibold shadow-lg ${fulfillmentTagClass(getFulfillmentDisplay(detailItem, detail), isLight)}` }, getFulfillmentDisplay(detailItem, detail), detail.guestCount > 0 ? ` ${detail.checkedInCount}/${detail.guestCount}` : ""))), /* @__PURE__ */ react.default.createElement("div", { className: `pointer-events-none absolute bottom-2 right-4 text-[11px] text-white/48` }, "Last updated ", ((_detail$history2 = detail.history) === null || _detail$history2 === void 0 || (_detail$history2 = _detail$history2[0]) === null || _detail$history2 === void 0 ? void 0 : _detail$history2.time) || "--")), /* @__PURE__ */ react.default.createElement("div", { className: "grid h-[calc(100%-88px)] grid-cols-[78px_1fr]" }, /* @__PURE__ */ react.default.createElement("div", { className: `border-r px-2 py-3 border-zinc-800 bg-[#11162a]` }, /* @__PURE__ */ react.default.createElement("div", { className: "flex h-full flex-col gap-3" }, /* @__PURE__ */ react.default.createElement("div", { className: "flex flex-col gap-3" }, tabs.map((tab) => {
3144
+ const meta = tabMeta(tab);
3145
+ const Icon = meta.icon;
3146
+ const badge = tabBadgeValue(tab, detail);
3147
+ const unread = isMainTabUnread(tab, detail, viewedForDetail, viewedSubtabsForDetail);
3148
+ return /* @__PURE__ */ react.default.createElement("button", {
3149
+ key: tab,
3150
+ onClick: () => setDetailTab(tab),
3151
+ className: `flex flex-col items-center gap-2 rounded-2xl px-2 py-3 text-center text-xs ${detailTab === tab ? "bg-violet-600/20 text-white ring-1 ring-violet-400/40" : "text-zinc-400 hover:bg-zinc-800"}`
3152
+ }, /* @__PURE__ */ react.default.createElement("div", { className: `relative flex h-11 w-11 items-center justify-center rounded-full ${detailTab === tab ? "bg-violet-600/25 border border-violet-400/40" : "bg-zinc-800 border border-zinc-700"}` }, /* @__PURE__ */ react.default.createElement(Icon, { size: 18 }), badge && /* @__PURE__ */ react.default.createElement("span", { className: `absolute -right-2 -top-1 min-w-[18px] rounded-full px-1.5 py-0.5 text-[10px] font-semibold ${tabBadgeClass(unread)}` }, badge)), /* @__PURE__ */ react.default.createElement("span", null, meta.label));
3153
+ })), /* @__PURE__ */ react.default.createElement("div", {
3154
+ className: "mt-auto relative",
3155
+ ref: detailPrefRef
3156
+ }, /* @__PURE__ */ react.default.createElement("button", {
3157
+ onClick: () => setDetailPrefOpen((v) => !v),
3158
+ className: `flex w-full items-center justify-center rounded-2xl px-2 py-3 ${detailPrefOpen ? "bg-violet-600/20 text-white ring-1 ring-violet-400/40" : "text-zinc-400 hover:bg-zinc-800"}`
3159
+ }, /* @__PURE__ */ react.default.createElement("div", { className: `flex h-11 w-11 items-center justify-center rounded-full ${detailPrefOpen ? "bg-violet-600/25 border border-violet-400/40" : "bg-zinc-800 border border-zinc-700"}` }, /* @__PURE__ */ react.default.createElement(lucide_react.Settings2, { size: 18 }))), detailPrefOpen && /* @__PURE__ */ react.default.createElement("div", { className: `absolute bottom-[calc(100%+10px)] left-0 z-30 w-[300px] rounded-2xl border p-3 shadow-2xl border-zinc-700 bg-[#121217]` }, /* @__PURE__ */ react.default.createElement("div", { className: `mb-2 text-xs uppercase tracking-[0.14em] text-zinc-500` }, "Detail preferences"), /* @__PURE__ */ react.default.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("div", { className: `mb-2 text-[11px] uppercase tracking-[0.12em] text-zinc-500` }, "Default open mode"), /* @__PURE__ */ react.default.createElement("div", { className: `inline-flex w-full rounded-2xl border p-1 border-zinc-700 bg-[#151822]` }, /* @__PURE__ */ react.default.createElement("button", {
3160
+ onClick: () => {
3161
+ setPreferQuickPopup(true);
3162
+ setPreferDrawerOpen(false);
3163
+ },
3164
+ className: `flex-1 rounded-xl px-3 py-2 text-xs font-medium ${preferQuickPopup ? "bg-violet-600 text-white" : "text-zinc-400"}`
3165
+ }, "Pop-up express window"), /* @__PURE__ */ react.default.createElement("button", {
3166
+ onClick: () => {
3167
+ setPreferQuickPopup(false);
3168
+ setPreferDrawerOpen(true);
3169
+ },
3170
+ className: `flex-1 rounded-xl px-3 py-2 text-xs font-medium ${preferDrawerOpen ? "bg-violet-600 text-white" : "text-zinc-400"}`
3171
+ }, "Detail first"))), /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("div", { className: `mb-2 text-[11px] uppercase tracking-[0.12em] text-zinc-500` }, "Default tab"), /* @__PURE__ */ react.default.createElement("div", { className: "grid grid-cols-2 gap-2" }, [
3172
+ ["summary", "Summary"],
3173
+ ["items", "Items"],
3174
+ ["payments", "Payments"],
3175
+ ["guest", "Guests"],
3176
+ ["files", "Files"],
3177
+ ["history", "History"]
3178
+ ].map(([key, label]) => /* @__PURE__ */ react.default.createElement("button", {
3179
+ key,
3180
+ onClick: () => setDefaultDetailTab(key),
3181
+ className: `rounded-xl px-3 py-2 text-xs font-medium ${defaultDetailTab === key ? "bg-violet-600 text-white" : "border border-zinc-700 bg-white/5 text-zinc-300"}`
3182
+ }, label))))))))), /* @__PURE__ */ react.default.createElement("div", { className: "flex h-full flex-col overflow-hidden" }, /* @__PURE__ */ react.default.createElement("div", { className: "pisell-scroll-hidden flex-1 overflow-y-auto px-4 py-4 pb-6" }, detailTab === "summary" && /* @__PURE__ */ react.default.createElement("div", { className: "space-y-3 pb-2" }, /* @__PURE__ */ react.default.createElement("div", { className: `w-full rounded-3xl border p-4 text-left border-zinc-800 bg-[#151822]` }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start justify-between gap-4" }, /* @__PURE__ */ react.default.createElement("div", { className: "min-w-0 flex-1" }, /* @__PURE__ */ react.default.createElement("div", { className: `text-xs uppercase tracking-[0.14em] text-zinc-500` }, "Booking"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-2 text-xl font-semibold text-white` }, detail.headerSummary.customerName), /* @__PURE__ */ react.default.createElement("div", { className: `mt-2 space-y-1.5 text-sm text-zinc-300` }, /* @__PURE__ */ react.default.createElement("div", { className: "flex flex-wrap items-center gap-x-4 gap-y-1" }, /* @__PURE__ */ react.default.createElement("span", { className: "inline-flex items-center gap-2" }, /* @__PURE__ */ react.default.createElement(lucide_react.CalendarDays, { size: 14 }), " ", detail.schedule.startDate), /* @__PURE__ */ react.default.createElement("span", { className: "inline-flex items-center gap-2" }, /* @__PURE__ */ react.default.createElement(lucide_react.Clock4, { size: 14 }), " ", detail.schedule.startTime, " -", " ", detail.schedule.endTime)), /* @__PURE__ */ react.default.createElement("div", { className: "flex flex-wrap items-center gap-x-4 gap-y-1" }, /* @__PURE__ */ react.default.createElement("span", { className: "inline-flex items-center gap-2" }, /* @__PURE__ */ react.default.createElement(lucide_react.MapPinned, { size: 14 }), " ", detail.headerSummary.resourceLabel), /* @__PURE__ */ react.default.createElement("span", { className: "inline-flex items-center gap-2" }, /* @__PURE__ */ react.default.createElement(lucide_react.Users, { size: 14 }), " ", detail.guestCount, " guests")), /* @__PURE__ */ react.default.createElement("div", { className: "flex flex-wrap items-center gap-x-4 gap-y-1" }, detail.customer.phone && /* @__PURE__ */ react.default.createElement("span", { className: "inline-flex items-center gap-2" }, /* @__PURE__ */ react.default.createElement(lucide_react.Phone, { size: 14 }), " ", detail.customer.phone), detail.customer.email && /* @__PURE__ */ react.default.createElement("span", { className: "inline-flex items-center gap-2" }, /* @__PURE__ */ react.default.createElement(lucide_react.User, { size: 14 }), " ", detail.customer.email)))), /* @__PURE__ */ react.default.createElement("div", { className: "flex shrink-0 flex-col items-end gap-2 text-right" }, /* @__PURE__ */ react.default.createElement("button", {
3183
+ onClick: (e) => {
3184
+ var _visibleCourts$3, _visibleCourts$4;
3185
+ e.stopPropagation();
3186
+ setMoveConfirm({
3187
+ item: detailItem,
3188
+ targetCourtId: detailItem.courtId || ((_visibleCourts$3 = visibleCourts[0]) === null || _visibleCourts$3 === void 0 ? void 0 : _visibleCourts$3.id) || courts[0].id,
3189
+ targetDate: detailItem.date,
3190
+ targetHour: detailItem.startHour
3191
+ });
3192
+ setMoveDraft({
3193
+ targetCourtId: detailItem.courtId || ((_visibleCourts$4 = visibleCourts[0]) === null || _visibleCourts$4 === void 0 ? void 0 : _visibleCourts$4.id) || courts[0].id,
3194
+ targetDate: detailItem.date,
3195
+ targetHour: detailItem.startHour
3196
+ });
3197
+ },
3198
+ className: `rounded-2xl px-3 py-2 text-sm font-medium border border-zinc-700 bg-white/5 text-white hover:bg-white/10`
3199
+ }, "Change"), /* @__PURE__ */ react.default.createElement("div", { className: `text-xs text-zinc-500` }, "Last updated"), /* @__PURE__ */ react.default.createElement("div", { className: `text-xs text-zinc-400` }, ((_detail$history3 = detail.history) === null || _detail$history3 === void 0 || (_detail$history3 = _detail$history3[0]) === null || _detail$history3 === void 0 ? void 0 : _detail$history3.time) || "--")))), /* @__PURE__ */ react.default.createElement("button", {
3200
+ onClick: () => {
3201
+ setDetailTab("files");
3202
+ setFilesSubtab("notes");
3203
+ },
3204
+ className: `w-full rounded-3xl border p-4 text-left border-zinc-800 bg-[#151822] hover:bg-[#1a1d29]`
3205
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start justify-between gap-3" }, /* @__PURE__ */ react.default.createElement("div", { className: "min-w-0 flex-1" }, /* @__PURE__ */ react.default.createElement("div", { className: `text-xs uppercase tracking-[0.14em] text-zinc-500` }, "Notes"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-2 text-sm leading-6 text-zinc-300` }, detail.note || "No order note.")), /* @__PURE__ */ react.default.createElement("div", { className: "flex shrink-0 items-center gap-2" }, /* @__PURE__ */ react.default.createElement("div", { className: `rounded-full px-2.5 py-1 text-xs font-semibold bg-violet-600/20 text-violet-200` }, "+", (((_detail$noteGroups4 = detail.noteGroups) === null || _detail$noteGroups4 === void 0 || (_detail$noteGroups4 = _detail$noteGroups4.internal) === null || _detail$noteGroups4 === void 0 ? void 0 : _detail$noteGroups4.length) || 0) + (((_detail$noteGroups5 = detail.noteGroups) === null || _detail$noteGroups5 === void 0 || (_detail$noteGroups5 = _detail$noteGroups5.order) === null || _detail$noteGroups5 === void 0 ? void 0 : _detail$noteGroups5.length) || 0) + (((_detail$noteGroups6 = detail.noteGroups) === null || _detail$noteGroups6 === void 0 || (_detail$noteGroups6 = _detail$noteGroups6.item) === null || _detail$noteGroups6 === void 0 ? void 0 : _detail$noteGroups6.length) || 0)), /* @__PURE__ */ react.default.createElement("button", {
3206
+ onClick: (e) => {
3207
+ e.stopPropagation();
3208
+ setDetailTab("files");
3209
+ setFilesSubtab("notes");
3210
+ },
3211
+ className: `rounded-2xl px-3 py-2 text-sm font-medium border border-zinc-700 bg-white/5 text-white hover:bg-white/10`
3212
+ }, "Change")))), /* @__PURE__ */ react.default.createElement("button", {
3213
+ onClick: () => setDetailTab("items"),
3214
+ className: `w-full rounded-3xl border p-4 text-left border-zinc-800 bg-[#151822] hover:bg-[#1a1d29]`
3215
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "mb-3 flex items-center justify-between gap-3" }, /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("div", { className: `text-xs uppercase tracking-[0.14em] text-zinc-500` }, "Items"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-sm text-zinc-400` }, ((_detail$itemSummary = detail.itemSummary) === null || _detail$itemSummary === void 0 ? void 0 : _detail$itemSummary.itemCount) || 0, " ", "items ·", " ", ((_detail$itemSummary2 = detail.itemSummary) === null || _detail$itemSummary2 === void 0 ? void 0 : _detail$itemSummary2.itemQtyTotal) || 0, " ", "qty")), /* @__PURE__ */ react.default.createElement("button", {
3216
+ onClick: (e) => {
3217
+ e.stopPropagation();
3218
+ setDetailTab("items");
3219
+ },
3220
+ className: `rounded-2xl px-3 py-2 text-sm font-medium border border-zinc-700 bg-white/5 text-white hover:bg-white/10`
3221
+ }, "Change")), /* @__PURE__ */ react.default.createElement("div", { className: "space-y-3" }, detail.items.slice(0, 4).map((row) => /* @__PURE__ */ react.default.createElement("div", {
3222
+ key: row.id,
3223
+ className: `rounded-2xl border px-3 py-3 border-zinc-700 bg-[#101117]`
3224
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start gap-3" }, /* @__PURE__ */ react.default.createElement("div", { className: "relative h-16 w-16 shrink-0 overflow-hidden rounded-2xl border border-black/5 bg-[linear-gradient(135deg,#8B5CF6,#6941C6)] text-white" }, /* @__PURE__ */ react.default.createElement("div", { className: "flex h-full w-full items-center justify-center text-lg font-semibold" }, String(row.name || "I").slice(0, 1).toUpperCase()), /* @__PURE__ */ react.default.createElement("div", { className: "absolute -left-1 -top-1 flex h-7 min-w-7 items-center justify-center rounded-full bg-[var(--brand-primary)] px-1.5 text-xs font-semibold text-white shadow-lg" }, row.qty)), /* @__PURE__ */ react.default.createElement("div", { className: "min-w-0 flex-1" }, /* @__PURE__ */ react.default.createElement("div", { className: `truncate text-[17px] font-semibold text-white` }, row.name), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-sm text-zinc-400` }, row.specs || row.unitLabel), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 line-clamp-2 text-sm text-zinc-300` }, row.note)), /* @__PURE__ */ react.default.createElement("div", { className: "shrink-0 text-right" }, /* @__PURE__ */ react.default.createElement("div", { className: `text-[17px] font-semibold text-white` }, detail.paymentSummary.currencySymbol, row.total.toFixed(2)))))), detail.items.length > 4 && /* @__PURE__ */ react.default.createElement("div", { className: `text-sm text-zinc-400` }, "+", detail.items.length - 4, " more items")))), detailTab === "items" && /* @__PURE__ */ react.default.createElement("div", { className: `space-y-3 rounded-3xl border p-3 border-zinc-800 bg-[#151822]` }, /* @__PURE__ */ react.default.createElement("div", { className: `overflow-hidden rounded-[22px] border border-zinc-700 bg-[#101117]` }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start gap-3 px-4 py-4" }, /* @__PURE__ */ react.default.createElement("div", { className: `h-20 w-20 shrink-0 overflow-hidden rounded-2xl bg-zinc-800` }, /* @__PURE__ */ react.default.createElement("img", {
3225
+ src: "https://images.unsplash.com/photo-1517649763962-0c623066013b?auto=format&fit=crop&w=300&q=80",
3226
+ alt: "booking item",
3227
+ className: "h-full w-full object-cover"
3228
+ })), /* @__PURE__ */ react.default.createElement("div", { className: "min-w-0 flex-1" }, /* @__PURE__ */ react.default.createElement("div", { className: `text-[15px] font-semibold leading-tight text-white` }, "Private Lesson Package"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-[14px] font-semibold leading-none text-white` }, "$30"), /* @__PURE__ */ react.default.createElement("button", { className: "mt-2 inline-flex items-center gap-2 text-[14px] font-semibold text-blue-500" }, /* @__PURE__ */ react.default.createElement(lucide_react.NotebookPen, { size: 16 }), " Edit")), /* @__PURE__ */ react.default.createElement("button", { className: `rounded-xl p-1.5 text-zinc-400 hover:bg-zinc-800` }, /* @__PURE__ */ react.default.createElement(lucide_react.X, { size: 18 }))), /* @__PURE__ */ react.default.createElement("div", { className: `mx-4 border-t border-zinc-700` }), /* @__PURE__ */ react.default.createElement("div", { className: "space-y-2.5 px-4 py-3.5" }, /* @__PURE__ */ react.default.createElement("div", { className: `flex items-center justify-between rounded-2xl border px-3.5 py-3 border-zinc-700 bg-[#151822]` }, /* @__PURE__ */ react.default.createElement("span", { className: `text-[14px] text-zinc-200` }, "14:00 2026/03/31 ~ 16:00 2026/03/31"), /* @__PURE__ */ react.default.createElement(lucide_react.CalendarDays, {
3229
+ size: 17,
3230
+ className: "text-zinc-500"
3231
+ })), /* @__PURE__ */ react.default.createElement("div", { className: "flex flex-wrap gap-2.5" }, /* @__PURE__ */ react.default.createElement("div", { className: `inline-flex items-center gap-2 rounded-full border px-3.5 py-2 text-[14px] border-zinc-700 bg-[#151822] text-zinc-200` }, "Jack; Ami", " ", /* @__PURE__ */ react.default.createElement(lucide_react.ChevronRight, {
3232
+ size: 15,
3233
+ className: "rotate-90"
3234
+ }))), /* @__PURE__ */ react.default.createElement("div", { className: "grid gap-2.5" }, /* @__PURE__ */ react.default.createElement("div", { className: "flex gap-2.5" }, /* @__PURE__ */ react.default.createElement("button", { className: `h-12 w-12 shrink-0 rounded-2xl border text-[18px] border-zinc-700 bg-[#151822] text-pink-400` }, "❤"), /* @__PURE__ */ react.default.createElement("div", { className: `flex flex-1 items-center justify-between rounded-2xl border px-3.5 py-3 text-[14px] border-zinc-700 bg-[#151822] text-zinc-200` }, /* @__PURE__ */ react.default.createElement("span", null, "VIP Court 1"), /* @__PURE__ */ react.default.createElement(lucide_react.ChevronRight, {
3235
+ size: 15,
3236
+ className: "rotate-90"
3237
+ }))), /* @__PURE__ */ react.default.createElement("div", { className: "flex gap-2.5" }, /* @__PURE__ */ react.default.createElement("button", { className: `h-12 w-12 shrink-0 rounded-2xl border text-[18px] border-zinc-700 bg-[#151822] text-zinc-400` }, "♡"), /* @__PURE__ */ react.default.createElement("div", { className: `flex flex-1 items-center justify-between rounded-2xl border px-3.5 py-3 text-[14px] border-zinc-700 bg-[#151822] text-zinc-200` }, /* @__PURE__ */ react.default.createElement("span", null, "Coach Joey"), /* @__PURE__ */ react.default.createElement(lucide_react.ChevronRight, {
3238
+ size: 15,
3239
+ className: "rotate-90"
3240
+ }))))), /* @__PURE__ */ react.default.createElement("div", { className: `mx-4 border-t border-zinc-700` }), /* @__PURE__ */ react.default.createElement("div", { className: "px-4 py-3.5" }, /* @__PURE__ */ react.default.createElement("div", { className: `mb-2.5 text-[15px] font-semibold text-white` }, "Items in package"), /* @__PURE__ */ react.default.createElement("div", { className: "space-y-2.5" }, /* @__PURE__ */ react.default.createElement("div", { className: `rounded-2xl border p-3.5 border-zinc-700 bg-[#151822]` }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start justify-between gap-3" }, /* @__PURE__ */ react.default.createElement("div", { className: "min-w-0 flex-1" }, /* @__PURE__ */ react.default.createElement("div", { className: `text-[15px] font-semibold leading-tight text-zinc-100` }, "2-Hours (Private Coaching)"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-[13px] leading-snug text-zinc-400` }, "Shuttle rental $10 × 1")), /* @__PURE__ */ react.default.createElement("div", { className: `text-right text-[13px] leading-snug text-zinc-300` }, /* @__PURE__ */ react.default.createElement("div", null, "$30"), /* @__PURE__ */ react.default.createElement("div", { className: "mt-1" }, "$10"))), /* @__PURE__ */ react.default.createElement("div", { className: `mt-2.5 flex items-center justify-between border-t pt-2.5 border-zinc-700` }, /* @__PURE__ */ react.default.createElement("div", { className: `text-[16px] font-semibold text-zinc-300` }, "$40"), /* @__PURE__ */ react.default.createElement("div", { className: `text-[16px] font-semibold text-zinc-400` }, "×4"), /* @__PURE__ */ react.default.createElement("div", { className: `text-[18px] font-semibold text-white` }, "$160.00"))), /* @__PURE__ */ react.default.createElement("div", { className: `rounded-2xl border p-3.5 border-zinc-700 bg-[#151822]` }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start justify-between gap-3" }, /* @__PURE__ */ react.default.createElement("div", { className: "min-w-0 flex-1" }, /* @__PURE__ */ react.default.createElement("div", { className: `text-[15px] font-semibold leading-tight text-zinc-100` }, "Lesson package + equipment"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-[13px] leading-snug text-zinc-400` }, "Coach: Joey; Court: VIP Court 1; SKU: PR-2H"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-[13px] leading-snug text-zinc-400` }, "Shuttle rental $10 × 1"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-[13px] leading-snug text-zinc-400` }, "Racket rental $10 × 2")), /* @__PURE__ */ react.default.createElement("div", { className: `text-right text-[13px] leading-snug text-zinc-300` }, /* @__PURE__ */ react.default.createElement("div", null, "$30"), /* @__PURE__ */ react.default.createElement("div", { className: "mt-1" }, "$10"), /* @__PURE__ */ react.default.createElement("div", { className: "mt-1" }, "$20"))), /* @__PURE__ */ react.default.createElement("div", { className: `mt-2.5 flex items-center justify-between border-t pt-2.5 border-zinc-700` }, /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("div", { className: `text-[16px] font-semibold text-zinc-300` }, "$40"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-0.5 text-[13px] line-through text-zinc-500` }, "$48")), /* @__PURE__ */ react.default.createElement("div", { className: `text-[16px] font-semibold text-zinc-400` }, "×4"), /* @__PURE__ */ react.default.createElement("div", { className: "text-right" }, /* @__PURE__ */ react.default.createElement("div", { className: `text-[18px] font-semibold text-white` }, "$160.00"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-0.5 text-[13px] line-through text-zinc-500` }, "$178.00")))))), /* @__PURE__ */ react.default.createElement("div", { className: `mx-4 border-t border-zinc-700` }), /* @__PURE__ */ react.default.createElement("div", { className: "px-4 py-3.5" }, /* @__PURE__ */ react.default.createElement("div", { className: `mb-2.5 text-[15px] font-semibold text-white` }, "Sales"), /* @__PURE__ */ react.default.createElement("div", { className: "space-y-2.5" }, /* @__PURE__ */ react.default.createElement("div", { className: `rounded-2xl border p-3.5 border-zinc-700 bg-[#151822]` }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start gap-3" }, /* @__PURE__ */ react.default.createElement("div", { className: `h-14 w-14 shrink-0 overflow-hidden rounded-2xl bg-zinc-800` }, /* @__PURE__ */ react.default.createElement("img", {
3241
+ src: "https://images.unsplash.com/photo-1551024601-bec78aea704b?auto=format&fit=crop&w=300&q=80",
3242
+ alt: "milk tea",
3243
+ className: "h-full w-full object-cover"
3244
+ })), /* @__PURE__ */ react.default.createElement("div", { className: "min-w-0 flex-1" }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start justify-between gap-3" }, /* @__PURE__ */ react.default.createElement("div", { className: "min-w-0 flex-1" }, /* @__PURE__ */ react.default.createElement("div", { className: `text-[15px] font-semibold leading-tight text-white` }, "Night Market Drinks"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-[14px] font-semibold leading-none text-white` }, "$30")), /* @__PURE__ */ react.default.createElement("button", { className: `shrink-0 rounded-xl p-1.5 text-zinc-400 hover:bg-zinc-800` }, /* @__PURE__ */ react.default.createElement(lucide_react.X, { size: 18 }))), /* @__PURE__ */ react.default.createElement("div", { className: "mt-2 space-y-0.5" }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start justify-between gap-3" }, /* @__PURE__ */ react.default.createElement("div", { className: `min-w-0 flex-1 text-[13px] leading-snug text-zinc-400` }, "Red bean $10 × 1"), /* @__PURE__ */ react.default.createElement("div", { className: `shrink-0 text-[13px] leading-snug text-zinc-300` }, "$10")), /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start justify-between gap-3" }, /* @__PURE__ */ react.default.createElement("div", { className: `min-w-0 flex-1 text-[13px] leading-snug text-zinc-400` }, "Pearl $10 × 1"), /* @__PURE__ */ react.default.createElement("div", { className: `shrink-0 text-[13px] leading-snug text-zinc-300` }, "$10")), /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start justify-between gap-3" }, /* @__PURE__ */ react.default.createElement("div", { className: `min-w-0 flex-1 text-[13px] leading-snug text-zinc-400` }, "Boba mochi $5 × 2"), /* @__PURE__ */ react.default.createElement("div", { className: `shrink-0 text-[13px] leading-snug text-zinc-300` }, "$10")), /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start justify-between gap-3" }, /* @__PURE__ */ react.default.createElement("div", { className: `min-w-0 flex-1 text-[13px] leading-snug text-zinc-400` }, "Matcha lid with a very long custom name to show wrapping"), /* @__PURE__ */ react.default.createElement("div", { className: `shrink-0 text-[13px] leading-snug text-zinc-300` }, "$10"))), /* @__PURE__ */ react.default.createElement("button", { className: "mt-2 inline-flex items-center gap-2 text-[14px] font-semibold text-blue-500" }, /* @__PURE__ */ react.default.createElement(lucide_react.NotebookPen, { size: 16 }), " Edit"))), /* @__PURE__ */ react.default.createElement("div", { className: `mt-2.5 border-t pt-2.5 border-zinc-700` }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-end justify-between gap-3" }, /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("div", { className: `text-[16px] font-semibold text-zinc-300` }, "$40"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-0.5 text-[13px] line-through text-zinc-500` }, "$48")), /* @__PURE__ */ react.default.createElement("div", { className: `text-[16px] font-semibold text-zinc-400` }, "×4"), /* @__PURE__ */ react.default.createElement("div", { className: "text-right" }, /* @__PURE__ */ react.default.createElement("div", { className: `text-[18px] font-semibold text-white` }, "$160.00"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-0.5 text-[13px] line-through text-zinc-500` }, "$178.00")))))), /* @__PURE__ */ react.default.createElement("button", { className: `mt-3.5 w-full rounded-2xl border px-4 py-2.5 text-[15px] font-semibold border-zinc-700 bg-[#151822] text-zinc-200` }, "Add time")))), detailTab === "payments" && /* @__PURE__ */ react.default.createElement("div", { className: `rounded-3xl border p-4 border-zinc-800 bg-[#151822]` }, detail.payments.length === 0 ? /* @__PURE__ */ react.default.createElement("div", { className: `rounded-2xl p-4 text-sm bg-[#101117] text-zinc-400` }, "No payments yet.") : /* @__PURE__ */ react.default.createElement("div", { className: "space-y-4" }, detail.payments.map((pay, index) => {
3245
+ const stamp = formatTimelineStamp(pay.time);
3246
+ return /* @__PURE__ */ react.default.createElement("div", {
3247
+ key: pay.id,
3248
+ className: "grid grid-cols-[92px_20px_1fr] gap-3 items-start"
3249
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "pt-1 text-right" }, /* @__PURE__ */ react.default.createElement("div", { className: `text-[11px] font-semibold text-violet-300` }, stamp.time), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-[11px] text-zinc-500` }, stamp.date)), /* @__PURE__ */ react.default.createElement("div", { className: "relative flex justify-center pt-1" }, index !== detail.payments.length - 1 && /* @__PURE__ */ react.default.createElement("div", { className: `absolute top-5 bottom-[-22px] left-1/2 w-px -translate-x-1/2 bg-zinc-700` }), /* @__PURE__ */ react.default.createElement("div", { className: `relative z-10 h-3.5 w-3.5 rounded-full bg-violet-400 ring-4 ring-[#151822]` })), /* @__PURE__ */ react.default.createElement("div", { className: `rounded-2xl border p-4 border-zinc-700 bg-[#101117]` }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start justify-between gap-3" }, /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("div", { className: `font-semibold text-white` }, pay.label), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-sm text-zinc-300` }, pay.method)), /* @__PURE__ */ react.default.createElement("div", { className: "text-right" }, /* @__PURE__ */ react.default.createElement("div", { className: `font-semibold text-violet-200` }, detail.paymentSummary.currencySymbol, pay.amount.toFixed(2)), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 inline-flex rounded-full px-2 py-0.5 text-[11px] font-semibold ${pay.status === "paid" ? "bg-emerald-500/20 text-emerald-300" : "bg-amber-500/20 text-amber-300"}` }, pay.status)))));
3250
+ }))), detailTab === "guest" && /* @__PURE__ */ react.default.createElement("div", { className: `space-y-3 rounded-3xl border p-4 border-zinc-800 bg-[#151822]` }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-center justify-between gap-3" }, /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("div", { className: `text-xs uppercase tracking-[0.14em] text-zinc-500` }, "Guests"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-sm text-zinc-400` }, guestMockRows.filter((row) => row.checkedIn).length, " ", "/ ", detail.guestCount, " checked-in")), /* @__PURE__ */ react.default.createElement("button", {
3251
+ onClick: () => setGuestBulkActionOpen(true),
3252
+ className: `rounded-2xl px-3 py-2 text-sm font-medium border border-zinc-700 bg-white/5 text-white hover:bg-white/10`
3253
+ }, "Check-in All")), /* @__PURE__ */ react.default.createElement("div", { className: `rounded-2xl border p-4 border-zinc-700 bg-[#101117]` }), guestMockRows.map((guest) => /* @__PURE__ */ react.default.createElement("div", {
3254
+ key: guest.id,
3255
+ className: `rounded-2xl p-4 bg-[#101117]`
3256
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start justify-between gap-3" }, /* @__PURE__ */ react.default.createElement("div", { className: "min-w-0 flex-1" }, /* @__PURE__ */ react.default.createElement("div", { className: `font-semibold text-white` }, guest.name), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-sm text-zinc-400` }, guest.note)), /* @__PURE__ */ react.default.createElement("div", { className: "flex shrink-0 items-center gap-2" }, /* @__PURE__ */ react.default.createElement("button", {
3257
+ onClick: () => {
3258
+ setGuestMockRows((prev) => prev.map((row) => row.id === guest.id ? require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, row), {}, {
3259
+ checkedIn: !row.checkedIn,
3260
+ noShow: false
3261
+ }) : row));
3262
+ },
3263
+ className: `rounded-2xl px-3 py-2 text-sm font-medium ${guest.checkedIn ? "border border-amber-500/35 bg-amber-500/15 text-white" : "border border-violet-500/35 bg-violet-600/15 text-white"}`
3264
+ }, guest.checkedIn ? "Un-checkin" : "Check-in"), guest.checkedIn && /* @__PURE__ */ react.default.createElement("div", { className: `inline-flex h-10 w-10 items-center justify-center rounded-2xl border border-emerald-500/35 bg-emerald-500/15 text-emerald-300` }, /* @__PURE__ */ react.default.createElement(lucide_react.CheckCircle2, { size: 18 })), /* @__PURE__ */ react.default.createElement("div", {
3265
+ className: "relative",
3266
+ "data-guest-row-menu": true
3267
+ }, /* @__PURE__ */ react.default.createElement("button", {
3268
+ onClick: () => setGuestRowMenu((prev) => prev === guest.id ? null : guest.id),
3269
+ className: `rounded-2xl px-3 py-2 text-sm font-semibold border border-zinc-700 bg-white/5 text-white`
3270
+ }, "⋮"), guestRowMenu === guest.id && /* @__PURE__ */ react.default.createElement("div", { className: `absolute right-0 top-[calc(100%+8px)] z-20 min-w-[150px] rounded-2xl border p-2 shadow-xl border-zinc-700 bg-[#151822]` }, /* @__PURE__ */ react.default.createElement("button", {
3271
+ onClick: () => {
3272
+ setGuestMockRows((prev) => prev.map((row) => row.id === guest.id ? require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, row), {}, {
3273
+ noShow: !row.noShow,
3274
+ checkedIn: false
3275
+ }) : row));
3276
+ setGuestRowMenu(null);
3277
+ },
3278
+ className: `mb-1 block w-full rounded-xl px-3 py-2 text-left text-sm text-zinc-200 hover:bg-white/5`
3279
+ }, "No-show"), /* @__PURE__ */ react.default.createElement("button", {
3280
+ onClick: () => {
3281
+ setGuestMockRows((prev) => prev.filter((row) => row.id !== guest.id));
3282
+ setGuestRowMenu(null);
3283
+ },
3284
+ className: `block w-full rounded-xl px-3 py-2 text-left text-sm text-red-300 hover:bg-red-500/10`
3285
+ }, "Remove"))))))), guestBulkActionOpen && /* @__PURE__ */ react.default.createElement("div", { className: "fixed inset-0 z-[76] flex items-center justify-center bg-black/45 p-4 backdrop-blur-sm" }, /* @__PURE__ */ react.default.createElement("div", {
3286
+ ref: guestBulkActionRef,
3287
+ className: `w-full max-w-[420px] rounded-3xl border p-5 shadow-2xl border-zinc-700 bg-[#121217]`
3288
+ }, /* @__PURE__ */ react.default.createElement("div", { className: `text-lg font-semibold text-white` }, "Check-in All"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-2 text-sm text-zinc-400` }, "Choose how to apply bulk check-in for all guests in this booking."), /* @__PURE__ */ react.default.createElement("div", { className: "mt-4 grid gap-3" }, /* @__PURE__ */ react.default.createElement("button", {
3289
+ onClick: () => {
3290
+ setGuestMockRows((prev) => prev.map((row) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, row), {}, {
3291
+ checkedIn: true,
3292
+ noShow: false
3293
+ })));
3294
+ setGuestBulkActionOpen(false);
3295
+ },
3296
+ className: `rounded-2xl px-4 py-3 text-left text-sm font-semibold border border-violet-500/35 bg-violet-600/15 text-white hover:bg-violet-600/25`
3297
+ }, "Check-in all"), /* @__PURE__ */ react.default.createElement("button", {
3298
+ onClick: () => {
3299
+ setGuestMockRows((prev) => prev.map((row) => row.noShow ? require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, row), {}, { checkedIn: false }) : require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, row), {}, { checkedIn: true })));
3300
+ setGuestBulkActionOpen(false);
3301
+ },
3302
+ className: `rounded-2xl px-4 py-3 text-left text-sm font-semibold border border-zinc-700 bg-white/5 text-white hover:bg-white/10`
3303
+ }, "Check-in all except no-show")), /* @__PURE__ */ react.default.createElement("div", { className: "mt-4 flex justify-end" }, /* @__PURE__ */ react.default.createElement("button", {
3304
+ onClick: () => setGuestBulkActionOpen(false),
3305
+ className: `rounded-2xl px-3 py-2 text-sm font-medium border border-zinc-700 bg-white/5 text-white hover:bg-white/10`
3306
+ }, "Close"))))), detailTab === "files" && /* @__PURE__ */ react.default.createElement("div", { className: `rounded-3xl border p-4 border-zinc-800 bg-[#151822]` }, /* @__PURE__ */ react.default.createElement("div", { className: "mb-3 flex flex-wrap gap-2" }, [
3307
+ ["notes", "Notes"],
3308
+ ["form", "Forms"],
3309
+ ["uploaded", "Uploaded"],
3310
+ ["invoice", "Invoice"]
3311
+ ].map(([key, label]) => /* @__PURE__ */ react.default.createElement("button", {
3312
+ key,
3313
+ onClick: () => setFilesSubtab(key),
3314
+ className: `rounded-2xl px-3 py-2 text-sm ${filesSubtab === key ? "bg-violet-600 text-white" : "border border-zinc-700 bg-white/5 text-zinc-300"}`
3315
+ }, label))), filesSubtab === "notes" ? /* @__PURE__ */ react.default.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ react.default.createElement("div", { className: "flex flex-wrap items-center gap-2" }, [
3316
+ ["internal-notes", "Internal"],
3317
+ ["order-notes", "Order"],
3318
+ ["item-notes", "Item"]
3319
+ ].map(([anchor, label]) => /* @__PURE__ */ react.default.createElement("a", {
3320
+ key: anchor,
3321
+ href: `#${anchor}`,
3322
+ className: `rounded-2xl px-3 py-2 text-sm border border-zinc-700 bg-white/5 text-zinc-200`
3323
+ }, label))), /* @__PURE__ */ react.default.createElement("div", {
3324
+ id: "internal-notes",
3325
+ className: `rounded-2xl border p-4 border-zinc-700 bg-[#101117]`
3326
+ }, /* @__PURE__ */ react.default.createElement("div", { className: `mb-3 text-xs uppercase tracking-[0.12em] text-zinc-500` }, "Internal notes"), detailWithNoteOverrides.noteGroups.internal.length === 0 ? /* @__PURE__ */ react.default.createElement("div", { className: `text-sm text-zinc-400` }, "No internal notes.") : detailWithNoteOverrides.noteGroups.internal.map((note) => /* @__PURE__ */ react.default.createElement("div", {
3327
+ key: note.id,
3328
+ className: `mb-2 rounded-xl px-3 py-3 last:mb-0 bg-[#151822]`
3329
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start justify-between gap-3" }, /* @__PURE__ */ react.default.createElement("div", { className: `min-w-0 flex-1 text-sm text-zinc-300` }, note.text), /* @__PURE__ */ react.default.createElement("button", {
3330
+ onClick: () => setNoteEditor({
3331
+ id: note.id,
3332
+ text: note.text,
3333
+ title: "Edit internal note"
3334
+ }),
3335
+ className: `shrink-0 rounded-xl px-3 py-1.5 text-xs font-medium border border-zinc-700 bg-white/5 text-white hover:bg-white/10`
3336
+ }, "Edit"))))), /* @__PURE__ */ react.default.createElement("div", {
3337
+ id: "order-notes",
3338
+ className: `rounded-2xl border p-4 border-zinc-700 bg-[#101117]`
3339
+ }, /* @__PURE__ */ react.default.createElement("div", { className: `mb-3 text-xs uppercase tracking-[0.12em] text-zinc-500` }, "Order notes"), detailWithNoteOverrides.noteGroups.order.length === 0 ? /* @__PURE__ */ react.default.createElement("div", { className: `text-sm text-zinc-400` }, "No order notes.") : detailWithNoteOverrides.noteGroups.order.map((note) => /* @__PURE__ */ react.default.createElement("div", {
3340
+ key: note.id,
3341
+ className: `mb-2 rounded-xl px-3 py-3 last:mb-0 bg-[#151822]`
3342
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start justify-between gap-3" }, /* @__PURE__ */ react.default.createElement("div", { className: `min-w-0 flex-1 text-sm text-zinc-300` }, note.text), /* @__PURE__ */ react.default.createElement("button", {
3343
+ onClick: () => setNoteEditor({
3344
+ id: note.id,
3345
+ text: note.text,
3346
+ title: "Edit order note"
3347
+ }),
3348
+ className: `shrink-0 rounded-xl px-3 py-1.5 text-xs font-medium border border-zinc-700 bg-white/5 text-white hover:bg-white/10`
3349
+ }, "Edit"))))), /* @__PURE__ */ react.default.createElement("div", {
3350
+ id: "item-notes",
3351
+ className: `rounded-2xl border p-4 border-zinc-700 bg-[#101117]`
3352
+ }, /* @__PURE__ */ react.default.createElement("div", { className: `mb-3 text-xs uppercase tracking-[0.12em] text-zinc-500` }, "Item notes"), detailWithNoteOverrides.noteGroups.item.length === 0 ? /* @__PURE__ */ react.default.createElement("div", { className: `text-sm text-zinc-400` }, "No item notes.") : detailWithNoteOverrides.noteGroups.item.map((note) => /* @__PURE__ */ react.default.createElement("div", {
3353
+ key: note.id,
3354
+ onClick: () => setDetailTab("items"),
3355
+ className: `mb-2 cursor-pointer rounded-xl px-3 py-3 last:mb-0 bg-[#151822] hover:bg-[#1b2030]`
3356
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start justify-between gap-3" }, /* @__PURE__ */ react.default.createElement("div", { className: "min-w-0 flex-1" }, /* @__PURE__ */ react.default.createElement("div", { className: `flex items-center justify-between gap-3 text-sm font-medium text-white` }, /* @__PURE__ */ react.default.createElement("span", null, note.label), /* @__PURE__ */ react.default.createElement("span", null, note.qtyLabel || "×1")), /* @__PURE__ */ react.default.createElement("div", { className: `mt-2 text-sm text-zinc-300` }, note.text)), /* @__PURE__ */ react.default.createElement("button", {
3357
+ onClick: (e) => {
3358
+ e.stopPropagation();
3359
+ setNoteEditor({
3360
+ id: note.id,
3361
+ text: note.text,
3362
+ title: `Edit ${note.label} note`
3363
+ });
3364
+ },
3365
+ className: `shrink-0 rounded-xl px-3 py-1.5 text-xs font-medium border border-zinc-700 bg-white/5 text-white hover:bg-white/10`
3366
+ }, "Edit")))))) : /* @__PURE__ */ react.default.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ react.default.createElement("div", { className: "flex flex-wrap items-center justify-between gap-2" }, /* @__PURE__ */ react.default.createElement("label", { className: `inline-flex items-center gap-2 rounded-2xl px-3 py-2 text-sm border border-zinc-700 bg-white/5 text-zinc-200` }, /* @__PURE__ */ react.default.createElement("input", {
3367
+ type: "checkbox",
3368
+ checked: (detail.files[filesSubtab] || []).length > 0 && selectedFileIds.length === (detail.files[filesSubtab] || []).length,
3369
+ onChange: (e) => setSelectedFileIds(e.target.checked ? (detail.files[filesSubtab] || []).map((file) => file.id) : [])
3370
+ }), /* @__PURE__ */ react.default.createElement("span", null, "Select all")), /* @__PURE__ */ react.default.createElement("div", { className: "flex flex-wrap items-center gap-2" }, /* @__PURE__ */ react.default.createElement("button", { className: `rounded-2xl px-3 py-2 text-sm font-medium border border-zinc-700 bg-white/5 text-zinc-200` }, "Send"), /* @__PURE__ */ react.default.createElement("button", { className: `rounded-2xl px-3 py-2 text-sm font-medium border border-zinc-700 bg-white/5 text-zinc-200` }, "Print"), /* @__PURE__ */ react.default.createElement("button", { className: `rounded-2xl px-3 py-2 text-sm font-medium border border-zinc-700 bg-white/5 text-zinc-200` }, "Download"))), (detail.files[filesSubtab] || []).length === 0 ? /* @__PURE__ */ react.default.createElement("div", { className: `rounded-2xl p-4 text-sm bg-[#101117] text-zinc-400` }, "No files in this section.") : (detail.files[filesSubtab] || []).map((file) => /* @__PURE__ */ react.default.createElement("button", {
3371
+ key: file.id,
3372
+ onClick: () => setFilePreviewItem(file),
3373
+ className: `block w-full rounded-2xl p-4 text-left bg-[#101117] hover:bg-[#151822]`
3374
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start justify-between gap-3" }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start gap-3" }, /* @__PURE__ */ react.default.createElement("input", {
3375
+ type: "checkbox",
3376
+ checked: selectedFileIds.includes(file.id),
3377
+ onChange: (e) => {
3378
+ e.stopPropagation();
3379
+ setSelectedFileIds((prev) => e.target.checked ? [...prev, file.id] : prev.filter((id) => id !== file.id));
3380
+ },
3381
+ onClick: (e) => e.stopPropagation(),
3382
+ className: "mt-1"
3383
+ }), /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("div", { className: `font-semibold text-white` }, file.name), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-sm text-zinc-400` }, file.type, " ·", " ", file.time || "--"))), /* @__PURE__ */ react.default.createElement("div", { className: `text-sm text-violet-200` }, "Open")))), filePreviewItem && /* @__PURE__ */ react.default.createElement("div", { className: "fixed inset-0 z-[88] flex items-center justify-center bg-black/45 p-4 backdrop-blur-sm" }, /* @__PURE__ */ react.default.createElement("div", { className: `w-full max-w-[520px] rounded-3xl border p-5 shadow-2xl border-zinc-700 bg-[#121217]` }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start justify-between gap-3" }, /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("div", { className: `text-lg font-semibold text-white` }, filePreviewItem.name), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-sm text-zinc-400` }, filePreviewItem.type, " ·", " ", filePreviewItem.time || "--")), /* @__PURE__ */ react.default.createElement("button", {
3384
+ onClick: () => setFilePreviewItem(null),
3385
+ className: `rounded-xl p-2 border border-zinc-700 text-zinc-300 hover:bg-zinc-800`
3386
+ }, /* @__PURE__ */ react.default.createElement(lucide_react.X, { size: 16 }))), /* @__PURE__ */ react.default.createElement("div", { className: `mt-4 rounded-2xl border p-6 text-center text-sm border-zinc-700 bg-[#101117] text-zinc-400` }, "File preview window"), /* @__PURE__ */ react.default.createElement("div", { className: "mt-4 grid grid-cols-3 gap-3" }, /* @__PURE__ */ react.default.createElement("button", { className: `rounded-2xl px-4 py-3 text-sm font-medium border border-zinc-700 bg-white/5 text-zinc-200` }, "Send"), /* @__PURE__ */ react.default.createElement("button", { className: `rounded-2xl px-4 py-3 text-sm font-medium border border-zinc-700 bg-white/5 text-zinc-200` }, "Print"), /* @__PURE__ */ react.default.createElement("button", { className: `rounded-2xl px-4 py-3 text-sm font-medium border border-zinc-700 bg-white/5 text-zinc-200` }, "Download")))))), detailTab === "history" && /* @__PURE__ */ react.default.createElement("div", { className: `rounded-3xl border p-4 border-zinc-800 bg-[#151822]` }, /* @__PURE__ */ react.default.createElement("div", { className: "space-y-4" }, detail.history.map((row, index) => {
3387
+ const stamp = formatTimelineStamp(row.time);
3388
+ return /* @__PURE__ */ react.default.createElement("div", {
3389
+ key: row.id,
3390
+ className: "grid grid-cols-[92px_20px_1fr] gap-3 items-start"
3391
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "pt-1 text-right" }, /* @__PURE__ */ react.default.createElement("div", { className: `text-[11px] font-semibold text-violet-300` }, stamp.time), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-[11px] text-zinc-500` }, stamp.date)), /* @__PURE__ */ react.default.createElement("div", { className: "relative flex justify-center pt-1" }, index !== detail.history.length - 1 && /* @__PURE__ */ react.default.createElement("div", { className: `absolute top-5 bottom-[-22px] left-1/2 w-px -translate-x-1/2 bg-zinc-700` }), /* @__PURE__ */ react.default.createElement("div", { className: `relative z-10 h-3.5 w-3.5 rounded-full bg-violet-400 ring-4 ring-[#151822]` })), /* @__PURE__ */ react.default.createElement("div", { className: `rounded-2xl border p-4 border-zinc-700 bg-[#101117]` }, /* @__PURE__ */ react.default.createElement("div", { className: `font-semibold text-white` }, row.actor), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-sm text-zinc-300` }, row.text)));
3392
+ })))), /* @__PURE__ */ react.default.createElement("div", { className: `shrink-0 border-t px-4 py-3 backdrop-blur-md border-zinc-800 bg-[rgba(15,18,27,0.96)]` }, /* @__PURE__ */ react.default.createElement("div", { className: "mb-3 grid grid-cols-[4fr_2fr_1fr] gap-3" }, /* @__PURE__ */ react.default.createElement("button", {
3393
+ onClick: () => setDetailTab("guest"),
3394
+ className: `rounded-2xl px-4 py-3 text-left text-sm font-semibold border border-violet-500/35 bg-violet-600/15 text-white hover:bg-violet-600/25`
3395
+ }, "Check-in"), /* @__PURE__ */ react.default.createElement("button", { className: `rounded-2xl px-4 py-3 text-left text-sm font-semibold border border-zinc-700 bg-white/5 text-white hover:bg-white/10` }, "Print"), /* @__PURE__ */ react.default.createElement("button", {
3396
+ onClick: () => setShowActionsOverlay(true),
3397
+ className: `rounded-2xl px-4 py-3 text-center text-sm font-semibold border border-zinc-700 bg-white/5 text-white hover:bg-white/10`
3398
+ }, "More")), ![
3399
+ "guest",
3400
+ "files",
3401
+ "history"
3402
+ ].includes(detailTab) && /* @__PURE__ */ react.default.createElement("div", { className: `rounded-3xl border p-4 border-violet-500/30 bg-[#101117] shadow-[0_0_0_1px_rgba(139,92,246,0.08)]` }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start justify-between gap-4" }, /* @__PURE__ */ react.default.createElement("div", { className: "min-w-0" }, /* @__PURE__ */ react.default.createElement("div", { className: `inline-flex rounded-full px-3 py-1 text-sm font-semibold ${paymentTagClass(getPaymentDisplay(detail), isLight)}` }, getPaymentDisplay(detail)), /* @__PURE__ */ react.default.createElement("div", { className: `mt-3 text-xs uppercase tracking-[0.16em] text-zinc-500` }, "Total"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-sm text-zinc-400` }, ((_detail$itemSummary3 = detail.itemSummary) === null || _detail$itemSummary3 === void 0 ? void 0 : _detail$itemSummary3.itemCount) || 0, " items")), /* @__PURE__ */ react.default.createElement("div", { className: "text-right" }, /* @__PURE__ */ react.default.createElement("div", { className: `text-[46px] font-semibold leading-none text-violet-200` }, detail.paymentSummary.currencySymbol, detail.paymentSummary.totalAmount.toFixed(2)))))))));
3403
+ })()))), /* @__PURE__ */ react.default.createElement(AnimatePresence, null, moveConfirm && (() => {
3404
+ var _detail$customer5, _detail$customer6, _detail$customer7, _courts$find, _courts$find2, _moveDraft$targetHour;
3405
+ const detail = getBookingDetailData(moveConfirm.item, courts);
3406
+ const currentCustomer = selectedCustomer || {
3407
+ name: ((_detail$customer5 = detail.customer) === null || _detail$customer5 === void 0 ? void 0 : _detail$customer5.name) || detail.headerSummary.customerName,
3408
+ phone: ((_detail$customer6 = detail.customer) === null || _detail$customer6 === void 0 ? void 0 : _detail$customer6.phone) || "",
3409
+ email: ((_detail$customer7 = detail.customer) === null || _detail$customer7 === void 0 ? void 0 : _detail$customer7.email) || ""
3410
+ };
3411
+ const originalCourtName = ((_courts$find = courts.find((c) => c.id === moveConfirm.item.courtId)) === null || _courts$find === void 0 ? void 0 : _courts$find.name) || detail.headerSummary.resourceLabel || "Court";
3412
+ const nextCourtName = ((_courts$find2 = courts.find((c) => c.id === ((moveDraft === null || moveDraft === void 0 ? void 0 : moveDraft.targetCourtId) || moveConfirm.targetCourtId))) === null || _courts$find2 === void 0 ? void 0 : _courts$find2.name) || "Court";
3413
+ const originalDate = moveConfirm.item.date;
3414
+ const originalStart = formatHourLabel(moveConfirm.item.startHour);
3415
+ const originalEnd = formatHourLabel(moveConfirm.item.endHour);
3416
+ const nextDate = (moveDraft === null || moveDraft === void 0 ? void 0 : moveDraft.targetDate) || moveConfirm.targetDate;
3417
+ const nextStartHour = (_moveDraft$targetHour = moveDraft === null || moveDraft === void 0 ? void 0 : moveDraft.targetHour) !== null && _moveDraft$targetHour !== void 0 ? _moveDraft$targetHour : moveConfirm.targetHour;
3418
+ const duration = moveConfirm.item.endHour - moveConfirm.item.startHour;
3419
+ const nextEndHour = nextStartHour + duration;
3420
+ const changed = originalDate !== nextDate || moveConfirm.item.courtId !== ((moveDraft === null || moveDraft === void 0 ? void 0 : moveDraft.targetCourtId) || moveConfirm.targetCourtId) || moveConfirm.item.startHour !== nextStartHour;
3421
+ const isDragScenario = moveConfirm.item.date !== moveConfirm.targetDate || moveConfirm.item.startHour !== moveConfirm.targetHour || moveConfirm.item.courtId !== moveConfirm.targetCourtId;
3422
+ return /* @__PURE__ */ react.default.createElement(motion.div, {
3423
+ initial: { opacity: 0 },
3424
+ animate: { opacity: 1 },
3425
+ exit: { opacity: 0 },
3426
+ className: "fixed inset-0 z-[72] bg-black/45 backdrop-blur-sm flex items-center justify-center p-4"
3427
+ }, /* @__PURE__ */ react.default.createElement(motion.div, {
3428
+ ref: moveConfirmRef,
3429
+ initial: {
3430
+ scale: .96,
3431
+ y: 8
3432
+ },
3433
+ animate: {
3434
+ scale: 1,
3435
+ y: 0
3436
+ },
3437
+ exit: {
3438
+ scale: .96,
3439
+ y: 8
3440
+ },
3441
+ className: `w-full max-w-[980px] rounded-3xl border p-6 shadow-2xl border-zinc-700 bg-[#121217]`
3442
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "text-[22px] font-semibold" }, "Booking information"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-2 text-sm text-zinc-400` }, "Update customer, court, date and time for this booking."), /* @__PURE__ */ react.default.createElement("div", { className: "mt-5 space-y-4" }, /* @__PURE__ */ react.default.createElement("div", { className: `rounded-3xl border p-5 border-zinc-700 bg-[#171820]` }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start justify-between gap-4" }, /* @__PURE__ */ react.default.createElement("div", { className: "min-w-0 flex-1" }, /* @__PURE__ */ react.default.createElement("div", { className: `text-xs uppercase tracking-[0.14em] text-zinc-500` }, "Customer"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-3 text-[20px] font-semibold text-white` }, currentCustomer.name), /* @__PURE__ */ react.default.createElement("div", { className: `mt-2 text-sm text-zinc-400` }, currentCustomer.phone || "No phone"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-sm text-zinc-400` }, currentCustomer.email || "No email")), /* @__PURE__ */ react.default.createElement("button", {
3443
+ onClick: () => setCustomerPickerOpen(true),
3444
+ className: `shrink-0 rounded-2xl px-4 py-2.5 text-sm font-medium border border-zinc-700 bg-white/5 text-white hover:bg-white/10`
3445
+ }, "Change"))), /* @__PURE__ */ react.default.createElement("div", { className: "grid gap-4 md:grid-cols-2" }, /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("label", { className: `mb-2 block text-sm text-zinc-400` }, "Court"), /* @__PURE__ */ react.default.createElement("select", {
3446
+ value: (moveDraft === null || moveDraft === void 0 ? void 0 : moveDraft.targetCourtId) || moveConfirm.targetCourtId,
3447
+ onChange: (e) => setMoveDraft((prev) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev || {}), {}, { targetCourtId: e.target.value })),
3448
+ className: `w-full rounded-2xl px-4 py-4 outline-none border border-zinc-700 bg-[#171820] text-white`
3449
+ }, visibleCourts.map((court) => /* @__PURE__ */ react.default.createElement("option", {
3450
+ key: court.id,
3451
+ value: court.id
3452
+ }, court.name)))), /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("label", { className: `mb-2 block text-sm text-zinc-400` }, "New date"), /* @__PURE__ */ react.default.createElement("input", {
3453
+ type: "date",
3454
+ value: (moveDraft === null || moveDraft === void 0 ? void 0 : moveDraft.targetDate) || moveConfirm.targetDate,
3455
+ onChange: (e) => setMoveDraft((prev) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev || {}), {}, { targetDate: e.target.value })),
3456
+ className: `w-full rounded-2xl px-4 py-4 outline-none border border-zinc-700 bg-[#171820] text-white`
3457
+ }))), /* @__PURE__ */ react.default.createElement("div", { className: "grid gap-4 md:grid-cols-2" }, /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("label", { className: `mb-2 block text-sm text-zinc-400` }, "New start time"), /* @__PURE__ */ react.default.createElement("select", {
3458
+ value: nextStartHour,
3459
+ onChange: (e) => setMoveDraft((prev) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev || {}), {}, { targetHour: Number(e.target.value) })),
3460
+ className: `w-full rounded-2xl px-4 py-4 outline-none border border-zinc-700 bg-[#171820] text-white`
3461
+ }, hourSlots.filter(isBusinessHour).map((hour) => {
3462
+ const targetCourtId = (moveDraft === null || moveDraft === void 0 ? void 0 : moveDraft.targetCourtId) || moveConfirm.targetCourtId;
3463
+ const targetDate = (moveDraft === null || moveDraft === void 0 ? void 0 : moveDraft.targetDate) || moveConfirm.targetDate;
3464
+ const disabled = hour + duration > endTimelineExclusive || hasConflict(bookings, targetCourtId, targetDate, hour, hour + duration, moveConfirm.item.id);
3465
+ return /* @__PURE__ */ react.default.createElement("option", {
3466
+ key: hour,
3467
+ value: hour,
3468
+ disabled
3469
+ }, disabled ? `⛔ ${formatHourLabel(hour)}` : formatHourLabel(hour));
3470
+ }))), /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("label", { className: `mb-2 block text-sm text-zinc-400` }, "New end time"), /* @__PURE__ */ react.default.createElement("select", {
3471
+ value: nextEndHour,
3472
+ onChange: (e) => {
3473
+ const nextEnd = Number(e.target.value);
3474
+ setMoveDraft((prev) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev || {}), {}, { targetHour: nextEnd - duration }));
3475
+ },
3476
+ className: `w-full rounded-2xl px-4 py-4 outline-none border border-zinc-700 bg-[#171820] text-white`
3477
+ }, hourSlots.filter(isBusinessHour).map((hour) => {
3478
+ const startHour = hour - duration;
3479
+ const targetCourtId = (moveDraft === null || moveDraft === void 0 ? void 0 : moveDraft.targetCourtId) || moveConfirm.targetCourtId;
3480
+ const targetDate = (moveDraft === null || moveDraft === void 0 ? void 0 : moveDraft.targetDate) || moveConfirm.targetDate;
3481
+ const disabled = startHour < firstTimelineHour || hasConflict(bookings, targetCourtId, targetDate, startHour, hour, moveConfirm.item.id);
3482
+ return /* @__PURE__ */ react.default.createElement("option", {
3483
+ key: `end-${hour}`,
3484
+ value: hour,
3485
+ disabled
3486
+ }, disabled ? `⛔ ${formatHourLabel(hour)}` : formatHourLabel(hour));
3487
+ })))), changed && /* @__PURE__ */ react.default.createElement("div", { className: `rounded-3xl border p-5 border-zinc-700 bg-[#171820]` }, /* @__PURE__ */ react.default.createElement("div", { className: `text-xs uppercase tracking-[0.14em] text-zinc-500` }, "Previous booking info"), /* @__PURE__ */ react.default.createElement("div", { className: "mt-3 grid gap-3 md:grid-cols-2" }, /* @__PURE__ */ react.default.createElement("div", { className: `rounded-2xl p-4 bg-[#101117]` }, /* @__PURE__ */ react.default.createElement("div", { className: `text-xs text-zinc-500` }, "Original"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-2 text-sm text-zinc-300` }, originalCourtName), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-sm text-zinc-300` }, originalDate), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-sm text-zinc-300` }, originalStart, " - ", originalEnd)), /* @__PURE__ */ react.default.createElement("div", { className: `rounded-2xl p-4 bg-violet-600/10 border border-violet-500/30` }, /* @__PURE__ */ react.default.createElement("div", { className: `text-xs text-violet-300` }, isDragScenario ? "Drop target" : "Updated"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-2 text-sm text-white` }, nextCourtName), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-sm text-white` }, nextDate), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-sm text-white` }, formatHourLabel(nextStartHour), " -", " ", formatHourLabel(nextEndHour)))))), hasConflict(bookings, (moveDraft === null || moveDraft === void 0 ? void 0 : moveDraft.targetCourtId) || moveConfirm.targetCourtId, (moveDraft === null || moveDraft === void 0 ? void 0 : moveDraft.targetDate) || moveConfirm.targetDate, nextStartHour, nextEndHour, moveConfirm.item.id) && /* @__PURE__ */ react.default.createElement("div", { className: "mt-4 rounded-2xl border border-red-500/30 bg-red-500/10 px-4 py-3 text-sm text-red-200" }, "The selected date, court, or time range is unavailable. Please choose an available option."), /* @__PURE__ */ react.default.createElement("div", { className: "mt-6 flex justify-end gap-3" }, /* @__PURE__ */ react.default.createElement("button", {
3488
+ onClick: () => {
3489
+ setMoveConfirm(null);
3490
+ setMoveDraft(null);
3491
+ },
3492
+ className: `rounded-2xl px-5 py-3 border border-zinc-700 text-zinc-300 hover:bg-zinc-800`
3493
+ }, "Cancel"), /* @__PURE__ */ react.default.createElement("button", {
3494
+ onClick: confirmMove,
3495
+ disabled: hasConflict(bookings, (moveDraft === null || moveDraft === void 0 ? void 0 : moveDraft.targetCourtId) || moveConfirm.targetCourtId, (moveDraft === null || moveDraft === void 0 ? void 0 : moveDraft.targetDate) || moveConfirm.targetDate, nextStartHour, nextEndHour, moveConfirm.item.id),
3496
+ className: "rounded-2xl bg-violet-600 px-6 py-3 font-semibold text-white hover:bg-violet-500 disabled:cursor-not-allowed disabled:bg-zinc-700 disabled:text-zinc-400"
3497
+ }, "Confirm"))));
3498
+ })()), /* @__PURE__ */ react.default.createElement(AnimatePresence, null, conflictPicker && /* @__PURE__ */ react.default.createElement(motion.div, {
3499
+ initial: { opacity: 0 },
3500
+ animate: { opacity: 1 },
3501
+ exit: { opacity: 0 },
3502
+ className: "fixed inset-0 z-[73] bg-black/50 backdrop-blur-sm flex items-center justify-center p-4"
3503
+ }, /* @__PURE__ */ react.default.createElement(motion.div, {
3504
+ ref: conflictPickerRef,
3505
+ initial: {
3506
+ scale: .96,
3507
+ y: 8
3508
+ },
3509
+ animate: {
3510
+ scale: 1,
3511
+ y: 0
3512
+ },
3513
+ exit: {
3514
+ scale: .96,
3515
+ y: 8
3516
+ },
3517
+ className: `w-full max-w-[760px] rounded-3xl border p-5 shadow-2xl border-zinc-700 bg-[#121217]`
3518
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "text-xl font-semibold" }, "Target time is unavailable"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-2 text-sm text-zinc-400` }, conflictPicker.targetDate, " The target court is unavailable. Please choose another available slot on the same day."), /* @__PURE__ */ react.default.createElement("div", { className: "mt-4 grid gap-3 md:grid-cols-2" }, visibleCourts.map((court) => {
3519
+ dayOccupancy(court.id, conflictPicker.targetDate, bookings, hourSlots);
3520
+ return /* @__PURE__ */ react.default.createElement("div", {
3521
+ key: court.id,
3522
+ className: `rounded-2xl border p-3 border-zinc-700 bg-[#171820]`
3523
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "mb-2 font-medium" }, court.name), /* @__PURE__ */ react.default.createElement("div", { className: "grid grid-cols-4 gap-2" }, hourSlots.filter(isBusinessHour).map((hour) => {
3524
+ const duration = conflictPicker.item.endHour - conflictPicker.item.startHour;
3525
+ const canUse = hour + duration <= endTimelineExclusive && !hasConflict(bookings, court.id, conflictPicker.targetDate, hour, hour + duration, conflictPicker.item.id);
3526
+ return /* @__PURE__ */ react.default.createElement("button", {
3527
+ key: hour,
3528
+ disabled: !canUse,
3529
+ onClick: () => applyConflictMove(court.id, hour),
3530
+ className: `rounded-lg px-2 py-2 text-xs ${canUse ? "bg-violet-700/80 text-white hover:bg-violet-600" : "bg-zinc-800 text-zinc-600 cursor-not-allowed"}`
3531
+ }, formatHourLabel(hour));
3532
+ })));
3533
+ })), /* @__PURE__ */ react.default.createElement("div", { className: "mt-5 flex justify-end" }, /* @__PURE__ */ react.default.createElement("button", {
3534
+ onClick: () => setConflictPicker(null),
3535
+ className: `rounded-xl px-4 py-2 border border-zinc-700 text-zinc-300 hover:bg-zinc-800`
3536
+ }, "Close"))))), /* @__PURE__ */ react.default.createElement(AnimatePresence, null, blockConflict && /* @__PURE__ */ react.default.createElement(motion.div, {
3537
+ initial: { opacity: 0 },
3538
+ animate: { opacity: 1 },
3539
+ exit: { opacity: 0 },
3540
+ className: "fixed inset-0 z-[74] bg-black/50 backdrop-blur-sm flex items-center justify-center p-4"
3541
+ }, /* @__PURE__ */ react.default.createElement(motion.div, {
3542
+ ref: blockConflictRef,
3543
+ initial: {
3544
+ scale: .96,
3545
+ y: 8
3546
+ },
3547
+ animate: {
3548
+ scale: 1,
3549
+ y: 0
3550
+ },
3551
+ exit: {
3552
+ scale: .96,
3553
+ y: 8
3554
+ },
3555
+ className: `w-full max-w-[620px] rounded-3xl border p-5 shadow-2xl border-zinc-700 bg-[#121217]`
3556
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "text-xl font-semibold" }, "Bookings exist inside block range"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-2 text-sm text-zinc-400` }, "There are already bookings inside the selected block range. Do you want to clear their assigned court and leave them unassigned for later reassignment?"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-4 max-h-[240px] overflow-auto space-y-2 rounded-2xl border p-3 border-zinc-700 bg-[#171820]` }, blockConflict.conflicts.map((item) => {
3557
+ var _courts$find3;
3558
+ return /* @__PURE__ */ react.default.createElement("div", {
3559
+ key: item.id,
3560
+ className: `rounded-xl px-3 py-3 text-sm bg-zinc-900/80 text-zinc-200`
3561
+ }, item.name, " · ", item.date, " ·", " ", formatHourLabel(item.startHour), "-", formatHourLabel(item.endHour), " ·", " ", ((_courts$find3 = courts.find((c) => c.id === item.courtId)) === null || _courts$find3 === void 0 ? void 0 : _courts$find3.name) || "Unassigned");
3562
+ })), /* @__PURE__ */ react.default.createElement("div", { className: "mt-5 flex justify-end gap-3" }, /* @__PURE__ */ react.default.createElement("button", {
3563
+ onClick: () => setBlockConflict(null),
3564
+ className: `rounded-xl px-4 py-2 border border-zinc-700 text-zinc-300 hover:bg-zinc-800`
3565
+ }, "Cancel"), /* @__PURE__ */ react.default.createElement("button", {
3566
+ onClick: confirmBlockWithUnsetCourts,
3567
+ className: "btn-brand rounded-xl px-5 py-2.5 font-semibold text-white"
3568
+ }, "Clear court assignment and continue"))))), /* @__PURE__ */ react.default.createElement(AnimatePresence, null, checkinModal && /* @__PURE__ */ react.default.createElement(motion.div, {
3569
+ initial: { opacity: 0 },
3570
+ animate: { opacity: 1 },
3571
+ exit: { opacity: 0 },
3572
+ className: "fixed inset-0 z-[75] bg-black/50 backdrop-blur-sm flex items-center justify-center p-4"
3573
+ }, /* @__PURE__ */ react.default.createElement(motion.div, {
3574
+ ref: checkinModalRef,
3575
+ initial: {
3576
+ scale: .96,
3577
+ y: 8
3578
+ },
3579
+ animate: {
3580
+ scale: 1,
3581
+ y: 0
3582
+ },
3583
+ exit: {
3584
+ scale: .96,
3585
+ y: 8
3586
+ },
3587
+ className: `w-full max-w-[620px] rounded-3xl border p-5 shadow-2xl border-zinc-700 bg-[#121217]`
3588
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start justify-between gap-4" }, /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("div", { className: "text-xl font-semibold" }, getDisplayStatusTag(checkinModal, checkinModal.date) === "no_show" ? "Backfill check-in" : "Check-in"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-sm text-zinc-400` }, checkinModal.name, " ·", " ", ((_courts$find4 = courts.find((c) => c.id === checkinModal.courtId)) === null || _courts$find4 === void 0 ? void 0 : _courts$find4.name) || "Unassigned")), /* @__PURE__ */ react.default.createElement("button", {
3589
+ onClick: () => setCheckinModal(null),
3590
+ className: `rounded-xl px-3 py-2 border border-zinc-700 text-zinc-300 hover:bg-zinc-800`
3591
+ }, "Close")), /* @__PURE__ */ react.default.createElement("div", { className: "mt-4 space-y-3 text-sm" }, /* @__PURE__ */ react.default.createElement("div", { className: `rounded-xl px-4 py-3 bg-[#171820]` }, /* @__PURE__ */ react.default.createElement("span", { className: "text-zinc-400" }, "Scheduled time:", " "), formatHourLabel(checkinModal.startHour), " -", " ", formatHourLabel(checkinModal.endHour)), /* @__PURE__ */ react.default.createElement("div", { className: `rounded-xl px-4 py-3 bg-[#171820]` }, /* @__PURE__ */ react.default.createElement("span", { className: "text-zinc-400" }, "Current time:", " "), currentTimeLabel())), /* @__PURE__ */ react.default.createElement("div", { className: "mt-5 grid gap-3 md:grid-cols-2" }, /* @__PURE__ */ react.default.createElement("button", {
3592
+ onClick: () => {
3593
+ if (!allowPersist("checkin")) return;
3594
+ setBookings((prev) => prev.map((b) => b.id === checkinModal.id ? require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, b), {}, { statusTag: "checked_in" }) : b));
3595
+ setCheckinModal(null);
3596
+ setDetailItem(null);
3597
+ },
3598
+ className: `rounded-2xl border p-4 text-left border-zinc-700 bg-[#171820] hover:border-emerald-400 hover:bg-emerald-500/10`
3599
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "font-semibold" }, getDisplayStatusTag(checkinModal, checkinModal.date) === "no_show" ? "Backfill check-in" : "Check-in as scheduled"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-sm text-zinc-400` }, formatHourLabel(checkinModal.startHour), " -", " ", formatHourLabel(checkinModal.endHour))), /* @__PURE__ */ react.default.createElement("div", { className: `rounded-2xl border p-4 border-zinc-700 bg-[#171820]` }, /* @__PURE__ */ react.default.createElement("div", { className: "font-semibold" }, "Reschedule check-in"), /* @__PURE__ */ react.default.createElement("div", { className: "mt-3 grid gap-3 sm:grid-cols-2" }, /* @__PURE__ */ react.default.createElement("select", {
3600
+ value: (_checkinDraft$startHo = checkinDraft === null || checkinDraft === void 0 ? void 0 : checkinDraft.startHour) !== null && _checkinDraft$startHo !== void 0 ? _checkinDraft$startHo : checkinModal.startHour,
3601
+ onChange: (e) => {
3602
+ var _checkinDraft$endHour, _checkinDraft$startHo2;
3603
+ const nextStart = Number(e.target.value);
3604
+ const duration = ((_checkinDraft$endHour = checkinDraft === null || checkinDraft === void 0 ? void 0 : checkinDraft.endHour) !== null && _checkinDraft$endHour !== void 0 ? _checkinDraft$endHour : checkinModal.endHour) - ((_checkinDraft$startHo2 = checkinDraft === null || checkinDraft === void 0 ? void 0 : checkinDraft.startHour) !== null && _checkinDraft$startHo2 !== void 0 ? _checkinDraft$startHo2 : checkinModal.startHour);
3605
+ const nextEnd = Math.min(endTimelineExclusive, nextStart + duration);
3606
+ setCheckinDraft((prev) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev || {}), {}, {
3607
+ startHour: nextStart,
3608
+ endHour: nextEnd
3609
+ }));
3610
+ },
3611
+ className: `rounded-xl px-3 py-2 outline-none border border-zinc-700 bg-[#101117] text-white`
3612
+ }, timeOptions.filter((hour) => hour >= firstTimelineHour && hour < endTimelineExclusive).map((hour) => /* @__PURE__ */ react.default.createElement("option", {
3613
+ key: hour,
3614
+ value: hour
3615
+ }, formatHourLabel(hour)))), /* @__PURE__ */ react.default.createElement("select", {
3616
+ value: (_checkinDraft$endHour2 = checkinDraft === null || checkinDraft === void 0 ? void 0 : checkinDraft.endHour) !== null && _checkinDraft$endHour2 !== void 0 ? _checkinDraft$endHour2 : checkinModal.endHour,
3617
+ onChange: (e) => setCheckinDraft((prev) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev || {}), {}, { endHour: Number(e.target.value) })),
3618
+ className: `rounded-xl px-3 py-2 outline-none border border-zinc-700 bg-[#101117] text-white`
3619
+ }, timeOptions.filter((hour) => {
3620
+ var _checkinDraft$startHo3;
3621
+ return hour > ((_checkinDraft$startHo3 = checkinDraft === null || checkinDraft === void 0 ? void 0 : checkinDraft.startHour) !== null && _checkinDraft$startHo3 !== void 0 ? _checkinDraft$startHo3 : checkinModal.startHour) && hour <= endTimelineExclusive;
3622
+ }).map((hour) => /* @__PURE__ */ react.default.createElement("option", {
3623
+ key: hour,
3624
+ value: hour
3625
+ }, formatHourLabel(hour))))), /* @__PURE__ */ react.default.createElement("div", { className: `mt-2 text-sm text-zinc-400` }, "Suggested time:", " ", formatHourLabel((_checkinDraft$startHo4 = checkinDraft === null || checkinDraft === void 0 ? void 0 : checkinDraft.startHour) !== null && _checkinDraft$startHo4 !== void 0 ? _checkinDraft$startHo4 : checkinModal.startHour), " ", "-", " ", formatHourLabel((_checkinDraft$endHour3 = checkinDraft === null || checkinDraft === void 0 ? void 0 : checkinDraft.endHour) !== null && _checkinDraft$endHour3 !== void 0 ? _checkinDraft$endHour3 : checkinModal.endHour)), /* @__PURE__ */ react.default.createElement("button", {
3626
+ onClick: () => {
3627
+ if (!allowPersist("checkinReschedule")) return;
3628
+ setBookings((prev) => prev.map((b) => {
3629
+ var _checkinDraft$startHo5, _checkinDraft$endHour4;
3630
+ return b.id === checkinModal.id ? require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, b), {}, {
3631
+ startHour: (_checkinDraft$startHo5 = checkinDraft === null || checkinDraft === void 0 ? void 0 : checkinDraft.startHour) !== null && _checkinDraft$startHo5 !== void 0 ? _checkinDraft$startHo5 : b.startHour,
3632
+ endHour: (_checkinDraft$endHour4 = checkinDraft === null || checkinDraft === void 0 ? void 0 : checkinDraft.endHour) !== null && _checkinDraft$endHour4 !== void 0 ? _checkinDraft$endHour4 : b.endHour,
3633
+ statusTag: "checked_in"
3634
+ }) : b;
3635
+ }));
3636
+ setCheckinModal(null);
3637
+ setDetailItem(null);
3638
+ },
3639
+ className: "mt-3 w-full btn-brand rounded-xl px-4 py-2.5 text-sm font-semibold text-white"
3640
+ }, "Confirm reschedule and check-in")))))), /* @__PURE__ */ react.default.createElement(AnimatePresence, null, mergeOrderModal && /* @__PURE__ */ react.default.createElement(motion.div, {
3641
+ initial: { opacity: 0 },
3642
+ animate: { opacity: 1 },
3643
+ exit: { opacity: 0 },
3644
+ className: "fixed inset-0 z-[76] bg-black/50 backdrop-blur-sm flex items-center justify-center p-4"
3645
+ }, /* @__PURE__ */ react.default.createElement(motion.div, {
3646
+ ref: mergeOrderModalRef,
3647
+ initial: {
3648
+ scale: .96,
3649
+ y: 8
3650
+ },
3651
+ animate: {
3652
+ scale: 1,
3653
+ y: 0
3654
+ },
3655
+ exit: {
3656
+ scale: .96,
3657
+ y: 8
3658
+ },
3659
+ className: `w-full max-w-[640px] rounded-3xl border p-5 shadow-2xl border-zinc-700 bg-[#121217]`
3660
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start justify-between gap-4" }, /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("div", { className: "text-xl font-semibold" }, "Merge order"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-sm text-zinc-400` }, "Merge this booking into another booking / table.")), /* @__PURE__ */ react.default.createElement("button", {
3661
+ onClick: () => setMergeOrderModal(null),
3662
+ className: `rounded-xl px-3 py-2 border border-zinc-700 text-zinc-300 hover:bg-zinc-800`
3663
+ }, "Close")), /* @__PURE__ */ react.default.createElement("div", { className: `mt-4 rounded-2xl border p-4 border-zinc-700 bg-[#171820]` }, /* @__PURE__ */ react.default.createElement("div", { className: `text-sm text-zinc-400` }, "Current booking"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 font-semibold text-white` }, mergeOrderModal.item.name, " ·", " ", ((_courts$find5 = courts.find((c) => c.id === mergeOrderModal.item.courtId)) === null || _courts$find5 === void 0 ? void 0 : _courts$find5.name) || "Unassigned")), /* @__PURE__ */ react.default.createElement("div", { className: "mt-4" }, /* @__PURE__ */ react.default.createElement("label", { className: `mb-2 block text-sm text-zinc-400` }, "Merge into"), /* @__PURE__ */ react.default.createElement("select", {
3664
+ value: mergeOrderDraft.targetBookingId,
3665
+ onChange: (e) => setMergeOrderDraft((prev) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev), {}, { targetBookingId: e.target.value })),
3666
+ className: `w-full rounded-xl px-4 py-3 outline-none border border-zinc-700 bg-[#171820] text-white`
3667
+ }, mergeOrderModal.candidates.map((candidate) => {
3668
+ var _courts$find6;
3669
+ return /* @__PURE__ */ react.default.createElement("option", {
3670
+ key: candidate.id,
3671
+ value: candidate.id
3672
+ }, candidate.name, " ·", " ", ((_courts$find6 = courts.find((c) => c.id === candidate.courtId)) === null || _courts$find6 === void 0 ? void 0 : _courts$find6.name) || "Unassigned", " ", "· ", candidate.date, " ", formatHourLabel(candidate.startHour), "-", formatHourLabel(candidate.endHour));
3673
+ }))), /* @__PURE__ */ react.default.createElement("div", { className: `mt-4 rounded-2xl border p-4 border-zinc-700 bg-[#171820]` }, /* @__PURE__ */ react.default.createElement("div", { className: "font-semibold" }, "After merge"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-2 text-sm text-zinc-400` }, "Choose whether the current table should be cleared immediately, or kept until the target order is confirmed."), /* @__PURE__ */ react.default.createElement("label", { className: `mt-3 flex items-start gap-3 rounded-2xl border p-3 border-zinc-700 bg-[#101117]` }, /* @__PURE__ */ react.default.createElement("input", {
3674
+ type: "radio",
3675
+ name: "merge-order-mode",
3676
+ checked: !mergeOrderDraft.keepSourceOpen,
3677
+ onChange: () => setMergeOrderDraft((prev) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev), {}, { keepSourceOpen: false })),
3678
+ className: "mt-1"
3679
+ }), /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("div", { className: `font-medium text-white` }, "Merge and clear this table"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-sm text-zinc-400` }, "After merge, this booking is cleared and the current table / court is released."))), /* @__PURE__ */ react.default.createElement("label", { className: `mt-3 flex items-start gap-3 rounded-2xl border p-3 border-zinc-700 bg-[#101117]` }, /* @__PURE__ */ react.default.createElement("input", {
3680
+ type: "radio",
3681
+ name: "merge-order-mode",
3682
+ checked: mergeOrderDraft.keepSourceOpen,
3683
+ onChange: () => setMergeOrderDraft((prev) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev), {}, { keepSourceOpen: true })),
3684
+ className: "mt-1"
3685
+ }), /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("div", { className: `font-medium text-white` }, "Merge but keep this table for now"), /* @__PURE__ */ react.default.createElement("div", { className: `mt-1 text-sm text-zinc-400` }, "Keep the current table until the target booking / table is fully confirmed.")))), /* @__PURE__ */ react.default.createElement("div", { className: "mt-5 flex justify-end gap-3" }, /* @__PURE__ */ react.default.createElement("button", {
3686
+ onClick: () => setMergeOrderModal(null),
3687
+ className: `rounded-xl px-4 py-2 border border-zinc-700 text-zinc-300 hover:bg-zinc-800`
3688
+ }, "Cancel"), /* @__PURE__ */ react.default.createElement("button", { className: "btn-brand rounded-xl px-5 py-2.5 font-semibold text-white" }, "Confirm merge order")))), customerPickerOpen && /* @__PURE__ */ react.default.createElement(motion.div, {
3689
+ initial: { opacity: 0 },
3690
+ animate: { opacity: 1 },
3691
+ exit: { opacity: 0 },
3692
+ className: "fixed inset-0 z-[77] bg-black/50 backdrop-blur-sm flex items-center justify-center p-4"
3693
+ }, /* @__PURE__ */ react.default.createElement(motion.div, {
3694
+ ref: customerPickerRef,
3695
+ initial: {
3696
+ scale: .96,
3697
+ y: 8
3698
+ },
3699
+ animate: {
3700
+ scale: 1,
3701
+ y: 0
3702
+ },
3703
+ exit: {
3704
+ scale: .96,
3705
+ y: 8
3706
+ },
3707
+ className: `w-full max-w-[1120px] rounded-3xl border p-6 shadow-2xl border-zinc-700 bg-[#121217]`
3708
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "flex items-start justify-between gap-4" }, /* @__PURE__ */ react.default.createElement("div", { className: `text-2xl font-semibold text-white` }, "Select customer"), /* @__PURE__ */ react.default.createElement("button", {
3709
+ onClick: () => setCustomerPickerOpen(false),
3710
+ className: `rounded-xl p-2 border border-zinc-700 text-zinc-300 hover:bg-zinc-800`
3711
+ }, /* @__PURE__ */ react.default.createElement(lucide_react.X, { size: 18 }))), /* @__PURE__ */ react.default.createElement("div", { className: "mt-5 flex items-center gap-3" }, /* @__PURE__ */ react.default.createElement("button", { className: "btn-pill-active rounded-2xl px-5 py-3 text-base font-semibold" }, "New Client"), /* @__PURE__ */ react.default.createElement("div", { className: "ml-auto flex items-center gap-3 text-emerald-500" }, /* @__PURE__ */ react.default.createElement("div", { className: "h-9 w-9 rounded-full border border-current/20 flex items-center justify-center" }, "✓"), /* @__PURE__ */ react.default.createElement("div", { className: "h-9 w-9 rounded-full border border-current/20 flex items-center justify-center" }, "✓"), /* @__PURE__ */ react.default.createElement("div", { className: "h-9 w-9 rounded-full border border-current/20 flex items-center justify-center" }, "✓"))), /* @__PURE__ */ react.default.createElement("div", { className: "mt-4 flex items-center gap-3" }, /* @__PURE__ */ react.default.createElement("button", { className: `rounded-2xl p-4 border border-violet-500/35 bg-violet-600/20 text-white` }, /* @__PURE__ */ react.default.createElement(lucide_react.Eye, { size: 24 })), /* @__PURE__ */ react.default.createElement("div", { className: `flex flex-1 items-center gap-3 rounded-2xl border px-4 py-4 border-zinc-700 bg-[#171820]` }, /* @__PURE__ */ react.default.createElement(Search, {
3712
+ size: 28,
3713
+ className: "text-zinc-400"
3714
+ }), /* @__PURE__ */ react.default.createElement("input", {
3715
+ value: customerSearch,
3716
+ onChange: (e) => setCustomerSearch(e.target.value),
3717
+ placeholder: "WalletPass Code / Name / Mobile / Email",
3718
+ className: "w-full bg-transparent text-lg outline-none"
3719
+ })), /* @__PURE__ */ react.default.createElement("button", { className: "btn-pill-active rounded-2xl px-8 py-4 text-xl font-semibold" }, "Search")), /* @__PURE__ */ react.default.createElement("div", { className: `mt-5 overflow-hidden rounded-2xl border border-zinc-700` }, /* @__PURE__ */ react.default.createElement("div", { className: `grid grid-cols-[1.2fr_1.2fr_1.1fr_1.6fr_.8fr] px-6 py-4 text-sm font-semibold bg-[#171820] text-zinc-300` }, /* @__PURE__ */ react.default.createElement("div", null, "Name"), /* @__PURE__ */ react.default.createElement("div", null, "Registration Time"), /* @__PURE__ */ react.default.createElement("div", null, "Phone Number"), /* @__PURE__ */ react.default.createElement("div", null, "Email address"), /* @__PURE__ */ react.default.createElement("div", null, "Membership")), customerPickerMock.filter((row) => {
3720
+ const q = customerSearch.trim().toLowerCase();
3721
+ if (!q) return true;
3722
+ return [
3723
+ row.name,
3724
+ row.phone,
3725
+ row.email,
3726
+ row.membership
3727
+ ].join(" ").toLowerCase().includes(q);
3728
+ }).map((row) => /* @__PURE__ */ react.default.createElement("button", {
3729
+ key: row.id,
3730
+ onClick: () => {
3731
+ setSelectedCustomer(row);
3732
+ setCustomerPickerOpen(false);
3733
+ },
3734
+ className: `grid w-full grid-cols-[1.2fr_1.2fr_1.1fr_1.6fr_.8fr] items-center gap-4 border-t px-6 py-5 text-left border-zinc-700 bg-[#121217] text-white hover:bg-[#171820]`
3735
+ }, /* @__PURE__ */ react.default.createElement("div", { className: "text-[17px] font-semibold" }, row.name), /* @__PURE__ */ react.default.createElement("div", { className: "text-zinc-400" }, row.registeredAt), /* @__PURE__ */ react.default.createElement("div", { className: "text-zinc-300" }, row.phone), /* @__PURE__ */ react.default.createElement("div", { className: "text-zinc-300" }, row.email), /* @__PURE__ */ react.default.createElement("div", null, /* @__PURE__ */ react.default.createElement("span", { className: `rounded-full border px-3 py-1 text-sm border-amber-400/35 bg-amber-400/10 text-amber-300` }, row.membership))))))), noteEditor && /* @__PURE__ */ react.default.createElement(motion.div, {
3736
+ initial: { opacity: 0 },
3737
+ animate: { opacity: 1 },
3738
+ exit: { opacity: 0 },
3739
+ className: "fixed inset-0 z-[89] bg-black/45 backdrop-blur-sm flex items-center justify-center p-4"
3740
+ }, /* @__PURE__ */ react.default.createElement(motion.div, {
3741
+ ref: noteEditorRef,
3742
+ initial: {
3743
+ scale: .96,
3744
+ y: 8
3745
+ },
3746
+ animate: {
3747
+ scale: 1,
3748
+ y: 0
3749
+ },
3750
+ exit: {
3751
+ scale: .96,
3752
+ y: 8
3753
+ },
3754
+ className: `w-full max-w-[520px] rounded-3xl border p-5 shadow-2xl border-zinc-700 bg-[#121217]`
3755
+ }, /* @__PURE__ */ react.default.createElement("div", { className: `text-lg font-semibold text-white` }, noteEditor.title || "Edit note"), /* @__PURE__ */ react.default.createElement("textarea", {
3756
+ value: noteEditor.text,
3757
+ onChange: (e) => setNoteEditor((prev) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev), {}, { text: e.target.value })),
3758
+ className: `mt-4 min-h-[160px] w-full rounded-2xl px-4 py-3 outline-none border border-zinc-700 bg-[#171820] text-white`
3759
+ }), /* @__PURE__ */ react.default.createElement("div", { className: "mt-4 flex justify-end gap-3" }, /* @__PURE__ */ react.default.createElement("button", {
3760
+ onClick: () => setNoteEditor(null),
3761
+ className: `rounded-2xl px-4 py-2 text-sm font-medium border border-zinc-700 bg-white/5 text-white hover:bg-white/10`
3762
+ }, "Cancel"), /* @__PURE__ */ react.default.createElement("button", {
3763
+ onClick: () => {
3764
+ setNoteOverrides((prev) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev), {}, { [noteEditor.id]: noteEditor.text }));
3765
+ setDetailMode("drawer");
3766
+ setDetailTab("files");
3767
+ setFilesSubtab("notes");
3768
+ setCalendarShiftedForDrawer(true);
3769
+ setNoteEditor(null);
3770
+ },
3771
+ className: "rounded-2xl bg-violet-600 px-4 py-2 text-sm font-semibold text-white hover:bg-violet-500"
3772
+ }, "Save")))), quickActionLimitMessage && /* @__PURE__ */ react.default.createElement(motion.div, {
3773
+ initial: {
3774
+ opacity: 0,
3775
+ y: -10,
3776
+ scale: .98
3777
+ },
3778
+ animate: {
3779
+ opacity: 1,
3780
+ y: 0,
3781
+ scale: 1
3782
+ },
3783
+ exit: {
3784
+ opacity: 0,
3785
+ y: -10,
3786
+ scale: .98
3787
+ },
3788
+ className: "fixed left-1/2 top-6 z-[90] -translate-x-1/2 rounded-2xl border border-amber-400/35 bg-[#1a1510]/90 px-4 py-3 text-sm font-medium text-amber-200 shadow-2xl backdrop-blur-md"
3789
+ }, quickActionLimitMessage), transitioningToDay && /* @__PURE__ */ react.default.createElement(motion.div, {
3790
+ layoutId: `zoom-${transitioningToDay.source}`,
3791
+ className: "fixed inset-6 z-[60] rounded-[28px] border border-violet-400/20 bg-[#151220] pointer-events-none",
3792
+ initial: {
3793
+ opacity: .1,
3794
+ scale: 1
3795
+ },
3796
+ animate: {
3797
+ opacity: 0,
3798
+ scale: 1
3799
+ },
3800
+ exit: { opacity: 0 },
3801
+ transition: {
3802
+ duration: .18,
3803
+ ease: [
3804
+ .18,
3805
+ .9,
3806
+ .22,
3807
+ 1
3808
+ ]
3809
+ }
3810
+ })))));
3811
+ }
3812
+ //#endregion
3813
+ exports.default = BookingCalendarDemo;