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