@fluid-app/portal-sdk 0.1.523 → 0.1.525
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{ContactsScreen-DeXNeKhZ.cjs → ContactsScreen-C3ccWqAe.cjs} +41 -38
- package/dist/{ContactsScreen-DeXNeKhZ.cjs.map → ContactsScreen-C3ccWqAe.cjs.map} +1 -1
- package/dist/{ContactsScreen-C29wHxlb.mjs → ContactsScreen-C_UMnqhN.mjs} +2 -2
- package/dist/{ContactsScreen-xXR5SM7U.cjs → ContactsScreen-DEQAF0fC.cjs} +2 -2
- package/dist/{ContactsScreen-C5WtXbuk.mjs → ContactsScreen-DkChLGnB.mjs} +41 -38
- package/dist/{ContactsScreen-C5WtXbuk.mjs.map → ContactsScreen-DkChLGnB.mjs.map} +1 -1
- package/dist/{ContactsTranslationBridge-7hUvizHe.mjs → ContactsTranslationBridge-B4SlrRSR.mjs} +4 -3
- package/dist/{ContactsTranslationBridge-7hUvizHe.mjs.map → ContactsTranslationBridge-B4SlrRSR.mjs.map} +1 -1
- package/dist/{ContactsTranslationBridge-MTW9WS-j.cjs → ContactsTranslationBridge-C7Q9rpKH.cjs} +4 -3
- package/dist/{ContactsTranslationBridge-MTW9WS-j.cjs.map → ContactsTranslationBridge-C7Q9rpKH.cjs.map} +1 -1
- package/dist/{FluidProvider-Ch_tyk-O.cjs → FluidProvider-B4msuwpR.cjs} +36 -36
- package/dist/{FluidProvider-Ch_tyk-O.cjs.map → FluidProvider-B4msuwpR.cjs.map} +1 -1
- package/dist/{FluidProvider-xCT9m0AV.mjs → FluidProvider-CqFIXA9E.mjs} +36 -36
- package/dist/{FluidProvider-xCT9m0AV.mjs.map → FluidProvider-CqFIXA9E.mjs.map} +1 -1
- package/dist/{MessagingScreen-BLeMJBlZ.mjs → MessagingScreen-8OZSwMYW.mjs} +3 -3
- package/dist/{MessagingScreen-jDXAQrjW.cjs → MessagingScreen-CY8VbrOx.cjs} +3 -3
- package/dist/{MessagingScreen-CsXm0cqp.cjs → MessagingScreen-D_Y3Coa6.cjs} +38 -17
- package/dist/MessagingScreen-D_Y3Coa6.cjs.map +1 -0
- package/dist/{MessagingScreen-Cx1HMX4z.mjs → MessagingScreen-DwU7sqzj.mjs} +38 -17
- package/dist/MessagingScreen-DwU7sqzj.mjs.map +1 -0
- package/dist/{OrdersScreen-DXDqL5ec.mjs → OrdersScreen-CNYPIZBb.mjs} +3 -3
- package/dist/{OrdersScreen-C2qOTfFC.mjs → OrdersScreen-CNzRy_gk.mjs} +3 -3
- package/dist/{OrdersScreen-C2qOTfFC.mjs.map → OrdersScreen-CNzRy_gk.mjs.map} +1 -1
- package/dist/{OrdersScreen-RdIKrkWk.cjs → OrdersScreen-CSYdmQVZ.cjs} +3 -3
- package/dist/{OrdersScreen-DR_Aiyui.cjs → OrdersScreen-DZfsHpZK.cjs} +3 -3
- package/dist/{OrdersScreen-DR_Aiyui.cjs.map → OrdersScreen-DZfsHpZK.cjs.map} +1 -1
- package/dist/{ProfileScreen-CVjKS2Tx.cjs → ProfileScreen-B8Df2C1b.cjs} +3 -3
- package/dist/{ProfileScreen-CVjKS2Tx.cjs.map → ProfileScreen-B8Df2C1b.cjs.map} +1 -1
- package/dist/{ProfileScreen-Ct1eY-TI.cjs → ProfileScreen-DYNeWfwK.cjs} +4 -4
- package/dist/{ProfileScreen-C5i0U4Cg.mjs → ProfileScreen-DsFhKUi2.mjs} +4 -4
- package/dist/{ProfileScreen-5xAu0suR.mjs → ProfileScreen-OH5UYO9J.mjs} +3 -3
- package/dist/{ProfileScreen-5xAu0suR.mjs.map → ProfileScreen-OH5UYO9J.mjs.map} +1 -1
- package/dist/{SubscriptionsScreen-BXBojuLi.cjs → SubscriptionsScreen-C0s1Dy_5.cjs} +4 -4
- package/dist/{SubscriptionsScreen-C_Wt4-wY.mjs → SubscriptionsScreen-CJheY605.mjs} +4 -4
- package/dist/{SubscriptionsScreen-C_Wt4-wY.mjs.map → SubscriptionsScreen-CJheY605.mjs.map} +1 -1
- package/dist/{SubscriptionsScreen-CqLyS0HD.mjs → SubscriptionsScreen-D0wBR3ji.mjs} +4 -4
- package/dist/{SubscriptionsScreen-DCDoF2c3.cjs → SubscriptionsScreen-DplufOOc.cjs} +4 -4
- package/dist/{SubscriptionsScreen-DCDoF2c3.cjs.map → SubscriptionsScreen-DplufOOc.cjs.map} +1 -1
- package/dist/{ar-Q-NaoEri.cjs → ar-BxGpk3WD.cjs} +17 -1
- package/dist/ar-BxGpk3WD.cjs.map +1 -0
- package/dist/{ar-By819iLs.mjs → ar-UY6sMSBz.mjs} +17 -1
- package/dist/ar-UY6sMSBz.mjs.map +1 -0
- package/dist/{bg-CphcIKwp.cjs → bg-6dLdyS22.cjs} +17 -1
- package/dist/bg-6dLdyS22.cjs.map +1 -0
- package/dist/{bg-Ozlunm5D.mjs → bg-DVgZmqBN.mjs} +17 -1
- package/dist/bg-DVgZmqBN.mjs.map +1 -0
- package/dist/{bn-C1XrKXPP.cjs → bn-CN4xchOx.cjs} +17 -1
- package/dist/bn-CN4xchOx.cjs.map +1 -0
- package/dist/{bn-CAx26Q7Z.mjs → bn-CObqi9vT.mjs} +17 -1
- package/dist/bn-CObqi9vT.mjs.map +1 -0
- package/dist/{cs-BxBDT4LE.cjs → cs-C83bfcdz.cjs} +17 -1
- package/dist/cs-C83bfcdz.cjs.map +1 -0
- package/dist/{cs-CzMsKE6E.mjs → cs-DKnyuxXT.mjs} +17 -1
- package/dist/cs-DKnyuxXT.mjs.map +1 -0
- package/dist/{da-DDmqyaY9.mjs → da-BqI9yubs.mjs} +17 -1
- package/dist/da-BqI9yubs.mjs.map +1 -0
- package/dist/{da-C7VwqH9W.cjs → da-DvQ7SG_u.cjs} +17 -1
- package/dist/da-DvQ7SG_u.cjs.map +1 -0
- package/dist/{de-ccXwAZTf.cjs → de-DZtK55DQ.cjs} +17 -1
- package/dist/de-DZtK55DQ.cjs.map +1 -0
- package/dist/{de-BHAmbCdV.mjs → de-ghun6-Q2.mjs} +17 -1
- package/dist/de-ghun6-Q2.mjs.map +1 -0
- package/dist/{el-Cn7eWezs.mjs → el-BnVQ-Skf.mjs} +17 -1
- package/dist/el-BnVQ-Skf.mjs.map +1 -0
- package/dist/{el-CPYxRSxE.cjs → el-D7gKYs0O.cjs} +17 -1
- package/dist/el-D7gKYs0O.cjs.map +1 -0
- package/dist/{es-UTJSo7GT.cjs → es-BQIjuOK4.cjs} +17 -1
- package/dist/es-BQIjuOK4.cjs.map +1 -0
- package/dist/{es-BEUWSN_T.mjs → es-CMsMBiTp.mjs} +17 -1
- package/dist/es-CMsMBiTp.mjs.map +1 -0
- package/dist/{fi-BIN2FPWU.cjs → fi-BzAhQvS6.cjs} +17 -1
- package/dist/fi-BzAhQvS6.cjs.map +1 -0
- package/dist/{fi-Bx6sDcTy.mjs → fi-DCT7Hr4f.mjs} +17 -1
- package/dist/fi-DCT7Hr4f.mjs.map +1 -0
- package/dist/{fr-kth_1NSN.mjs → fr-DS9UzkOd.mjs} +17 -1
- package/dist/fr-DS9UzkOd.mjs.map +1 -0
- package/dist/{fr-ZmFbN7rs.cjs → fr-DeBMFETa.cjs} +17 -1
- package/dist/fr-DeBMFETa.cjs.map +1 -0
- package/dist/{he-ClajU1jI.mjs → he-C-_X_DDe.mjs} +17 -1
- package/dist/he-C-_X_DDe.mjs.map +1 -0
- package/dist/{he-CieyYAcH.cjs → he-DFgmAn4d.cjs} +17 -1
- package/dist/he-DFgmAn4d.cjs.map +1 -0
- package/dist/{hi-Dq6Usj9r.cjs → hi-CNOsQK2m.cjs} +17 -1
- package/dist/hi-CNOsQK2m.cjs.map +1 -0
- package/dist/{hi-BOumyBkw.mjs → hi-D-xszavc.mjs} +17 -1
- package/dist/hi-D-xszavc.mjs.map +1 -0
- package/dist/{hr-BXro_hmk.mjs → hr-BmzzEGwS.mjs} +17 -1
- package/dist/hr-BmzzEGwS.mjs.map +1 -0
- package/dist/{hr-D0rsvL5w.cjs → hr-DS7BbhkR.cjs} +17 -1
- package/dist/hr-DS7BbhkR.cjs.map +1 -0
- package/dist/{hu-BzfeP0To.cjs → hu-B4NGWYHv.cjs} +17 -1
- package/dist/hu-B4NGWYHv.cjs.map +1 -0
- package/dist/{hu-CECKiIJS.mjs → hu-fITR5hBP.mjs} +17 -1
- package/dist/hu-fITR5hBP.mjs.map +1 -0
- package/dist/{id-RnPYk94a.cjs → id-DoLeeCcA.cjs} +17 -1
- package/dist/id-DoLeeCcA.cjs.map +1 -0
- package/dist/{id-xXzEOX1N.mjs → id-IhoBaXCG.mjs} +17 -1
- package/dist/id-IhoBaXCG.mjs.map +1 -0
- package/dist/index.cjs +18 -18
- package/dist/index.d.cts +309 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +309 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +18 -18
- package/dist/{it-BbmPeCmD.cjs → it-DMxVwgUD.cjs} +17 -1
- package/dist/it-DMxVwgUD.cjs.map +1 -0
- package/dist/{it-DDg2CLjd.mjs → it-to_7a6Js.mjs} +17 -1
- package/dist/it-to_7a6Js.mjs.map +1 -0
- package/dist/{ja-Dc8_w26E.cjs → ja-BBblfFr3.cjs} +17 -1
- package/dist/ja-BBblfFr3.cjs.map +1 -0
- package/dist/{ja-BAJHbkve.mjs → ja-tP-WEell.mjs} +17 -1
- package/dist/ja-tP-WEell.mjs.map +1 -0
- package/dist/{ko-Dyu-Wuz6.mjs → ko-Ijy8ztce.mjs} +17 -1
- package/dist/ko-Ijy8ztce.mjs.map +1 -0
- package/dist/{ko-CgnIztAC.cjs → ko-KuTIpeKH.cjs} +17 -1
- package/dist/ko-KuTIpeKH.cjs.map +1 -0
- package/dist/{ms-azDbbJdp.mjs → ms-CF-Z2-NX.mjs} +17 -1
- package/dist/ms-CF-Z2-NX.mjs.map +1 -0
- package/dist/{ms-ru9X-Hv2.cjs → ms-CNrlx04G.cjs} +17 -1
- package/dist/ms-CNrlx04G.cjs.map +1 -0
- package/dist/{nl-Br8QjUuZ.mjs → nl-C-Bbv-C0.mjs} +17 -1
- package/dist/nl-C-Bbv-C0.mjs.map +1 -0
- package/dist/{nl-CusUbo1B.cjs → nl-D0eBn_CI.cjs} +17 -1
- package/dist/nl-D0eBn_CI.cjs.map +1 -0
- package/dist/{no-koa8e5wo.mjs → no-B49o3Ojz.mjs} +17 -1
- package/dist/no-B49o3Ojz.mjs.map +1 -0
- package/dist/{no-D84uIL3_.cjs → no-BkOpvB4D.cjs} +17 -1
- package/dist/no-BkOpvB4D.cjs.map +1 -0
- package/dist/{pl-D6gHXrAQ.mjs → pl-BHTxQZRA.mjs} +17 -1
- package/dist/pl-BHTxQZRA.mjs.map +1 -0
- package/dist/{pl-B2VzrbcN.cjs → pl-D--KYSql.cjs} +17 -1
- package/dist/pl-D--KYSql.cjs.map +1 -0
- package/dist/{pt-4wIpPHzG.cjs → pt-AKMrSAie.cjs} +17 -1
- package/dist/pt-AKMrSAie.cjs.map +1 -0
- package/dist/{pt-B_pFsBYw.mjs → pt-z1PgzYT4.mjs} +17 -1
- package/dist/pt-z1PgzYT4.mjs.map +1 -0
- package/dist/{ro-rDPe5Fas.cjs → ro-BeiCzAAv.cjs} +17 -1
- package/dist/ro-BeiCzAAv.cjs.map +1 -0
- package/dist/{ro-BdEBOLXw.mjs → ro-CcT03CIz.mjs} +17 -1
- package/dist/ro-CcT03CIz.mjs.map +1 -0
- package/dist/{ru-xk7QpB5O.mjs → ru-04PsB9SW.mjs} +17 -1
- package/dist/ru-04PsB9SW.mjs.map +1 -0
- package/dist/{ru-BaRR1lGj.cjs → ru-CmS4sggM.cjs} +17 -1
- package/dist/ru-CmS4sggM.cjs.map +1 -0
- package/dist/{sk-D1eg6Pw_.mjs → sk-CatdqrcN.mjs} +17 -1
- package/dist/sk-CatdqrcN.mjs.map +1 -0
- package/dist/{sk-BCXWO4vb.cjs → sk-Ed8vlsOF.cjs} +17 -1
- package/dist/sk-Ed8vlsOF.cjs.map +1 -0
- package/dist/{sv-Bl_Vqffb.mjs → sv-CUdORyUb.mjs} +17 -1
- package/dist/sv-CUdORyUb.mjs.map +1 -0
- package/dist/{sv-BTNGXOlH.cjs → sv-Cz4K5Ri1.cjs} +17 -1
- package/dist/sv-Cz4K5Ri1.cjs.map +1 -0
- package/dist/task-composer-form-DDzxr6_A.cjs.map +1 -1
- package/dist/task-composer-form-DTHeuJ9-.mjs.map +1 -1
- package/dist/{th-CmwBiN_4.mjs → th-Cvw1o6oJ.mjs} +17 -1
- package/dist/th-Cvw1o6oJ.mjs.map +1 -0
- package/dist/{th-125nDymO.cjs → th-isKXMNPQ.cjs} +17 -1
- package/dist/th-isKXMNPQ.cjs.map +1 -0
- package/dist/{tl-Uvy1BO0V.cjs → tl-gewutb4u.cjs} +17 -1
- package/dist/tl-gewutb4u.cjs.map +1 -0
- package/dist/{tl-EdgOX4qZ.mjs → tl-x0eAo33S.mjs} +17 -1
- package/dist/tl-x0eAo33S.mjs.map +1 -0
- package/dist/{tr-D4MtO2wd.mjs → tr-BK4tCO2D.mjs} +17 -1
- package/dist/tr-BK4tCO2D.mjs.map +1 -0
- package/dist/{tr-DlUVhlGa.cjs → tr-JRCpWrMo.cjs} +17 -1
- package/dist/tr-JRCpWrMo.cjs.map +1 -0
- package/dist/{uk-Bg9CggUW.cjs → uk-7GCrvs02.cjs} +17 -1
- package/dist/uk-7GCrvs02.cjs.map +1 -0
- package/dist/{uk-DQBU-Xs5.mjs → uk-Batc1LYn.mjs} +17 -1
- package/dist/uk-Batc1LYn.mjs.map +1 -0
- package/dist/{use-portal-card-add-3ds-flow-DEPhZhOv.mjs → use-portal-card-add-3ds-flow-ps5Lr2c3.mjs} +2 -2
- package/dist/{use-portal-card-add-3ds-flow-DEPhZhOv.mjs.map → use-portal-card-add-3ds-flow-ps5Lr2c3.mjs.map} +1 -1
- package/dist/{use-portal-card-add-3ds-flow-BK7rp-NL.cjs → use-portal-card-add-3ds-flow-r2akoTNE.cjs} +2 -2
- package/dist/{use-portal-card-add-3ds-flow-BK7rp-NL.cjs.map → use-portal-card-add-3ds-flow-r2akoTNE.cjs.map} +1 -1
- package/dist/{vi-B5jvcCNp.cjs → vi-CfkAcK3W.cjs} +17 -1
- package/dist/vi-CfkAcK3W.cjs.map +1 -0
- package/dist/{vi-Bv7WsZOw.mjs → vi-gZ5HQmE5.mjs} +17 -1
- package/dist/vi-gZ5HQmE5.mjs.map +1 -0
- package/dist/{zh_CN-CmIBZ7Xg.cjs → zh_CN-D5BnBlxf.cjs} +17 -1
- package/dist/zh_CN-D5BnBlxf.cjs.map +1 -0
- package/dist/{zh_CN-C2PaZkc7.mjs → zh_CN-DYt0MsXc.mjs} +17 -1
- package/dist/zh_CN-DYt0MsXc.mjs.map +1 -0
- package/dist/{zh_TW-BWhqcVAs.mjs → zh_TW-BROI3pFG.mjs} +17 -1
- package/dist/zh_TW-BROI3pFG.mjs.map +1 -0
- package/dist/{zh_TW-phSEI-XZ.cjs → zh_TW-C7H6gs6G.cjs} +17 -1
- package/dist/zh_TW-C7H6gs6G.cjs.map +1 -0
- package/package.json +11 -11
- package/dist/MessagingScreen-CsXm0cqp.cjs.map +0 -1
- package/dist/MessagingScreen-Cx1HMX4z.mjs.map +0 -1
- package/dist/ar-By819iLs.mjs.map +0 -1
- package/dist/ar-Q-NaoEri.cjs.map +0 -1
- package/dist/bg-CphcIKwp.cjs.map +0 -1
- package/dist/bg-Ozlunm5D.mjs.map +0 -1
- package/dist/bn-C1XrKXPP.cjs.map +0 -1
- package/dist/bn-CAx26Q7Z.mjs.map +0 -1
- package/dist/cs-BxBDT4LE.cjs.map +0 -1
- package/dist/cs-CzMsKE6E.mjs.map +0 -1
- package/dist/da-C7VwqH9W.cjs.map +0 -1
- package/dist/da-DDmqyaY9.mjs.map +0 -1
- package/dist/de-BHAmbCdV.mjs.map +0 -1
- package/dist/de-ccXwAZTf.cjs.map +0 -1
- package/dist/el-CPYxRSxE.cjs.map +0 -1
- package/dist/el-Cn7eWezs.mjs.map +0 -1
- package/dist/es-BEUWSN_T.mjs.map +0 -1
- package/dist/es-UTJSo7GT.cjs.map +0 -1
- package/dist/fi-BIN2FPWU.cjs.map +0 -1
- package/dist/fi-Bx6sDcTy.mjs.map +0 -1
- package/dist/fr-ZmFbN7rs.cjs.map +0 -1
- package/dist/fr-kth_1NSN.mjs.map +0 -1
- package/dist/he-CieyYAcH.cjs.map +0 -1
- package/dist/he-ClajU1jI.mjs.map +0 -1
- package/dist/hi-BOumyBkw.mjs.map +0 -1
- package/dist/hi-Dq6Usj9r.cjs.map +0 -1
- package/dist/hr-BXro_hmk.mjs.map +0 -1
- package/dist/hr-D0rsvL5w.cjs.map +0 -1
- package/dist/hu-BzfeP0To.cjs.map +0 -1
- package/dist/hu-CECKiIJS.mjs.map +0 -1
- package/dist/id-RnPYk94a.cjs.map +0 -1
- package/dist/id-xXzEOX1N.mjs.map +0 -1
- package/dist/it-BbmPeCmD.cjs.map +0 -1
- package/dist/it-DDg2CLjd.mjs.map +0 -1
- package/dist/ja-BAJHbkve.mjs.map +0 -1
- package/dist/ja-Dc8_w26E.cjs.map +0 -1
- package/dist/ko-CgnIztAC.cjs.map +0 -1
- package/dist/ko-Dyu-Wuz6.mjs.map +0 -1
- package/dist/ms-azDbbJdp.mjs.map +0 -1
- package/dist/ms-ru9X-Hv2.cjs.map +0 -1
- package/dist/nl-Br8QjUuZ.mjs.map +0 -1
- package/dist/nl-CusUbo1B.cjs.map +0 -1
- package/dist/no-D84uIL3_.cjs.map +0 -1
- package/dist/no-koa8e5wo.mjs.map +0 -1
- package/dist/pl-B2VzrbcN.cjs.map +0 -1
- package/dist/pl-D6gHXrAQ.mjs.map +0 -1
- package/dist/pt-4wIpPHzG.cjs.map +0 -1
- package/dist/pt-B_pFsBYw.mjs.map +0 -1
- package/dist/ro-BdEBOLXw.mjs.map +0 -1
- package/dist/ro-rDPe5Fas.cjs.map +0 -1
- package/dist/ru-BaRR1lGj.cjs.map +0 -1
- package/dist/ru-xk7QpB5O.mjs.map +0 -1
- package/dist/sk-BCXWO4vb.cjs.map +0 -1
- package/dist/sk-D1eg6Pw_.mjs.map +0 -1
- package/dist/sv-BTNGXOlH.cjs.map +0 -1
- package/dist/sv-Bl_Vqffb.mjs.map +0 -1
- package/dist/th-125nDymO.cjs.map +0 -1
- package/dist/th-CmwBiN_4.mjs.map +0 -1
- package/dist/tl-EdgOX4qZ.mjs.map +0 -1
- package/dist/tl-Uvy1BO0V.cjs.map +0 -1
- package/dist/tr-D4MtO2wd.mjs.map +0 -1
- package/dist/tr-DlUVhlGa.cjs.map +0 -1
- package/dist/uk-Bg9CggUW.cjs.map +0 -1
- package/dist/uk-DQBU-Xs5.mjs.map +0 -1
- package/dist/vi-B5jvcCNp.cjs.map +0 -1
- package/dist/vi-Bv7WsZOw.mjs.map +0 -1
- package/dist/zh_CN-C2PaZkc7.mjs.map +0 -1
- package/dist/zh_CN-CmIBZ7Xg.cjs.map +0 -1
- package/dist/zh_TW-BWhqcVAs.mjs.map +0 -1
- package/dist/zh_TW-phSEI-XZ.cjs.map +0 -1
|
@@ -6,6 +6,21 @@ var sk_default = {
|
|
|
6
6
|
active: "Aktívne",
|
|
7
7
|
all: "Všetko",
|
|
8
8
|
amount: "Suma",
|
|
9
|
+
auto_apply_points_bundle_body: "Tieto predplatné sa obnovujú spolu v ten istý deň a sú fakturované ako jedna objednávka.",
|
|
10
|
+
auto_apply_points_bundle_cancel: "Zrušiť",
|
|
11
|
+
auto_apply_points_bundle_confirm_all: "Použiť na všetky",
|
|
12
|
+
auto_apply_points_bundle_confirm_all_off: "Vypnúť pre všetky",
|
|
13
|
+
auto_apply_points_bundle_confirm_one: "Len toto",
|
|
14
|
+
auto_apply_points_bundle_conflict_retry: "Táto skupina obnovení sa aktualizuje inde. Skúste znova.",
|
|
15
|
+
auto_apply_points_bundle_member_paused: "{{name}} (pozastavené)",
|
|
16
|
+
auto_apply_points_bundle_membership_changed: "Táto skupina obnovení sa zmenila počas ukladania, takže predplatné, ktoré sme aktualizovali, nemusia zodpovedať tým, ktoré ste potvrdili. Otvorte skupinu znova, aby ste videli aktuálne nastavenie.",
|
|
17
|
+
auto_apply_points_bundle_split_warning: "Výber inak pre jedno predplatné môže spôsobiť, že sa obnoví ako jeho vlastná objednávka. Doprava by sa potom vypočítala zvlášť a môže byť bezplatná, a spôsob platenia jednotlivých objednávok sa môže zmeniť.",
|
|
18
|
+
auto_apply_points_bundle_title: "Použiť {{label}} na túto skupinu obnovení?",
|
|
19
|
+
auto_apply_points_bundle_title_off: "Prestať používať {{label}} na túto skupinu obnovení?",
|
|
20
|
+
auto_apply_points_each_renewal: "Automaticky použiť {{label}} pri každej obnove",
|
|
21
|
+
auto_apply_points_partial_balance: "Ak váš zostatok nemôže pokryť celú obnovu, použijeme to, čo je dostupné.",
|
|
22
|
+
auto_apply_points_saved_but_not_refreshed: "Vaše nastavenie automatického {{label}} bolo uložené, ale túto stránku sa nepodarilo obnoviť. Načítajte ju znova, aby ste videli aktuálne nastavenie.",
|
|
23
|
+
auto_apply_points_updated: "Automatické {{label}} aktualizované",
|
|
9
24
|
bill_date_error: "Nepodarilo sa aktualizovať dátum faktúry. Skúste iné dátum.",
|
|
10
25
|
bill_date_preview_prefix: "Ďalšia faktúra bude dňa",
|
|
11
26
|
bill_date_preview_suffix: ".",
|
|
@@ -92,6 +107,7 @@ var sk_default = {
|
|
|
92
107
|
failed_to_reactivate: "Nepodarilo sa reaktivovať predplatné",
|
|
93
108
|
failed_to_resume: "Nepodarilo sa obnoviť predplatné",
|
|
94
109
|
failed_to_skip: "Nepodarilo sa preskočiť fakturáciu",
|
|
110
|
+
failed_to_update_auto_apply_points: "Nepodarilo sa aktualizovať nastavenie automatického {{label}}",
|
|
95
111
|
failed_to_update_bill_date: "Nepodarilo sa aktualizovať dátum faktúry",
|
|
96
112
|
failed_to_update_quantity: "Nepodarilo sa aktualizovať množstvo",
|
|
97
113
|
generic_error: "Niečo sa pokazilo. Skúste to znova.",
|
|
@@ -273,4 +289,4 @@ Object.defineProperty(exports, "default", {
|
|
|
273
289
|
}
|
|
274
290
|
});
|
|
275
291
|
|
|
276
|
-
//# sourceMappingURL=sk-
|
|
292
|
+
//# sourceMappingURL=sk-Ed8vlsOF.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sk-Ed8vlsOF.cjs","names":[],"sources":["../../../subscriptions/core/src/locale/sk.json"],"sourcesContent":[""],"mappings":""}
|
|
@@ -5,6 +5,21 @@ var sv_default = {
|
|
|
5
5
|
active: "Aktiv",
|
|
6
6
|
all: "Alla",
|
|
7
7
|
amount: "Belopp",
|
|
8
|
+
auto_apply_points_bundle_body: "Dessa prenumerationer förnyas tillsammans samma dag och faktureras som en order.",
|
|
9
|
+
auto_apply_points_bundle_cancel: "Avbryt",
|
|
10
|
+
auto_apply_points_bundle_confirm_all: "Använd för alla",
|
|
11
|
+
auto_apply_points_bundle_confirm_all_off: "Slå av för alla",
|
|
12
|
+
auto_apply_points_bundle_confirm_one: "Bara denna",
|
|
13
|
+
auto_apply_points_bundle_conflict_retry: "Denna förnyelsegrupp uppdateras någon annanstans. Försök igen.",
|
|
14
|
+
auto_apply_points_bundle_member_paused: "{{name}} (pausad)",
|
|
15
|
+
auto_apply_points_bundle_membership_changed: "Denna förnyelsegrupp ändrades vid sparning, så prenumerationerna vi uppdaterade kanske inte stämmer överens med dem du bekräftade. Öppna gruppen igen för att se den aktuella inställningen.",
|
|
16
|
+
auto_apply_points_bundle_split_warning: "Olika inställningar för en prenumeration gör att den förnyas som en separat order. Frakt beräknas då separat och kan bli kostnadsfri, och hur varje order betalas kan ändras.",
|
|
17
|
+
auto_apply_points_bundle_title: "Använd {{label}} för denna förnyelsegrupp?",
|
|
18
|
+
auto_apply_points_bundle_title_off: "Sluta använda {{label}} för denna förnyelsegrupp?",
|
|
19
|
+
auto_apply_points_each_renewal: "Använd {{label}} automatiskt vid varje förnyelse",
|
|
20
|
+
auto_apply_points_partial_balance: "Om ditt saldo inte räcker till en full förnyelse använder vi det som är tillgängligt.",
|
|
21
|
+
auto_apply_points_saved_but_not_refreshed: "Din automatiska {{label}}-inställning sparades, men sidan kunde inte uppdateras. Ladda om för att se den aktuella inställningen.",
|
|
22
|
+
auto_apply_points_updated: "Automatisk {{label}} uppdaterad",
|
|
8
23
|
bill_date_error: "Kunde inte uppdatera faktureringsdatum. Försök med ett annat datum.",
|
|
9
24
|
bill_date_preview_prefix: "Din nästa faktura skickas den",
|
|
10
25
|
bill_date_preview_suffix: ".",
|
|
@@ -91,6 +106,7 @@ var sv_default = {
|
|
|
91
106
|
failed_to_reactivate: "Det gick inte att återaktivera prenumerationen",
|
|
92
107
|
failed_to_resume: "Det gick inte att återuppta prenumerationen",
|
|
93
108
|
failed_to_skip: "Det gick inte att hoppa över fakturering",
|
|
109
|
+
failed_to_update_auto_apply_points: "Misslyckades att uppdatera den automatiska {{label}}-inställningen",
|
|
94
110
|
failed_to_update_bill_date: "Det gick inte att uppdatera faktureringsdatum",
|
|
95
111
|
failed_to_update_quantity: "Det gick inte att uppdatera kvantitet",
|
|
96
112
|
generic_error: "Något gick fel. Försök igen.",
|
|
@@ -267,4 +283,4 @@ var sv_default = {
|
|
|
267
283
|
//#endregion
|
|
268
284
|
export { sv_default as default };
|
|
269
285
|
|
|
270
|
-
//# sourceMappingURL=sv-
|
|
286
|
+
//# sourceMappingURL=sv-CUdORyUb.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sv-CUdORyUb.mjs","names":[],"sources":["../../../subscriptions/core/src/locale/sv.json"],"sourcesContent":[""],"mappings":""}
|
|
@@ -6,6 +6,21 @@ var sv_default = {
|
|
|
6
6
|
active: "Aktiv",
|
|
7
7
|
all: "Alla",
|
|
8
8
|
amount: "Belopp",
|
|
9
|
+
auto_apply_points_bundle_body: "Dessa prenumerationer förnyas tillsammans samma dag och faktureras som en order.",
|
|
10
|
+
auto_apply_points_bundle_cancel: "Avbryt",
|
|
11
|
+
auto_apply_points_bundle_confirm_all: "Använd för alla",
|
|
12
|
+
auto_apply_points_bundle_confirm_all_off: "Slå av för alla",
|
|
13
|
+
auto_apply_points_bundle_confirm_one: "Bara denna",
|
|
14
|
+
auto_apply_points_bundle_conflict_retry: "Denna förnyelsegrupp uppdateras någon annanstans. Försök igen.",
|
|
15
|
+
auto_apply_points_bundle_member_paused: "{{name}} (pausad)",
|
|
16
|
+
auto_apply_points_bundle_membership_changed: "Denna förnyelsegrupp ändrades vid sparning, så prenumerationerna vi uppdaterade kanske inte stämmer överens med dem du bekräftade. Öppna gruppen igen för att se den aktuella inställningen.",
|
|
17
|
+
auto_apply_points_bundle_split_warning: "Olika inställningar för en prenumeration gör att den förnyas som en separat order. Frakt beräknas då separat och kan bli kostnadsfri, och hur varje order betalas kan ändras.",
|
|
18
|
+
auto_apply_points_bundle_title: "Använd {{label}} för denna förnyelsegrupp?",
|
|
19
|
+
auto_apply_points_bundle_title_off: "Sluta använda {{label}} för denna förnyelsegrupp?",
|
|
20
|
+
auto_apply_points_each_renewal: "Använd {{label}} automatiskt vid varje förnyelse",
|
|
21
|
+
auto_apply_points_partial_balance: "Om ditt saldo inte räcker till en full förnyelse använder vi det som är tillgängligt.",
|
|
22
|
+
auto_apply_points_saved_but_not_refreshed: "Din automatiska {{label}}-inställning sparades, men sidan kunde inte uppdateras. Ladda om för att se den aktuella inställningen.",
|
|
23
|
+
auto_apply_points_updated: "Automatisk {{label}} uppdaterad",
|
|
9
24
|
bill_date_error: "Kunde inte uppdatera faktureringsdatum. Försök med ett annat datum.",
|
|
10
25
|
bill_date_preview_prefix: "Din nästa faktura skickas den",
|
|
11
26
|
bill_date_preview_suffix: ".",
|
|
@@ -92,6 +107,7 @@ var sv_default = {
|
|
|
92
107
|
failed_to_reactivate: "Det gick inte att återaktivera prenumerationen",
|
|
93
108
|
failed_to_resume: "Det gick inte att återuppta prenumerationen",
|
|
94
109
|
failed_to_skip: "Det gick inte att hoppa över fakturering",
|
|
110
|
+
failed_to_update_auto_apply_points: "Misslyckades att uppdatera den automatiska {{label}}-inställningen",
|
|
95
111
|
failed_to_update_bill_date: "Det gick inte att uppdatera faktureringsdatum",
|
|
96
112
|
failed_to_update_quantity: "Det gick inte att uppdatera kvantitet",
|
|
97
113
|
generic_error: "Något gick fel. Försök igen.",
|
|
@@ -273,4 +289,4 @@ Object.defineProperty(exports, "default", {
|
|
|
273
289
|
}
|
|
274
290
|
});
|
|
275
291
|
|
|
276
|
-
//# sourceMappingURL=sv-
|
|
292
|
+
//# sourceMappingURL=sv-Cz4K5Ri1.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sv-Cz4K5Ri1.cjs","names":[],"sources":["../../../subscriptions/core/src/locale/sv.json"],"sourcesContent":[""],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-composer-form-DDzxr6_A.cjs","names":["createTranslationContext","X","Popover","PopoverTrigger","cn","CalendarIcon","Clock","PopoverContent","Separator","Sun","Sunrise","CalendarDays","CircleOff","Calendar"],"sources":["../../../contacts/core/src/contacts-api-context.ts","../../../contacts/core/src/translation-api-context.ts","../../../contacts/core/src/parse-task-body.ts","../../../contacts/core/src/iso-date.ts","../../../contacts/ui/src/portal/utils/format-date.ts","../../../contacts/core/src/query-keys.ts","../../../contacts/core/src/hooks/use-infinite-contacts.ts","../../../contacts/ui/src/portal/components/tasks/task-composer-form.tsx"],"sourcesContent":["import { createContext, use } from \"react\";\nimport type { ContactsApi } from \"./contacts-api\";\nimport type { NotesApi } from \"./notes-api\";\nimport type { TasksApi } from \"./tasks-api\";\nimport type { GroupsApi } from \"./groups-api\";\n\nexport interface ContactsDomainApi {\n contacts: ContactsApi;\n notes: NotesApi;\n tasks: TasksApi;\n groups?: GroupsApi;\n}\n\nconst ContactsApiContext = createContext<ContactsDomainApi | null>(null);\n\nexport const ContactsApiProvider = ContactsApiContext.Provider;\n\nexport function useContactsDomainApi(): ContactsDomainApi {\n const api = use(ContactsApiContext);\n if (!api) {\n throw new Error(\n \"useContactsDomainApi must be used within a ContactsApiProvider\",\n );\n }\n return api;\n}\n\nexport function useContactsCrud(): ContactsApi {\n return useContactsDomainApi().contacts;\n}\n\nexport function useNotesApi(): NotesApi {\n return useContactsDomainApi().notes;\n}\n\nexport function useTasksApi(): TasksApi {\n return useContactsDomainApi().tasks;\n}\n\n/** Returns GroupsApi if the provider supplies one, otherwise null. */\nexport function useGroupsApi(): GroupsApi | null {\n return useContactsDomainApi().groups ?? null;\n}\n","import { use, type Provider } from \"react\";\nimport { createTranslationContext } from \"@fluid-app/i18n/translation-api-context-factory\";\nimport type { TranslationApi } from \"@fluid-app/i18n/translation-api\";\nimport type { ContactsDict } from \"./translation-dictionary\";\n\nconst {\n Context,\n Provider: ContactsProvider,\n useTranslation,\n} = createTranslationContext<ContactsDict>(\"Contacts\");\n\nexport const ContactsTranslationProvider: Provider<TranslationApi<ContactsDict> | null> =\n ContactsProvider;\nexport const useContactsTranslation = useTranslation;\n\n/**\n * Like `useContactsTranslation()` but returns `null` instead of throwing\n * when no `ContactsTranslationProvider` is present in the tree.\n * Useful for shared hooks consumed by both portal (has provider) and admin (no provider).\n */\nexport function useOptionalContactsTranslation(): TranslationApi<ContactsDict> | null {\n return use(Context);\n}\n","/**\n * Tasks store both a title (first line) and an optional body separated by a\n * blank line. This is the canonical convention used by the task editor and\n * by every consumer that displays tasks (contacts UI list, portal todo\n * widget). Drift across consumers would mean some surfaces show \"Title\\n\\n\n * body details\" verbatim while others split correctly — keep the delimiter\n * convention in one place.\n */\nexport function parseTaskBody(raw: string): { title: string; body: string } {\n const split = raw.indexOf(\"\\n\\n\");\n if (split >= 0) {\n return {\n title: raw.slice(0, split),\n body: raw.slice(split + 2),\n };\n }\n return { title: raw, body: \"\" };\n}\n","/**\n * Format a date as YYYY-MM-DD in the renderer's local timezone, optionally\n * shifted by `offsetDays`. Use this for due-date inputs where \"today\" must\n * resolve to the user's local calendar date — never `toISOString().slice(0, 10)`,\n * which returns the UTC date and silently rolls over a day for users east/west\n * of UTC at the wrong hours.\n */\nexport function isoDate(offsetDays: number, now: Date = new Date()): string {\n const d = new Date(now);\n d.setDate(d.getDate() + offsetDays);\n const yyyy = d.getFullYear();\n const mm = String(d.getMonth() + 1).padStart(2, \"0\");\n const dd = String(d.getDate()).padStart(2, \"0\");\n return `${yyyy}-${mm}-${dd}`;\n}\n\n/**\n * Return a Date pinned to local midnight of the calendar day represented by\n * `input`. Use this whenever you need to compare two due dates by calendar day\n * (overdue / today / tomorrow / future).\n *\n * Why not just `new Date(input)`? `new Date(\"YYYY-MM-DD\")` parses the string\n * as UTC midnight, which lands on the *previous* calendar day in any UTC−\n * timezone — a task due \"May 1\" then reads as April 30 for a user in the\n * Americas, classifying it as \"Overdue\" all day. Parse the date components\n * directly so the calendar-day intent of the string is preserved.\n */\nexport function startOfLocalDay(input: Date | string): Date {\n if (typeof input === \"string\") {\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})/.exec(input);\n if (match?.[1] && match[2] && match[3]) {\n return new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3]));\n }\n }\n const d = typeof input === \"string\" ? new Date(input) : input;\n return new Date(d.getFullYear(), d.getMonth(), d.getDate());\n}\n","import { isoDate, startOfLocalDay } from \"@fluid-app/contacts-core/iso-date\";\n\n/** Detect bare YYYY-MM-DD and ISO strings whose time is exactly midnight. */\nexport const ALL_DAY_PATTERN =\n /^\\d{4}-\\d{2}-\\d{2}(?:$|T00:00(?::00(?:\\.\\d+)?)?(?:[+-]\\d{2}:\\d{2}|Z)?)$/;\n\n/**\n * Detect non-Z ISO date-time strings that should stay on the timed path instead\n * of being classified as all-day. Editors may read the written date/time fields\n * directly. A trailing `Z` is intentionally excluded; UTC midnight values may\n * still be handled as all-day by ALL_DAY_PATTERN.\n */\nexport const LOCAL_TIMED_DUE_AT_PATTERN =\n /^\\d{4}-\\d{2}-\\d{2}T(\\d{2}):(\\d{2})(?::\\d{2}(?:\\.\\d+)?)?(?:[+-]\\d{2}:\\d{2})?$/;\n\nexport function isAllDay(dateStr: string): boolean {\n return ALL_DAY_PATTERN.test(dateStr);\n}\n\nexport function toDateInputValue(dueDate: string | null | undefined): string {\n if (!dueDate) return \"\";\n if (LOCAL_TIMED_DUE_AT_PATTERN.test(dueDate)) {\n return dueDate.slice(0, 10);\n }\n\n if (isAllDay(dueDate)) {\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})/.exec(dueDate);\n if (match?.[1] && match[2] && match[3])\n return `${match[1]}-${match[2]}-${match[3]}`;\n return \"\";\n }\n\n const d = new Date(dueDate);\n if (Number.isNaN(d.getTime())) return \"\";\n return isoDate(0, d);\n}\n\nexport function getLocalCalendarDayDiff(\n dateStr: string,\n now: Date = new Date(),\n): number | null {\n const date = startOfLocalDay(dateStr);\n if (Number.isNaN(date.getTime())) return null;\n\n const today = startOfLocalDay(now);\n const dateUtc = Date.UTC(date.getFullYear(), date.getMonth(), date.getDate());\n const todayUtc = Date.UTC(\n today.getFullYear(),\n today.getMonth(),\n today.getDate(),\n );\n\n return Math.round((dateUtc - todayUtc) / (1000 * 60 * 60 * 24));\n}\n\nexport function formatDateForDisplay(dateStr: string, locale?: string): string {\n const normalizedLocale = locale?.replace(/_/g, \"-\") ?? \"en-US\";\n // All-day / midnight values: preserve the represented calendar date\n // regardless of local timezone. Genuine timed instants are parsed with\n // new Date() so the locale string reflects the instant.\n const date = isAllDay(dateStr) ? startOfLocalDay(dateStr) : new Date(dateStr);\n return date.toLocaleDateString(normalizedLocale, {\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n });\n}\n","export const CONTACTS_QUERY_KEYS = {\n all: (prefix: string) => [prefix] as const,\n list: (prefix: string) =>\n [...CONTACTS_QUERY_KEYS.all(prefix), \"list\"] as const,\n detail: (prefix: string, id: string) =>\n [...CONTACTS_QUERY_KEYS.all(prefix), \"detail\", id] as const,\n} as const;\n\nexport const contactsKeys = {\n activities: (contactId: string) =>\n [\"portal-contacts\", \"activities\", contactId] as const,\n tasks: (contactId: string) =>\n [\"portal-contacts\", \"tasks\", contactId] as const,\n notes: (contactId: string) =>\n [\"portal-contacts\", \"notes\", contactId] as const,\n orders: (contactId: string) => [\"rep-contacts\", \"orders\", contactId] as const,\n subscriptionOrders: (contactId: string) =>\n [\"rep-contacts\", \"subscription-orders\", contactId] as const,\n groups: () => [\"portal-contacts\", \"groups\"] as const,\n groupMembers: (groupName: string) =>\n [\"portal-contacts\", \"group-members\", groupName] as const,\n groupAddSearch: (groupName: string, search: string) =>\n [\"portal-contacts\", \"group-add-search\", groupName, search] as const,\n} as const;\n","import { useInfiniteQuery } from \"@tanstack/react-query\";\nimport { useContactsCrud } from \"../contacts-api-context\";\nimport { CONTACTS_QUERY_KEYS } from \"../query-keys\";\n\nexport interface UseInfiniteContactsParams {\n search_query?: string;\n status?: string;\n sort_by?: string;\n sort_direction?: string;\n per_page?: number;\n tags?: string[];\n}\n\nexport function useInfiniteContacts(params: UseInfiniteContactsParams) {\n const api = useContactsCrud();\n return useInfiniteQuery({\n queryKey: [...CONTACTS_QUERY_KEYS.list(\"contacts\"), params],\n queryFn: ({ pageParam }) =>\n api.listContacts({\n ...params,\n page: pageParam,\n }),\n getNextPageParam: (lastPage) => {\n const currentPage = lastPage.meta.current_page;\n // Contacts API is page-number based; next_cursor and total_pages\n // are both used as \"has-next-page\" signals.\n if (currentPage == null) return undefined;\n if (lastPage.meta.next_cursor) return currentPage + 1;\n if (\n lastPage.meta.total_pages != null &&\n currentPage < lastPage.meta.total_pages\n ) {\n return currentPage + 1;\n }\n return undefined;\n },\n initialPageParam: 1,\n });\n}\n","\"use client\";\n\nimport React, { useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport {\n CalendarDays,\n CalendarIcon,\n CircleOff,\n Clock,\n Sunrise,\n Sun,\n X,\n type LucideIcon,\n} from \"lucide-react\";\nimport {\n Calendar,\n Popover,\n PopoverContent,\n PopoverTrigger,\n Separator,\n cn,\n type CalendarProps,\n} from \"@fluid-app/ui-primitives\";\nimport { isoDate, startOfLocalDay } from \"@fluid-app/contacts-core/iso-date\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport {\n formatDateForDisplay,\n getLocalCalendarDayDiff,\n isAllDay,\n LOCAL_TIMED_DUE_AT_PATTERN,\n toDateInputValue,\n} from \"../../utils/format-date\";\n\nconst RELATIVE_DATE_MAX_DAYS = 30;\nconst DEFAULT_DUE_TIME = \"12:00\";\nconst TIME_INPUT_PATTERN = /^(\\d{2}):(\\d{2})$/;\n\nfunction isValidTimeInput(timeValue: string): boolean {\n const match = TIME_INPUT_PATTERN.exec(timeValue);\n const hours = match?.[1] ? Number(match[1]) : Number.NaN;\n const minutes = match?.[2] ? Number(match[2]) : Number.NaN;\n\n return (\n Number.isInteger(hours) &&\n Number.isInteger(minutes) &&\n hours >= 0 &&\n hours <= 23 &&\n minutes >= 0 &&\n minutes <= 59\n );\n}\n\nfunction toTimeInputValue(dueDate: string | null | undefined): string {\n if (!dueDate) return \"\";\n\n const localTimedMatch = LOCAL_TIMED_DUE_AT_PATTERN.exec(dueDate);\n if (localTimedMatch?.[1] && localTimedMatch[2]) {\n const timeValue = `${localTimedMatch[1]}:${localTimedMatch[2]}`;\n return isValidTimeInput(timeValue) ? timeValue : \"\";\n }\n\n if (isAllDay(dueDate)) return \"\";\n\n const date = new Date(dueDate);\n if (Number.isNaN(date.getTime())) return \"\";\n\n return `${String(date.getHours()).padStart(2, \"0\")}:${String(\n date.getMinutes(),\n ).padStart(2, \"0\")}`;\n}\n\nfunction formatTimeForDisplay(timeValue: string, locale: string): string {\n const match = TIME_INPUT_PATTERN.exec(timeValue);\n const hours = match?.[1] ? Number(match[1]) : Number.NaN;\n const minutes = match?.[2] ? Number(match[2]) : Number.NaN;\n\n if (!isValidTimeInput(timeValue)) return timeValue;\n\n const date = new Date();\n date.setHours(hours, minutes, 0, 0);\n\n return new Intl.DateTimeFormat(locale, {\n hour: \"numeric\",\n minute: \"2-digit\",\n }).format(date);\n}\n\nfunction formatOffset(date: Date): string {\n const offsetMinutes = -date.getTimezoneOffset();\n const sign = offsetMinutes >= 0 ? \"+\" : \"-\";\n const absoluteOffset = Math.abs(offsetMinutes);\n const hours = String(Math.floor(absoluteOffset / 60)).padStart(2, \"0\");\n const minutes = String(absoluteOffset % 60).padStart(2, \"0\");\n\n return `${sign}${hours}:${minutes}`;\n}\n\nfunction composeDueAt(dateOnlyValue: string, timeValue: string): string | null {\n if (!dateOnlyValue) return null;\n if (isValidTimeInput(timeValue)) {\n const dateMatch = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(dateOnlyValue);\n const timeMatch = TIME_INPUT_PATTERN.exec(timeValue);\n if (\n dateMatch?.[1] &&\n dateMatch[2] &&\n dateMatch[3] &&\n timeMatch?.[1] &&\n timeMatch[2]\n ) {\n const localDate = new Date(\n Number(dateMatch[1]),\n Number(dateMatch[2]) - 1,\n Number(dateMatch[3]),\n Number(timeMatch[1]),\n Number(timeMatch[2]),\n 0,\n 0,\n );\n\n return `${dateOnlyValue}T${timeValue}:00${formatOffset(localDate)}`;\n }\n }\n\n return dateOnlyValue;\n}\n\ninterface QuickDateRowProps {\n icon: LucideIcon;\n label: string;\n rightLabel?: string;\n onSelect: () => void;\n}\n\nfunction QuickDateRow({\n icon: Icon,\n label,\n rightLabel,\n onSelect,\n}: QuickDateRowProps): React.JSX.Element {\n return (\n <button\n type=\"button\"\n onClick={onSelect}\n className=\"text-foreground hover:bg-accent hover:text-accent-foreground focus-visible:ring-ring flex w-full min-w-0 items-center gap-3 rounded-lg px-2 py-2 text-sm transition-colors outline-none focus-visible:ring-2\"\n >\n <Icon className=\"size-4 shrink-0\" aria-hidden=\"true\" />\n <span className=\"min-w-0 flex-1 truncate text-left font-medium\">\n {label}\n </span>\n {rightLabel && (\n <span className=\"ml-auto max-w-[50%] min-w-0 truncate text-right text-xs font-medium text-current/80\">\n {rightLabel}\n </span>\n )}\n </button>\n );\n}\n\nexport interface TaskComposerFormValues {\n body: string;\n due_at: string | null;\n}\n\nexport interface TaskComposerFormProps {\n /** Caller-controlled submit handler. */\n onSubmit: (values: TaskComposerFormValues) => void;\n /** Disable the submit button while the parent mutation is in flight. */\n isSubmitting?: boolean;\n /** Label for the submit button. Defaults to translated \"add_task\". */\n submitLabel?: string;\n /** Label shown while submitting. Defaults to translated \"adding\". */\n submittingLabel?: string;\n /** Optional initial body — used for edit mode. */\n initialBody?: string;\n /** Optional initial due date (ISO string) — used for edit mode. */\n initialDueAt?: string | null;\n /** Optional controls rendered after the date controls in the metadata row. */\n metadataControls?: React.ReactNode;\n /** When provided, an X button is rendered and Escape closes the form. */\n onClose?: () => void;\n /** Focus the body input on mount. Default true. */\n autoFocus?: boolean;\n}\n\nexport function TaskComposerForm({\n onSubmit,\n isSubmitting = false,\n submitLabel,\n submittingLabel,\n initialBody = \"\",\n initialDueAt = null,\n metadataControls,\n onClose,\n autoFocus = true,\n}: TaskComposerFormProps): React.JSX.Element {\n const { t, locale } = useContactsTranslation();\n const [body, setBody] = useState(initialBody);\n const [dueDate, setDueDate] = useState<string | null>(initialDueAt ?? null);\n const [dueTime, setDueTime] = useState(\n () => toTimeInputValue(initialDueAt) || DEFAULT_DUE_TIME,\n );\n const [dateTimeControlsChanged, setDateTimeControlsChanged] = useState(false);\n const [datePopoverOpen, setDatePopoverOpen] = useState(false);\n const [labelNow, setLabelNow] = useState(() => new Date());\n const timeInputId = useId();\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n useEffect(() => {\n if (autoFocus) inputRef.current?.focus();\n }, [autoFocus]);\n\n useEffect(() => {\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const scheduleNextMidnightUpdate = () => {\n const now = new Date();\n setLabelNow(now);\n\n const nextMidnight = new Date(now);\n nextMidnight.setHours(24, 0, 0, 0);\n\n timeoutId = setTimeout(\n scheduleNextMidnightUpdate,\n nextMidnight.getTime() - now.getTime(),\n );\n };\n\n scheduleNextMidnightUpdate();\n\n return () => {\n if (timeoutId != null) clearTimeout(timeoutId);\n };\n }, []);\n\n const dateOnlyValue = useMemo(() => toDateInputValue(dueDate), [dueDate]);\n const hasDateSelected = dateOnlyValue !== \"\";\n const hasInitialTimedDueAt = toTimeInputValue(initialDueAt) !== \"\";\n const hasTimeSelected =\n dueTime !== \"\" &&\n hasDateSelected &&\n (dateTimeControlsChanged || hasInitialTimedDueAt);\n const selectedCalendarDate = useMemo(\n () => (dateOnlyValue === \"\" ? undefined : startOfLocalDay(dateOnlyValue)),\n [dateOnlyValue],\n );\n const todayLocalMidnight = useMemo(\n () => startOfLocalDay(labelNow),\n [labelNow],\n );\n const normalizedLocale = useMemo(\n () => locale?.replace(/_/g, \"-\") ?? \"en-US\",\n [locale],\n );\n const calendarDefaultMonth = useMemo(() => {\n if (!selectedCalendarDate) return todayLocalMidnight;\n\n return selectedCalendarDate.getTime() < todayLocalMidnight.getTime()\n ? todayLocalMidnight\n : selectedCalendarDate;\n }, [selectedCalendarDate, todayLocalMidnight]);\n\n const quickDates = useMemo(() => {\n const tomorrow = isoDate(1, labelNow);\n const nextWeek = isoDate(7, labelNow);\n const weekdayFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n weekday: \"short\",\n });\n const nextWeekFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n weekday: \"short\",\n month: \"short\",\n day: \"numeric\",\n });\n\n return {\n tomorrow,\n tomorrowLabel: weekdayFormatter.format(startOfLocalDay(tomorrow)),\n nextWeek,\n nextWeekLabel: nextWeekFormatter.format(startOfLocalDay(nextWeek)),\n };\n }, [labelNow, normalizedLocale]);\n\n const calendarFormatters = useMemo<\n NonNullable<CalendarProps[\"formatters\"]>\n >(() => {\n const monthYearFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n month: \"long\",\n year: \"numeric\",\n });\n const monthFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n month: \"long\",\n });\n const yearFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n year: \"numeric\",\n });\n const dayFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n day: \"numeric\",\n });\n const weekdayFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n weekday: \"short\",\n });\n const weekNumberFormatter = new Intl.NumberFormat(normalizedLocale);\n\n return {\n formatCaption: (month) => monthYearFormatter.format(month),\n formatMonthCaption: (month) => monthFormatter.format(month),\n formatYearCaption: (year) => yearFormatter.format(year),\n formatDay: (day) => dayFormatter.format(day),\n formatWeekdayName: (weekday) => weekdayFormatter.format(weekday),\n formatWeekNumber: (weekNumber) => weekNumberFormatter.format(weekNumber),\n };\n }, [normalizedLocale]);\n\n const calendarLabels = useMemo<NonNullable<CalendarProps[\"labels\"]>>(() => {\n const dayLabelFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n weekday: \"long\",\n month: \"long\",\n day: \"numeric\",\n year: \"numeric\",\n });\n const weekdayLabelFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n weekday: \"long\",\n });\n const weekNumberFormatter = new Intl.NumberFormat(normalizedLocale);\n\n return {\n labelNext: () => t(\"calendar_next_month\"),\n labelPrevious: () => t(\"calendar_previous_month\"),\n labelMonthDropdown: () => t(\"calendar_month_dropdown\"),\n labelYearDropdown: () => t(\"calendar_year_dropdown\"),\n labelDay: (day) => dayLabelFormatter.format(day),\n labelWeekday: (weekday) => weekdayLabelFormatter.format(weekday),\n labelWeekNumber: (weekNumber) =>\n t(\"calendar_week_number\", {\n number: weekNumberFormatter.format(weekNumber),\n }),\n };\n }, [normalizedLocale, t]);\n\n const dateBadgeLabel = useMemo(() => {\n if (!hasDateSelected) return t(\"task_select_date\");\n\n const diffDays = getLocalCalendarDayDiff(dateOnlyValue, labelNow);\n if (diffDays === 0) return t(\"quick_today\");\n if (diffDays === 1) return t(\"quick_tomorrow\");\n if (\n diffDays != null &&\n diffDays >= 2 &&\n diffDays <= RELATIVE_DATE_MAX_DAYS\n ) {\n return t(\"task_due_in_days\", { count: diffDays });\n }\n\n return formatDateForDisplay(dateOnlyValue, normalizedLocale);\n }, [dateOnlyValue, hasDateSelected, labelNow, normalizedLocale, t]);\n\n const timeBadgeLabel = useMemo(\n () =>\n hasTimeSelected ? formatTimeForDisplay(dueTime, normalizedLocale) : \"\",\n [dueTime, hasTimeSelected, normalizedLocale],\n );\n const dateBadgeAriaLabel = hasTimeSelected\n ? `${dateBadgeLabel}, ${timeBadgeLabel}`\n : dateBadgeLabel;\n\n const submit = () => {\n const trimmed = body.trim();\n if (!trimmed || isSubmitting) return;\n\n onSubmit({\n body: trimmed,\n due_at: dateTimeControlsChanged\n ? composeDueAt(dateOnlyValue, dueTime)\n : (initialDueAt ?? null),\n });\n };\n\n const canSubmit = body.trim().length > 0 && !isSubmitting;\n\n const selectDueDate = (value: string) => {\n setDateTimeControlsChanged(true);\n setDueDate(value);\n setDueTime((currentTime) => currentTime || DEFAULT_DUE_TIME);\n };\n\n const clearDueDate = () => {\n setDateTimeControlsChanged(true);\n setDueDate(null);\n setDueTime(DEFAULT_DUE_TIME);\n setDatePopoverOpen(false);\n };\n\n const handleTimeChange = (value: string) => {\n setDateTimeControlsChanged(true);\n setDueTime(value);\n if (value && !hasDateSelected) setDueDate(isoDate(0, labelNow));\n };\n\n return (\n <div className=\"border-border/50 focus-within:border-foreground/30 rounded-xl border p-3 transition-colors\">\n <div className=\"flex items-start gap-3\">\n <div\n className=\"border-muted-foreground/50 mt-1.5 size-5 shrink-0 rounded-full border-2\"\n aria-hidden=\"true\"\n />\n <input\n ref={inputRef}\n value={body}\n onChange={(e) => setBody(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n submit();\n } else if (e.key === \"Escape\" && onClose) {\n e.preventDefault();\n onClose();\n }\n }}\n placeholder={t(\"task_describe_placeholder\")}\n aria-label={t(\"task_description_aria\")}\n className=\"placeholder:text-muted-foreground/80 text-foreground flex-1 border-0 bg-transparent text-sm font-medium outline-none pointer-coarse:text-base\"\n />\n {onClose && (\n <button\n type=\"button\"\n onClick={onClose}\n aria-label={t(\"task_discard_aria\")}\n className=\"text-muted-foreground hover:bg-muted hover:text-foreground -mt-0.5 -mr-0.5 flex size-7 shrink-0 items-center justify-center rounded-md transition-colors\"\n >\n <X className=\"size-4\" />\n </button>\n )}\n </div>\n\n {/* --row-indent aligns the date row with the input text above (size-5\n circle + gap-3 = 2rem). The mobile Add button cancels it via\n -ml-(--row-indent) + w-[calc(100%+var(--row-indent))] so the two\n values stay locked to a single source. */}\n <div className=\"mt-3 flex flex-wrap items-center gap-1.5 pl-(--row-indent) [--row-indent:2rem]\">\n <Popover open={datePopoverOpen} onOpenChange={setDatePopoverOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-label={\n hasDateSelected\n ? t(\"task_custom_date_selected_aria\", {\n date: dateBadgeAriaLabel,\n })\n : t(\"task_custom_date_aria\")\n }\n className={cn(\n \"flex shrink-0 items-center gap-1 rounded-full px-3 py-1 text-xs font-medium transition-colors\",\n hasDateSelected\n ? \"bg-primary text-primary-foreground\"\n : \"bg-muted text-muted-foreground hover:bg-muted/70\",\n )}\n >\n <CalendarIcon className=\"size-3\" aria-hidden=\"true\" />\n <span>{dateBadgeLabel}</span>\n {hasTimeSelected && (\n <span className=\"inline-flex items-center gap-0.5 text-current/80\">\n <Clock className=\"size-3\" aria-hidden=\"true\" />\n <span>{timeBadgeLabel}</span>\n </span>\n )}\n </button>\n </PopoverTrigger>\n <PopoverContent\n align=\"start\"\n className=\"bg-popover text-popover-foreground pointer-events-auto z-[9999] w-max max-w-[calc(100vw-2rem)] rounded-xl border p-3 shadow-lg\"\n >\n <h3 className=\"text-foreground max-w-full truncate px-1 text-sm font-semibold\">\n {dateBadgeLabel}\n </h3>\n <Separator className=\"bg-border my-3\" />\n <div className=\"min-w-0 space-y-1\">\n <QuickDateRow\n icon={Sun}\n label={t(\"quick_today\")}\n onSelect={() => selectDueDate(isoDate(0, labelNow))}\n />\n <QuickDateRow\n icon={Sunrise}\n label={t(\"quick_tomorrow\")}\n rightLabel={quickDates.tomorrowLabel}\n onSelect={() => selectDueDate(quickDates.tomorrow)}\n />\n <QuickDateRow\n icon={CalendarDays}\n label={t(\"task_next_week\")}\n rightLabel={quickDates.nextWeekLabel}\n onSelect={() => selectDueDate(quickDates.nextWeek)}\n />\n <QuickDateRow\n icon={CircleOff}\n label={t(\"task_no_date\")}\n onSelect={clearDueDate}\n />\n </div>\n <Separator className=\"bg-border my-3\" />\n <div>\n <p className=\"text-muted-foreground px-1 text-xs font-semibold\">\n {t(\"task_custom_calendar\")}\n </p>\n <Calendar\n mode=\"single\"\n formatters={calendarFormatters}\n labels={calendarLabels}\n disabled={{ before: todayLocalMidnight }}\n onSelect={(date) => {\n if (!date) return;\n\n const selectedDate = startOfLocalDay(date);\n if (selectedDate.getTime() < todayLocalMidnight.getTime()) {\n return;\n }\n\n selectDueDate(isoDate(0, selectedDate));\n }}\n className=\"p-0 pt-2\"\n classNames={{\n cell: \"h-9 w-9 p-0 text-center text-sm focus-within:relative focus-within:z-20\",\n day_selected:\n \"rounded-md bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground\",\n }}\n initialFocus\n defaultMonth={calendarDefaultMonth}\n {...(selectedCalendarDate\n ? {\n selected: selectedCalendarDate,\n }\n : {})}\n />\n </div>\n <Separator className=\"bg-border my-3\" />\n <div className=\"flex items-center justify-between gap-4 px-1\">\n <label\n htmlFor={timeInputId}\n className=\"text-muted-foreground text-xs font-semibold\"\n >\n {t(\"task_time_label\")}\n </label>\n <div className=\"border-input bg-background text-foreground focus-within:ring-ring flex h-9 items-center gap-2 rounded-md border px-2 focus-within:ring-2\">\n <Clock\n className=\"text-muted-foreground size-3.5 shrink-0\"\n aria-hidden=\"true\"\n />\n <input\n id={timeInputId}\n type=\"time\"\n value={dueTime}\n onChange={(event) => handleTimeChange(event.target.value)}\n aria-label={t(\"task_time_aria\")}\n className=\"h-full border-0 bg-transparent p-0 text-right text-sm outline-none [&::-webkit-calendar-picker-indicator]:hidden\"\n />\n </div>\n </div>\n </PopoverContent>\n </Popover>\n {metadataControls}\n <button\n type=\"button\"\n onClick={submit}\n disabled={!canSubmit}\n className=\"bg-primary text-primary-foreground hover:bg-primary/90 disabled:bg-muted disabled:text-muted-foreground mt-1 -ml-(--row-indent) inline-flex h-10 w-[calc(100%+var(--row-indent))] items-center justify-center rounded-lg text-sm font-semibold transition-colors disabled:cursor-not-allowed sm:mt-0 sm:ml-auto sm:h-auto sm:w-auto sm:shrink-0 sm:gap-1.5 sm:rounded-full sm:px-4 sm:py-1.5 sm:text-xs\"\n >\n {isSubmitting\n ? (submittingLabel ?? t(\"adding\"))\n : (submitLabel ?? t(\"add_task\"))}\n </button>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"task-composer-form-DDzxr6_A.cjs","names":["createTranslationContext","X","Popover","PopoverTrigger","cn","CalendarIcon","Clock","PopoverContent","Separator","Sun","Sunrise","CalendarDays","CircleOff","Calendar"],"sources":["../../../contacts/core/src/contacts-api-context.ts","../../../contacts/core/src/translation-api-context.ts","../../../contacts/core/src/parse-task-body.ts","../../../contacts/core/src/iso-date.ts","../../../contacts/ui/src/portal/utils/format-date.ts","../../../contacts/core/src/query-keys.ts","../../../contacts/core/src/hooks/use-infinite-contacts.ts","../../../contacts/ui/src/portal/components/tasks/task-composer-form.tsx"],"sourcesContent":["import { createContext, use, type Provider } from \"react\";\nimport type { ContactsApi } from \"./contacts-api\";\nimport type { NotesApi } from \"./notes-api\";\nimport type { TasksApi } from \"./tasks-api\";\nimport type { GroupsApi } from \"./groups-api\";\n\nexport interface ContactsDomainApi {\n contacts: ContactsApi;\n notes: NotesApi;\n tasks: TasksApi;\n groups?: GroupsApi;\n}\n\nconst ContactsApiContext = createContext<ContactsDomainApi | null>(null);\n\nexport const ContactsApiProvider: Provider<ContactsDomainApi | null> =\n ContactsApiContext.Provider;\n\nexport function useContactsDomainApi(): ContactsDomainApi {\n const api = use(ContactsApiContext);\n if (!api) {\n throw new Error(\n \"useContactsDomainApi must be used within a ContactsApiProvider\",\n );\n }\n return api;\n}\n\nexport function useContactsCrud(): ContactsApi {\n return useContactsDomainApi().contacts;\n}\n\nexport function useNotesApi(): NotesApi {\n return useContactsDomainApi().notes;\n}\n\nexport function useTasksApi(): TasksApi {\n return useContactsDomainApi().tasks;\n}\n\n/** Returns GroupsApi if the provider supplies one, otherwise null. */\nexport function useGroupsApi(): GroupsApi | null {\n return useContactsDomainApi().groups ?? null;\n}\n","import { use, type Provider } from \"react\";\nimport { createTranslationContext } from \"@fluid-app/i18n/translation-api-context-factory\";\nimport type { TranslationApi } from \"@fluid-app/i18n/translation-api\";\nimport type { ContactsDict } from \"./translation-dictionary\";\n\nconst {\n Context,\n Provider: ContactsProvider,\n useTranslation,\n} = createTranslationContext<ContactsDict>(\"Contacts\");\n\nexport const ContactsTranslationProvider: Provider<TranslationApi<ContactsDict> | null> =\n ContactsProvider;\nexport const useContactsTranslation = useTranslation;\n\n/**\n * Like `useContactsTranslation()` but returns `null` instead of throwing\n * when no `ContactsTranslationProvider` is present in the tree.\n * Useful for shared hooks consumed by both portal (has provider) and admin (no provider).\n */\nexport function useOptionalContactsTranslation(): TranslationApi<ContactsDict> | null {\n return use(Context);\n}\n","/**\n * Tasks store both a title (first line) and an optional body separated by a\n * blank line. This is the canonical convention used by the task editor and\n * by every consumer that displays tasks (contacts UI list, portal todo\n * widget). Drift across consumers would mean some surfaces show \"Title\\n\\n\n * body details\" verbatim while others split correctly — keep the delimiter\n * convention in one place.\n */\nexport function parseTaskBody(raw: string): { title: string; body: string } {\n const split = raw.indexOf(\"\\n\\n\");\n if (split >= 0) {\n return {\n title: raw.slice(0, split),\n body: raw.slice(split + 2),\n };\n }\n return { title: raw, body: \"\" };\n}\n","/**\n * Format a date as YYYY-MM-DD in the renderer's local timezone, optionally\n * shifted by `offsetDays`. Use this for due-date inputs where \"today\" must\n * resolve to the user's local calendar date — never `toISOString().slice(0, 10)`,\n * which returns the UTC date and silently rolls over a day for users east/west\n * of UTC at the wrong hours.\n */\nexport function isoDate(offsetDays: number, now: Date = new Date()): string {\n const d = new Date(now);\n d.setDate(d.getDate() + offsetDays);\n const yyyy = d.getFullYear();\n const mm = String(d.getMonth() + 1).padStart(2, \"0\");\n const dd = String(d.getDate()).padStart(2, \"0\");\n return `${yyyy}-${mm}-${dd}`;\n}\n\n/**\n * Return a Date pinned to local midnight of the calendar day represented by\n * `input`. Use this whenever you need to compare two due dates by calendar day\n * (overdue / today / tomorrow / future).\n *\n * Why not just `new Date(input)`? `new Date(\"YYYY-MM-DD\")` parses the string\n * as UTC midnight, which lands on the *previous* calendar day in any UTC−\n * timezone — a task due \"May 1\" then reads as April 30 for a user in the\n * Americas, classifying it as \"Overdue\" all day. Parse the date components\n * directly so the calendar-day intent of the string is preserved.\n */\nexport function startOfLocalDay(input: Date | string): Date {\n if (typeof input === \"string\") {\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})/.exec(input);\n if (match?.[1] && match[2] && match[3]) {\n return new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3]));\n }\n }\n const d = typeof input === \"string\" ? new Date(input) : input;\n return new Date(d.getFullYear(), d.getMonth(), d.getDate());\n}\n","import { isoDate, startOfLocalDay } from \"@fluid-app/contacts-core/iso-date\";\n\n/** Detect bare YYYY-MM-DD and ISO strings whose time is exactly midnight. */\nexport const ALL_DAY_PATTERN =\n /^\\d{4}-\\d{2}-\\d{2}(?:$|T00:00(?::00(?:\\.\\d+)?)?(?:[+-]\\d{2}:\\d{2}|Z)?)$/;\n\n/**\n * Detect non-Z ISO date-time strings that should stay on the timed path instead\n * of being classified as all-day. Editors may read the written date/time fields\n * directly. A trailing `Z` is intentionally excluded; UTC midnight values may\n * still be handled as all-day by ALL_DAY_PATTERN.\n */\nexport const LOCAL_TIMED_DUE_AT_PATTERN =\n /^\\d{4}-\\d{2}-\\d{2}T(\\d{2}):(\\d{2})(?::\\d{2}(?:\\.\\d+)?)?(?:[+-]\\d{2}:\\d{2})?$/;\n\nexport function isAllDay(dateStr: string): boolean {\n return ALL_DAY_PATTERN.test(dateStr);\n}\n\nexport function toDateInputValue(dueDate: string | null | undefined): string {\n if (!dueDate) return \"\";\n if (LOCAL_TIMED_DUE_AT_PATTERN.test(dueDate)) {\n return dueDate.slice(0, 10);\n }\n\n if (isAllDay(dueDate)) {\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})/.exec(dueDate);\n if (match?.[1] && match[2] && match[3])\n return `${match[1]}-${match[2]}-${match[3]}`;\n return \"\";\n }\n\n const d = new Date(dueDate);\n if (Number.isNaN(d.getTime())) return \"\";\n return isoDate(0, d);\n}\n\nexport function getLocalCalendarDayDiff(\n dateStr: string,\n now: Date = new Date(),\n): number | null {\n const date = startOfLocalDay(dateStr);\n if (Number.isNaN(date.getTime())) return null;\n\n const today = startOfLocalDay(now);\n const dateUtc = Date.UTC(date.getFullYear(), date.getMonth(), date.getDate());\n const todayUtc = Date.UTC(\n today.getFullYear(),\n today.getMonth(),\n today.getDate(),\n );\n\n return Math.round((dateUtc - todayUtc) / (1000 * 60 * 60 * 24));\n}\n\nexport function formatDateForDisplay(dateStr: string, locale?: string): string {\n const normalizedLocale = locale?.replace(/_/g, \"-\") ?? \"en-US\";\n // All-day / midnight values: preserve the represented calendar date\n // regardless of local timezone. Genuine timed instants are parsed with\n // new Date() so the locale string reflects the instant.\n const date = isAllDay(dateStr) ? startOfLocalDay(dateStr) : new Date(dateStr);\n return date.toLocaleDateString(normalizedLocale, {\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n });\n}\n","export const CONTACTS_QUERY_KEYS = {\n all: (prefix: string) => [prefix] as const,\n list: (prefix: string) =>\n [...CONTACTS_QUERY_KEYS.all(prefix), \"list\"] as const,\n detail: (prefix: string, id: string) =>\n [...CONTACTS_QUERY_KEYS.all(prefix), \"detail\", id] as const,\n} as const;\n\nexport const contactsKeys = {\n activities: (contactId: string) =>\n [\"portal-contacts\", \"activities\", contactId] as const,\n tasks: (contactId: string) =>\n [\"portal-contacts\", \"tasks\", contactId] as const,\n notes: (contactId: string) =>\n [\"portal-contacts\", \"notes\", contactId] as const,\n orders: (contactId: string) => [\"rep-contacts\", \"orders\", contactId] as const,\n subscriptionOrders: (contactId: string) =>\n [\"rep-contacts\", \"subscription-orders\", contactId] as const,\n groups: () => [\"portal-contacts\", \"groups\"] as const,\n groupMembers: (groupName: string) =>\n [\"portal-contacts\", \"group-members\", groupName] as const,\n groupAddSearch: (groupName: string, search: string) =>\n [\"portal-contacts\", \"group-add-search\", groupName, search] as const,\n} as const;\n","import { useInfiniteQuery } from \"@tanstack/react-query\";\nimport { useContactsCrud } from \"../contacts-api-context\";\nimport { CONTACTS_QUERY_KEYS } from \"../query-keys\";\n\nexport interface UseInfiniteContactsParams {\n search_query?: string;\n status?: string;\n sort_by?: string;\n sort_direction?: string;\n per_page?: number;\n tags?: string[];\n}\n\nexport function useInfiniteContacts(params: UseInfiniteContactsParams) {\n const api = useContactsCrud();\n return useInfiniteQuery({\n queryKey: [...CONTACTS_QUERY_KEYS.list(\"contacts\"), params],\n queryFn: ({ pageParam }) =>\n api.listContacts({\n ...params,\n page: pageParam,\n }),\n getNextPageParam: (lastPage) => {\n const currentPage = lastPage.meta.current_page;\n // Contacts API is page-number based; next_cursor and total_pages\n // are both used as \"has-next-page\" signals.\n if (currentPage == null) return undefined;\n if (lastPage.meta.next_cursor) return currentPage + 1;\n if (\n lastPage.meta.total_pages != null &&\n currentPage < lastPage.meta.total_pages\n ) {\n return currentPage + 1;\n }\n return undefined;\n },\n initialPageParam: 1,\n });\n}\n","\"use client\";\n\nimport React, { useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport {\n CalendarDays,\n CalendarIcon,\n CircleOff,\n Clock,\n Sunrise,\n Sun,\n X,\n type LucideIcon,\n} from \"lucide-react\";\nimport {\n Calendar,\n Popover,\n PopoverContent,\n PopoverTrigger,\n Separator,\n cn,\n type CalendarProps,\n} from \"@fluid-app/ui-primitives\";\nimport { isoDate, startOfLocalDay } from \"@fluid-app/contacts-core/iso-date\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport {\n formatDateForDisplay,\n getLocalCalendarDayDiff,\n isAllDay,\n LOCAL_TIMED_DUE_AT_PATTERN,\n toDateInputValue,\n} from \"../../utils/format-date\";\n\nconst RELATIVE_DATE_MAX_DAYS = 30;\nconst DEFAULT_DUE_TIME = \"12:00\";\nconst TIME_INPUT_PATTERN = /^(\\d{2}):(\\d{2})$/;\n\nfunction isValidTimeInput(timeValue: string): boolean {\n const match = TIME_INPUT_PATTERN.exec(timeValue);\n const hours = match?.[1] ? Number(match[1]) : Number.NaN;\n const minutes = match?.[2] ? Number(match[2]) : Number.NaN;\n\n return (\n Number.isInteger(hours) &&\n Number.isInteger(minutes) &&\n hours >= 0 &&\n hours <= 23 &&\n minutes >= 0 &&\n minutes <= 59\n );\n}\n\nfunction toTimeInputValue(dueDate: string | null | undefined): string {\n if (!dueDate) return \"\";\n\n const localTimedMatch = LOCAL_TIMED_DUE_AT_PATTERN.exec(dueDate);\n if (localTimedMatch?.[1] && localTimedMatch[2]) {\n const timeValue = `${localTimedMatch[1]}:${localTimedMatch[2]}`;\n return isValidTimeInput(timeValue) ? timeValue : \"\";\n }\n\n if (isAllDay(dueDate)) return \"\";\n\n const date = new Date(dueDate);\n if (Number.isNaN(date.getTime())) return \"\";\n\n return `${String(date.getHours()).padStart(2, \"0\")}:${String(\n date.getMinutes(),\n ).padStart(2, \"0\")}`;\n}\n\nfunction formatTimeForDisplay(timeValue: string, locale: string): string {\n const match = TIME_INPUT_PATTERN.exec(timeValue);\n const hours = match?.[1] ? Number(match[1]) : Number.NaN;\n const minutes = match?.[2] ? Number(match[2]) : Number.NaN;\n\n if (!isValidTimeInput(timeValue)) return timeValue;\n\n const date = new Date();\n date.setHours(hours, minutes, 0, 0);\n\n return new Intl.DateTimeFormat(locale, {\n hour: \"numeric\",\n minute: \"2-digit\",\n }).format(date);\n}\n\nfunction formatOffset(date: Date): string {\n const offsetMinutes = -date.getTimezoneOffset();\n const sign = offsetMinutes >= 0 ? \"+\" : \"-\";\n const absoluteOffset = Math.abs(offsetMinutes);\n const hours = String(Math.floor(absoluteOffset / 60)).padStart(2, \"0\");\n const minutes = String(absoluteOffset % 60).padStart(2, \"0\");\n\n return `${sign}${hours}:${minutes}`;\n}\n\nfunction composeDueAt(dateOnlyValue: string, timeValue: string): string | null {\n if (!dateOnlyValue) return null;\n if (isValidTimeInput(timeValue)) {\n const dateMatch = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(dateOnlyValue);\n const timeMatch = TIME_INPUT_PATTERN.exec(timeValue);\n if (\n dateMatch?.[1] &&\n dateMatch[2] &&\n dateMatch[3] &&\n timeMatch?.[1] &&\n timeMatch[2]\n ) {\n const localDate = new Date(\n Number(dateMatch[1]),\n Number(dateMatch[2]) - 1,\n Number(dateMatch[3]),\n Number(timeMatch[1]),\n Number(timeMatch[2]),\n 0,\n 0,\n );\n\n return `${dateOnlyValue}T${timeValue}:00${formatOffset(localDate)}`;\n }\n }\n\n return dateOnlyValue;\n}\n\ninterface QuickDateRowProps {\n icon: LucideIcon;\n label: string;\n rightLabel?: string;\n onSelect: () => void;\n}\n\nfunction QuickDateRow({\n icon: Icon,\n label,\n rightLabel,\n onSelect,\n}: QuickDateRowProps): React.JSX.Element {\n return (\n <button\n type=\"button\"\n onClick={onSelect}\n className=\"text-foreground hover:bg-accent hover:text-accent-foreground focus-visible:ring-ring flex w-full min-w-0 items-center gap-3 rounded-lg px-2 py-2 text-sm transition-colors outline-none focus-visible:ring-2\"\n >\n <Icon className=\"size-4 shrink-0\" aria-hidden=\"true\" />\n <span className=\"min-w-0 flex-1 truncate text-left font-medium\">\n {label}\n </span>\n {rightLabel && (\n <span className=\"ml-auto max-w-[50%] min-w-0 truncate text-right text-xs font-medium text-current/80\">\n {rightLabel}\n </span>\n )}\n </button>\n );\n}\n\nexport interface TaskComposerFormValues {\n body: string;\n due_at: string | null;\n}\n\nexport interface TaskComposerFormProps {\n /** Caller-controlled submit handler. */\n onSubmit: (values: TaskComposerFormValues) => void;\n /** Disable the submit button while the parent mutation is in flight. */\n isSubmitting?: boolean;\n /** Label for the submit button. Defaults to translated \"add_task\". */\n submitLabel?: string;\n /** Label shown while submitting. Defaults to translated \"adding\". */\n submittingLabel?: string;\n /** Optional initial body — used for edit mode. */\n initialBody?: string;\n /** Optional initial due date (ISO string) — used for edit mode. */\n initialDueAt?: string | null;\n /** Optional controls rendered after the date controls in the metadata row. */\n metadataControls?: React.ReactNode;\n /** When provided, an X button is rendered and Escape closes the form. */\n onClose?: () => void;\n /** Focus the body input on mount. Default true. */\n autoFocus?: boolean;\n}\n\nexport function TaskComposerForm({\n onSubmit,\n isSubmitting = false,\n submitLabel,\n submittingLabel,\n initialBody = \"\",\n initialDueAt = null,\n metadataControls,\n onClose,\n autoFocus = true,\n}: TaskComposerFormProps): React.JSX.Element {\n const { t, locale } = useContactsTranslation();\n const [body, setBody] = useState(initialBody);\n const [dueDate, setDueDate] = useState<string | null>(initialDueAt ?? null);\n const [dueTime, setDueTime] = useState(\n () => toTimeInputValue(initialDueAt) || DEFAULT_DUE_TIME,\n );\n const [dateTimeControlsChanged, setDateTimeControlsChanged] = useState(false);\n const [datePopoverOpen, setDatePopoverOpen] = useState(false);\n const [labelNow, setLabelNow] = useState(() => new Date());\n const timeInputId = useId();\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n useEffect(() => {\n if (autoFocus) inputRef.current?.focus();\n }, [autoFocus]);\n\n useEffect(() => {\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const scheduleNextMidnightUpdate = () => {\n const now = new Date();\n setLabelNow(now);\n\n const nextMidnight = new Date(now);\n nextMidnight.setHours(24, 0, 0, 0);\n\n timeoutId = setTimeout(\n scheduleNextMidnightUpdate,\n nextMidnight.getTime() - now.getTime(),\n );\n };\n\n scheduleNextMidnightUpdate();\n\n return () => {\n if (timeoutId != null) clearTimeout(timeoutId);\n };\n }, []);\n\n const dateOnlyValue = useMemo(() => toDateInputValue(dueDate), [dueDate]);\n const hasDateSelected = dateOnlyValue !== \"\";\n const hasInitialTimedDueAt = toTimeInputValue(initialDueAt) !== \"\";\n const hasTimeSelected =\n dueTime !== \"\" &&\n hasDateSelected &&\n (dateTimeControlsChanged || hasInitialTimedDueAt);\n const selectedCalendarDate = useMemo(\n () => (dateOnlyValue === \"\" ? undefined : startOfLocalDay(dateOnlyValue)),\n [dateOnlyValue],\n );\n const todayLocalMidnight = useMemo(\n () => startOfLocalDay(labelNow),\n [labelNow],\n );\n const normalizedLocale = useMemo(\n () => locale?.replace(/_/g, \"-\") ?? \"en-US\",\n [locale],\n );\n const calendarDefaultMonth = useMemo(() => {\n if (!selectedCalendarDate) return todayLocalMidnight;\n\n return selectedCalendarDate.getTime() < todayLocalMidnight.getTime()\n ? todayLocalMidnight\n : selectedCalendarDate;\n }, [selectedCalendarDate, todayLocalMidnight]);\n\n const quickDates = useMemo(() => {\n const tomorrow = isoDate(1, labelNow);\n const nextWeek = isoDate(7, labelNow);\n const weekdayFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n weekday: \"short\",\n });\n const nextWeekFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n weekday: \"short\",\n month: \"short\",\n day: \"numeric\",\n });\n\n return {\n tomorrow,\n tomorrowLabel: weekdayFormatter.format(startOfLocalDay(tomorrow)),\n nextWeek,\n nextWeekLabel: nextWeekFormatter.format(startOfLocalDay(nextWeek)),\n };\n }, [labelNow, normalizedLocale]);\n\n const calendarFormatters = useMemo<\n NonNullable<CalendarProps[\"formatters\"]>\n >(() => {\n const monthYearFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n month: \"long\",\n year: \"numeric\",\n });\n const monthFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n month: \"long\",\n });\n const yearFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n year: \"numeric\",\n });\n const dayFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n day: \"numeric\",\n });\n const weekdayFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n weekday: \"short\",\n });\n const weekNumberFormatter = new Intl.NumberFormat(normalizedLocale);\n\n return {\n formatCaption: (month) => monthYearFormatter.format(month),\n formatMonthCaption: (month) => monthFormatter.format(month),\n formatYearCaption: (year) => yearFormatter.format(year),\n formatDay: (day) => dayFormatter.format(day),\n formatWeekdayName: (weekday) => weekdayFormatter.format(weekday),\n formatWeekNumber: (weekNumber) => weekNumberFormatter.format(weekNumber),\n };\n }, [normalizedLocale]);\n\n const calendarLabels = useMemo<NonNullable<CalendarProps[\"labels\"]>>(() => {\n const dayLabelFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n weekday: \"long\",\n month: \"long\",\n day: \"numeric\",\n year: \"numeric\",\n });\n const weekdayLabelFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n weekday: \"long\",\n });\n const weekNumberFormatter = new Intl.NumberFormat(normalizedLocale);\n\n return {\n labelNext: () => t(\"calendar_next_month\"),\n labelPrevious: () => t(\"calendar_previous_month\"),\n labelMonthDropdown: () => t(\"calendar_month_dropdown\"),\n labelYearDropdown: () => t(\"calendar_year_dropdown\"),\n labelDay: (day) => dayLabelFormatter.format(day),\n labelWeekday: (weekday) => weekdayLabelFormatter.format(weekday),\n labelWeekNumber: (weekNumber) =>\n t(\"calendar_week_number\", {\n number: weekNumberFormatter.format(weekNumber),\n }),\n };\n }, [normalizedLocale, t]);\n\n const dateBadgeLabel = useMemo(() => {\n if (!hasDateSelected) return t(\"task_select_date\");\n\n const diffDays = getLocalCalendarDayDiff(dateOnlyValue, labelNow);\n if (diffDays === 0) return t(\"quick_today\");\n if (diffDays === 1) return t(\"quick_tomorrow\");\n if (\n diffDays != null &&\n diffDays >= 2 &&\n diffDays <= RELATIVE_DATE_MAX_DAYS\n ) {\n return t(\"task_due_in_days\", { count: diffDays });\n }\n\n return formatDateForDisplay(dateOnlyValue, normalizedLocale);\n }, [dateOnlyValue, hasDateSelected, labelNow, normalizedLocale, t]);\n\n const timeBadgeLabel = useMemo(\n () =>\n hasTimeSelected ? formatTimeForDisplay(dueTime, normalizedLocale) : \"\",\n [dueTime, hasTimeSelected, normalizedLocale],\n );\n const dateBadgeAriaLabel = hasTimeSelected\n ? `${dateBadgeLabel}, ${timeBadgeLabel}`\n : dateBadgeLabel;\n\n const submit = () => {\n const trimmed = body.trim();\n if (!trimmed || isSubmitting) return;\n\n onSubmit({\n body: trimmed,\n due_at: dateTimeControlsChanged\n ? composeDueAt(dateOnlyValue, dueTime)\n : (initialDueAt ?? null),\n });\n };\n\n const canSubmit = body.trim().length > 0 && !isSubmitting;\n\n const selectDueDate = (value: string) => {\n setDateTimeControlsChanged(true);\n setDueDate(value);\n setDueTime((currentTime) => currentTime || DEFAULT_DUE_TIME);\n };\n\n const clearDueDate = () => {\n setDateTimeControlsChanged(true);\n setDueDate(null);\n setDueTime(DEFAULT_DUE_TIME);\n setDatePopoverOpen(false);\n };\n\n const handleTimeChange = (value: string) => {\n setDateTimeControlsChanged(true);\n setDueTime(value);\n if (value && !hasDateSelected) setDueDate(isoDate(0, labelNow));\n };\n\n return (\n <div className=\"border-border/50 focus-within:border-foreground/30 rounded-xl border p-3 transition-colors\">\n <div className=\"flex items-start gap-3\">\n <div\n className=\"border-muted-foreground/50 mt-1.5 size-5 shrink-0 rounded-full border-2\"\n aria-hidden=\"true\"\n />\n <input\n ref={inputRef}\n value={body}\n onChange={(e) => setBody(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n submit();\n } else if (e.key === \"Escape\" && onClose) {\n e.preventDefault();\n onClose();\n }\n }}\n placeholder={t(\"task_describe_placeholder\")}\n aria-label={t(\"task_description_aria\")}\n className=\"placeholder:text-muted-foreground/80 text-foreground flex-1 border-0 bg-transparent text-sm font-medium outline-none pointer-coarse:text-base\"\n />\n {onClose && (\n <button\n type=\"button\"\n onClick={onClose}\n aria-label={t(\"task_discard_aria\")}\n className=\"text-muted-foreground hover:bg-muted hover:text-foreground -mt-0.5 -mr-0.5 flex size-7 shrink-0 items-center justify-center rounded-md transition-colors\"\n >\n <X className=\"size-4\" />\n </button>\n )}\n </div>\n\n {/* --row-indent aligns the date row with the input text above (size-5\n circle + gap-3 = 2rem). The mobile Add button cancels it via\n -ml-(--row-indent) + w-[calc(100%+var(--row-indent))] so the two\n values stay locked to a single source. */}\n <div className=\"mt-3 flex flex-wrap items-center gap-1.5 pl-(--row-indent) [--row-indent:2rem]\">\n <Popover open={datePopoverOpen} onOpenChange={setDatePopoverOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-label={\n hasDateSelected\n ? t(\"task_custom_date_selected_aria\", {\n date: dateBadgeAriaLabel,\n })\n : t(\"task_custom_date_aria\")\n }\n className={cn(\n \"flex shrink-0 items-center gap-1 rounded-full px-3 py-1 text-xs font-medium transition-colors\",\n hasDateSelected\n ? \"bg-primary text-primary-foreground\"\n : \"bg-muted text-muted-foreground hover:bg-muted/70\",\n )}\n >\n <CalendarIcon className=\"size-3\" aria-hidden=\"true\" />\n <span>{dateBadgeLabel}</span>\n {hasTimeSelected && (\n <span className=\"inline-flex items-center gap-0.5 text-current/80\">\n <Clock className=\"size-3\" aria-hidden=\"true\" />\n <span>{timeBadgeLabel}</span>\n </span>\n )}\n </button>\n </PopoverTrigger>\n <PopoverContent\n align=\"start\"\n className=\"bg-popover text-popover-foreground pointer-events-auto z-[9999] w-max max-w-[calc(100vw-2rem)] rounded-xl border p-3 shadow-lg\"\n >\n <h3 className=\"text-foreground max-w-full truncate px-1 text-sm font-semibold\">\n {dateBadgeLabel}\n </h3>\n <Separator className=\"bg-border my-3\" />\n <div className=\"min-w-0 space-y-1\">\n <QuickDateRow\n icon={Sun}\n label={t(\"quick_today\")}\n onSelect={() => selectDueDate(isoDate(0, labelNow))}\n />\n <QuickDateRow\n icon={Sunrise}\n label={t(\"quick_tomorrow\")}\n rightLabel={quickDates.tomorrowLabel}\n onSelect={() => selectDueDate(quickDates.tomorrow)}\n />\n <QuickDateRow\n icon={CalendarDays}\n label={t(\"task_next_week\")}\n rightLabel={quickDates.nextWeekLabel}\n onSelect={() => selectDueDate(quickDates.nextWeek)}\n />\n <QuickDateRow\n icon={CircleOff}\n label={t(\"task_no_date\")}\n onSelect={clearDueDate}\n />\n </div>\n <Separator className=\"bg-border my-3\" />\n <div>\n <p className=\"text-muted-foreground px-1 text-xs font-semibold\">\n {t(\"task_custom_calendar\")}\n </p>\n <Calendar\n mode=\"single\"\n formatters={calendarFormatters}\n labels={calendarLabels}\n disabled={{ before: todayLocalMidnight }}\n onSelect={(date) => {\n if (!date) return;\n\n const selectedDate = startOfLocalDay(date);\n if (selectedDate.getTime() < todayLocalMidnight.getTime()) {\n return;\n }\n\n selectDueDate(isoDate(0, selectedDate));\n }}\n className=\"p-0 pt-2\"\n classNames={{\n cell: \"h-9 w-9 p-0 text-center text-sm focus-within:relative focus-within:z-20\",\n day_selected:\n \"rounded-md bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground\",\n }}\n initialFocus\n defaultMonth={calendarDefaultMonth}\n {...(selectedCalendarDate\n ? {\n selected: selectedCalendarDate,\n }\n : {})}\n />\n </div>\n <Separator className=\"bg-border my-3\" />\n <div className=\"flex items-center justify-between gap-4 px-1\">\n <label\n htmlFor={timeInputId}\n className=\"text-muted-foreground text-xs font-semibold\"\n >\n {t(\"task_time_label\")}\n </label>\n <div className=\"border-input bg-background text-foreground focus-within:ring-ring flex h-9 items-center gap-2 rounded-md border px-2 focus-within:ring-2\">\n <Clock\n className=\"text-muted-foreground size-3.5 shrink-0\"\n aria-hidden=\"true\"\n />\n <input\n id={timeInputId}\n type=\"time\"\n value={dueTime}\n onChange={(event) => handleTimeChange(event.target.value)}\n aria-label={t(\"task_time_aria\")}\n className=\"h-full border-0 bg-transparent p-0 text-right text-sm outline-none [&::-webkit-calendar-picker-indicator]:hidden\"\n />\n </div>\n </div>\n </PopoverContent>\n </Popover>\n {metadataControls}\n <button\n type=\"button\"\n onClick={submit}\n disabled={!canSubmit}\n className=\"bg-primary text-primary-foreground hover:bg-primary/90 disabled:bg-muted disabled:text-muted-foreground mt-1 -ml-(--row-indent) inline-flex h-10 w-[calc(100%+var(--row-indent))] items-center justify-center rounded-lg text-sm font-semibold transition-colors disabled:cursor-not-allowed sm:mt-0 sm:ml-auto sm:h-auto sm:w-auto sm:shrink-0 sm:gap-1.5 sm:rounded-full sm:px-4 sm:py-1.5 sm:text-xs\"\n >\n {isSubmitting\n ? (submittingLabel ?? t(\"adding\"))\n : (submitLabel ?? t(\"add_task\"))}\n </button>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-composer-form-DTHeuJ9-.mjs","names":["Calendar"],"sources":["../../../contacts/core/src/contacts-api-context.ts","../../../contacts/core/src/translation-api-context.ts","../../../contacts/core/src/parse-task-body.ts","../../../contacts/core/src/iso-date.ts","../../../contacts/ui/src/portal/utils/format-date.ts","../../../contacts/core/src/query-keys.ts","../../../contacts/core/src/hooks/use-infinite-contacts.ts","../../../contacts/ui/src/portal/components/tasks/task-composer-form.tsx"],"sourcesContent":["import { createContext, use } from \"react\";\nimport type { ContactsApi } from \"./contacts-api\";\nimport type { NotesApi } from \"./notes-api\";\nimport type { TasksApi } from \"./tasks-api\";\nimport type { GroupsApi } from \"./groups-api\";\n\nexport interface ContactsDomainApi {\n contacts: ContactsApi;\n notes: NotesApi;\n tasks: TasksApi;\n groups?: GroupsApi;\n}\n\nconst ContactsApiContext = createContext<ContactsDomainApi | null>(null);\n\nexport const ContactsApiProvider = ContactsApiContext.Provider;\n\nexport function useContactsDomainApi(): ContactsDomainApi {\n const api = use(ContactsApiContext);\n if (!api) {\n throw new Error(\n \"useContactsDomainApi must be used within a ContactsApiProvider\",\n );\n }\n return api;\n}\n\nexport function useContactsCrud(): ContactsApi {\n return useContactsDomainApi().contacts;\n}\n\nexport function useNotesApi(): NotesApi {\n return useContactsDomainApi().notes;\n}\n\nexport function useTasksApi(): TasksApi {\n return useContactsDomainApi().tasks;\n}\n\n/** Returns GroupsApi if the provider supplies one, otherwise null. */\nexport function useGroupsApi(): GroupsApi | null {\n return useContactsDomainApi().groups ?? null;\n}\n","import { use, type Provider } from \"react\";\nimport { createTranslationContext } from \"@fluid-app/i18n/translation-api-context-factory\";\nimport type { TranslationApi } from \"@fluid-app/i18n/translation-api\";\nimport type { ContactsDict } from \"./translation-dictionary\";\n\nconst {\n Context,\n Provider: ContactsProvider,\n useTranslation,\n} = createTranslationContext<ContactsDict>(\"Contacts\");\n\nexport const ContactsTranslationProvider: Provider<TranslationApi<ContactsDict> | null> =\n ContactsProvider;\nexport const useContactsTranslation = useTranslation;\n\n/**\n * Like `useContactsTranslation()` but returns `null` instead of throwing\n * when no `ContactsTranslationProvider` is present in the tree.\n * Useful for shared hooks consumed by both portal (has provider) and admin (no provider).\n */\nexport function useOptionalContactsTranslation(): TranslationApi<ContactsDict> | null {\n return use(Context);\n}\n","/**\n * Tasks store both a title (first line) and an optional body separated by a\n * blank line. This is the canonical convention used by the task editor and\n * by every consumer that displays tasks (contacts UI list, portal todo\n * widget). Drift across consumers would mean some surfaces show \"Title\\n\\n\n * body details\" verbatim while others split correctly — keep the delimiter\n * convention in one place.\n */\nexport function parseTaskBody(raw: string): { title: string; body: string } {\n const split = raw.indexOf(\"\\n\\n\");\n if (split >= 0) {\n return {\n title: raw.slice(0, split),\n body: raw.slice(split + 2),\n };\n }\n return { title: raw, body: \"\" };\n}\n","/**\n * Format a date as YYYY-MM-DD in the renderer's local timezone, optionally\n * shifted by `offsetDays`. Use this for due-date inputs where \"today\" must\n * resolve to the user's local calendar date — never `toISOString().slice(0, 10)`,\n * which returns the UTC date and silently rolls over a day for users east/west\n * of UTC at the wrong hours.\n */\nexport function isoDate(offsetDays: number, now: Date = new Date()): string {\n const d = new Date(now);\n d.setDate(d.getDate() + offsetDays);\n const yyyy = d.getFullYear();\n const mm = String(d.getMonth() + 1).padStart(2, \"0\");\n const dd = String(d.getDate()).padStart(2, \"0\");\n return `${yyyy}-${mm}-${dd}`;\n}\n\n/**\n * Return a Date pinned to local midnight of the calendar day represented by\n * `input`. Use this whenever you need to compare two due dates by calendar day\n * (overdue / today / tomorrow / future).\n *\n * Why not just `new Date(input)`? `new Date(\"YYYY-MM-DD\")` parses the string\n * as UTC midnight, which lands on the *previous* calendar day in any UTC−\n * timezone — a task due \"May 1\" then reads as April 30 for a user in the\n * Americas, classifying it as \"Overdue\" all day. Parse the date components\n * directly so the calendar-day intent of the string is preserved.\n */\nexport function startOfLocalDay(input: Date | string): Date {\n if (typeof input === \"string\") {\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})/.exec(input);\n if (match?.[1] && match[2] && match[3]) {\n return new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3]));\n }\n }\n const d = typeof input === \"string\" ? new Date(input) : input;\n return new Date(d.getFullYear(), d.getMonth(), d.getDate());\n}\n","import { isoDate, startOfLocalDay } from \"@fluid-app/contacts-core/iso-date\";\n\n/** Detect bare YYYY-MM-DD and ISO strings whose time is exactly midnight. */\nexport const ALL_DAY_PATTERN =\n /^\\d{4}-\\d{2}-\\d{2}(?:$|T00:00(?::00(?:\\.\\d+)?)?(?:[+-]\\d{2}:\\d{2}|Z)?)$/;\n\n/**\n * Detect non-Z ISO date-time strings that should stay on the timed path instead\n * of being classified as all-day. Editors may read the written date/time fields\n * directly. A trailing `Z` is intentionally excluded; UTC midnight values may\n * still be handled as all-day by ALL_DAY_PATTERN.\n */\nexport const LOCAL_TIMED_DUE_AT_PATTERN =\n /^\\d{4}-\\d{2}-\\d{2}T(\\d{2}):(\\d{2})(?::\\d{2}(?:\\.\\d+)?)?(?:[+-]\\d{2}:\\d{2})?$/;\n\nexport function isAllDay(dateStr: string): boolean {\n return ALL_DAY_PATTERN.test(dateStr);\n}\n\nexport function toDateInputValue(dueDate: string | null | undefined): string {\n if (!dueDate) return \"\";\n if (LOCAL_TIMED_DUE_AT_PATTERN.test(dueDate)) {\n return dueDate.slice(0, 10);\n }\n\n if (isAllDay(dueDate)) {\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})/.exec(dueDate);\n if (match?.[1] && match[2] && match[3])\n return `${match[1]}-${match[2]}-${match[3]}`;\n return \"\";\n }\n\n const d = new Date(dueDate);\n if (Number.isNaN(d.getTime())) return \"\";\n return isoDate(0, d);\n}\n\nexport function getLocalCalendarDayDiff(\n dateStr: string,\n now: Date = new Date(),\n): number | null {\n const date = startOfLocalDay(dateStr);\n if (Number.isNaN(date.getTime())) return null;\n\n const today = startOfLocalDay(now);\n const dateUtc = Date.UTC(date.getFullYear(), date.getMonth(), date.getDate());\n const todayUtc = Date.UTC(\n today.getFullYear(),\n today.getMonth(),\n today.getDate(),\n );\n\n return Math.round((dateUtc - todayUtc) / (1000 * 60 * 60 * 24));\n}\n\nexport function formatDateForDisplay(dateStr: string, locale?: string): string {\n const normalizedLocale = locale?.replace(/_/g, \"-\") ?? \"en-US\";\n // All-day / midnight values: preserve the represented calendar date\n // regardless of local timezone. Genuine timed instants are parsed with\n // new Date() so the locale string reflects the instant.\n const date = isAllDay(dateStr) ? startOfLocalDay(dateStr) : new Date(dateStr);\n return date.toLocaleDateString(normalizedLocale, {\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n });\n}\n","export const CONTACTS_QUERY_KEYS = {\n all: (prefix: string) => [prefix] as const,\n list: (prefix: string) =>\n [...CONTACTS_QUERY_KEYS.all(prefix), \"list\"] as const,\n detail: (prefix: string, id: string) =>\n [...CONTACTS_QUERY_KEYS.all(prefix), \"detail\", id] as const,\n} as const;\n\nexport const contactsKeys = {\n activities: (contactId: string) =>\n [\"portal-contacts\", \"activities\", contactId] as const,\n tasks: (contactId: string) =>\n [\"portal-contacts\", \"tasks\", contactId] as const,\n notes: (contactId: string) =>\n [\"portal-contacts\", \"notes\", contactId] as const,\n orders: (contactId: string) => [\"rep-contacts\", \"orders\", contactId] as const,\n subscriptionOrders: (contactId: string) =>\n [\"rep-contacts\", \"subscription-orders\", contactId] as const,\n groups: () => [\"portal-contacts\", \"groups\"] as const,\n groupMembers: (groupName: string) =>\n [\"portal-contacts\", \"group-members\", groupName] as const,\n groupAddSearch: (groupName: string, search: string) =>\n [\"portal-contacts\", \"group-add-search\", groupName, search] as const,\n} as const;\n","import { useInfiniteQuery } from \"@tanstack/react-query\";\nimport { useContactsCrud } from \"../contacts-api-context\";\nimport { CONTACTS_QUERY_KEYS } from \"../query-keys\";\n\nexport interface UseInfiniteContactsParams {\n search_query?: string;\n status?: string;\n sort_by?: string;\n sort_direction?: string;\n per_page?: number;\n tags?: string[];\n}\n\nexport function useInfiniteContacts(params: UseInfiniteContactsParams) {\n const api = useContactsCrud();\n return useInfiniteQuery({\n queryKey: [...CONTACTS_QUERY_KEYS.list(\"contacts\"), params],\n queryFn: ({ pageParam }) =>\n api.listContacts({\n ...params,\n page: pageParam,\n }),\n getNextPageParam: (lastPage) => {\n const currentPage = lastPage.meta.current_page;\n // Contacts API is page-number based; next_cursor and total_pages\n // are both used as \"has-next-page\" signals.\n if (currentPage == null) return undefined;\n if (lastPage.meta.next_cursor) return currentPage + 1;\n if (\n lastPage.meta.total_pages != null &&\n currentPage < lastPage.meta.total_pages\n ) {\n return currentPage + 1;\n }\n return undefined;\n },\n initialPageParam: 1,\n });\n}\n","\"use client\";\n\nimport React, { useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport {\n CalendarDays,\n CalendarIcon,\n CircleOff,\n Clock,\n Sunrise,\n Sun,\n X,\n type LucideIcon,\n} from \"lucide-react\";\nimport {\n Calendar,\n Popover,\n PopoverContent,\n PopoverTrigger,\n Separator,\n cn,\n type CalendarProps,\n} from \"@fluid-app/ui-primitives\";\nimport { isoDate, startOfLocalDay } from \"@fluid-app/contacts-core/iso-date\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport {\n formatDateForDisplay,\n getLocalCalendarDayDiff,\n isAllDay,\n LOCAL_TIMED_DUE_AT_PATTERN,\n toDateInputValue,\n} from \"../../utils/format-date\";\n\nconst RELATIVE_DATE_MAX_DAYS = 30;\nconst DEFAULT_DUE_TIME = \"12:00\";\nconst TIME_INPUT_PATTERN = /^(\\d{2}):(\\d{2})$/;\n\nfunction isValidTimeInput(timeValue: string): boolean {\n const match = TIME_INPUT_PATTERN.exec(timeValue);\n const hours = match?.[1] ? Number(match[1]) : Number.NaN;\n const minutes = match?.[2] ? Number(match[2]) : Number.NaN;\n\n return (\n Number.isInteger(hours) &&\n Number.isInteger(minutes) &&\n hours >= 0 &&\n hours <= 23 &&\n minutes >= 0 &&\n minutes <= 59\n );\n}\n\nfunction toTimeInputValue(dueDate: string | null | undefined): string {\n if (!dueDate) return \"\";\n\n const localTimedMatch = LOCAL_TIMED_DUE_AT_PATTERN.exec(dueDate);\n if (localTimedMatch?.[1] && localTimedMatch[2]) {\n const timeValue = `${localTimedMatch[1]}:${localTimedMatch[2]}`;\n return isValidTimeInput(timeValue) ? timeValue : \"\";\n }\n\n if (isAllDay(dueDate)) return \"\";\n\n const date = new Date(dueDate);\n if (Number.isNaN(date.getTime())) return \"\";\n\n return `${String(date.getHours()).padStart(2, \"0\")}:${String(\n date.getMinutes(),\n ).padStart(2, \"0\")}`;\n}\n\nfunction formatTimeForDisplay(timeValue: string, locale: string): string {\n const match = TIME_INPUT_PATTERN.exec(timeValue);\n const hours = match?.[1] ? Number(match[1]) : Number.NaN;\n const minutes = match?.[2] ? Number(match[2]) : Number.NaN;\n\n if (!isValidTimeInput(timeValue)) return timeValue;\n\n const date = new Date();\n date.setHours(hours, minutes, 0, 0);\n\n return new Intl.DateTimeFormat(locale, {\n hour: \"numeric\",\n minute: \"2-digit\",\n }).format(date);\n}\n\nfunction formatOffset(date: Date): string {\n const offsetMinutes = -date.getTimezoneOffset();\n const sign = offsetMinutes >= 0 ? \"+\" : \"-\";\n const absoluteOffset = Math.abs(offsetMinutes);\n const hours = String(Math.floor(absoluteOffset / 60)).padStart(2, \"0\");\n const minutes = String(absoluteOffset % 60).padStart(2, \"0\");\n\n return `${sign}${hours}:${minutes}`;\n}\n\nfunction composeDueAt(dateOnlyValue: string, timeValue: string): string | null {\n if (!dateOnlyValue) return null;\n if (isValidTimeInput(timeValue)) {\n const dateMatch = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(dateOnlyValue);\n const timeMatch = TIME_INPUT_PATTERN.exec(timeValue);\n if (\n dateMatch?.[1] &&\n dateMatch[2] &&\n dateMatch[3] &&\n timeMatch?.[1] &&\n timeMatch[2]\n ) {\n const localDate = new Date(\n Number(dateMatch[1]),\n Number(dateMatch[2]) - 1,\n Number(dateMatch[3]),\n Number(timeMatch[1]),\n Number(timeMatch[2]),\n 0,\n 0,\n );\n\n return `${dateOnlyValue}T${timeValue}:00${formatOffset(localDate)}`;\n }\n }\n\n return dateOnlyValue;\n}\n\ninterface QuickDateRowProps {\n icon: LucideIcon;\n label: string;\n rightLabel?: string;\n onSelect: () => void;\n}\n\nfunction QuickDateRow({\n icon: Icon,\n label,\n rightLabel,\n onSelect,\n}: QuickDateRowProps): React.JSX.Element {\n return (\n <button\n type=\"button\"\n onClick={onSelect}\n className=\"text-foreground hover:bg-accent hover:text-accent-foreground focus-visible:ring-ring flex w-full min-w-0 items-center gap-3 rounded-lg px-2 py-2 text-sm transition-colors outline-none focus-visible:ring-2\"\n >\n <Icon className=\"size-4 shrink-0\" aria-hidden=\"true\" />\n <span className=\"min-w-0 flex-1 truncate text-left font-medium\">\n {label}\n </span>\n {rightLabel && (\n <span className=\"ml-auto max-w-[50%] min-w-0 truncate text-right text-xs font-medium text-current/80\">\n {rightLabel}\n </span>\n )}\n </button>\n );\n}\n\nexport interface TaskComposerFormValues {\n body: string;\n due_at: string | null;\n}\n\nexport interface TaskComposerFormProps {\n /** Caller-controlled submit handler. */\n onSubmit: (values: TaskComposerFormValues) => void;\n /** Disable the submit button while the parent mutation is in flight. */\n isSubmitting?: boolean;\n /** Label for the submit button. Defaults to translated \"add_task\". */\n submitLabel?: string;\n /** Label shown while submitting. Defaults to translated \"adding\". */\n submittingLabel?: string;\n /** Optional initial body — used for edit mode. */\n initialBody?: string;\n /** Optional initial due date (ISO string) — used for edit mode. */\n initialDueAt?: string | null;\n /** Optional controls rendered after the date controls in the metadata row. */\n metadataControls?: React.ReactNode;\n /** When provided, an X button is rendered and Escape closes the form. */\n onClose?: () => void;\n /** Focus the body input on mount. Default true. */\n autoFocus?: boolean;\n}\n\nexport function TaskComposerForm({\n onSubmit,\n isSubmitting = false,\n submitLabel,\n submittingLabel,\n initialBody = \"\",\n initialDueAt = null,\n metadataControls,\n onClose,\n autoFocus = true,\n}: TaskComposerFormProps): React.JSX.Element {\n const { t, locale } = useContactsTranslation();\n const [body, setBody] = useState(initialBody);\n const [dueDate, setDueDate] = useState<string | null>(initialDueAt ?? null);\n const [dueTime, setDueTime] = useState(\n () => toTimeInputValue(initialDueAt) || DEFAULT_DUE_TIME,\n );\n const [dateTimeControlsChanged, setDateTimeControlsChanged] = useState(false);\n const [datePopoverOpen, setDatePopoverOpen] = useState(false);\n const [labelNow, setLabelNow] = useState(() => new Date());\n const timeInputId = useId();\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n useEffect(() => {\n if (autoFocus) inputRef.current?.focus();\n }, [autoFocus]);\n\n useEffect(() => {\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const scheduleNextMidnightUpdate = () => {\n const now = new Date();\n setLabelNow(now);\n\n const nextMidnight = new Date(now);\n nextMidnight.setHours(24, 0, 0, 0);\n\n timeoutId = setTimeout(\n scheduleNextMidnightUpdate,\n nextMidnight.getTime() - now.getTime(),\n );\n };\n\n scheduleNextMidnightUpdate();\n\n return () => {\n if (timeoutId != null) clearTimeout(timeoutId);\n };\n }, []);\n\n const dateOnlyValue = useMemo(() => toDateInputValue(dueDate), [dueDate]);\n const hasDateSelected = dateOnlyValue !== \"\";\n const hasInitialTimedDueAt = toTimeInputValue(initialDueAt) !== \"\";\n const hasTimeSelected =\n dueTime !== \"\" &&\n hasDateSelected &&\n (dateTimeControlsChanged || hasInitialTimedDueAt);\n const selectedCalendarDate = useMemo(\n () => (dateOnlyValue === \"\" ? undefined : startOfLocalDay(dateOnlyValue)),\n [dateOnlyValue],\n );\n const todayLocalMidnight = useMemo(\n () => startOfLocalDay(labelNow),\n [labelNow],\n );\n const normalizedLocale = useMemo(\n () => locale?.replace(/_/g, \"-\") ?? \"en-US\",\n [locale],\n );\n const calendarDefaultMonth = useMemo(() => {\n if (!selectedCalendarDate) return todayLocalMidnight;\n\n return selectedCalendarDate.getTime() < todayLocalMidnight.getTime()\n ? todayLocalMidnight\n : selectedCalendarDate;\n }, [selectedCalendarDate, todayLocalMidnight]);\n\n const quickDates = useMemo(() => {\n const tomorrow = isoDate(1, labelNow);\n const nextWeek = isoDate(7, labelNow);\n const weekdayFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n weekday: \"short\",\n });\n const nextWeekFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n weekday: \"short\",\n month: \"short\",\n day: \"numeric\",\n });\n\n return {\n tomorrow,\n tomorrowLabel: weekdayFormatter.format(startOfLocalDay(tomorrow)),\n nextWeek,\n nextWeekLabel: nextWeekFormatter.format(startOfLocalDay(nextWeek)),\n };\n }, [labelNow, normalizedLocale]);\n\n const calendarFormatters = useMemo<\n NonNullable<CalendarProps[\"formatters\"]>\n >(() => {\n const monthYearFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n month: \"long\",\n year: \"numeric\",\n });\n const monthFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n month: \"long\",\n });\n const yearFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n year: \"numeric\",\n });\n const dayFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n day: \"numeric\",\n });\n const weekdayFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n weekday: \"short\",\n });\n const weekNumberFormatter = new Intl.NumberFormat(normalizedLocale);\n\n return {\n formatCaption: (month) => monthYearFormatter.format(month),\n formatMonthCaption: (month) => monthFormatter.format(month),\n formatYearCaption: (year) => yearFormatter.format(year),\n formatDay: (day) => dayFormatter.format(day),\n formatWeekdayName: (weekday) => weekdayFormatter.format(weekday),\n formatWeekNumber: (weekNumber) => weekNumberFormatter.format(weekNumber),\n };\n }, [normalizedLocale]);\n\n const calendarLabels = useMemo<NonNullable<CalendarProps[\"labels\"]>>(() => {\n const dayLabelFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n weekday: \"long\",\n month: \"long\",\n day: \"numeric\",\n year: \"numeric\",\n });\n const weekdayLabelFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n weekday: \"long\",\n });\n const weekNumberFormatter = new Intl.NumberFormat(normalizedLocale);\n\n return {\n labelNext: () => t(\"calendar_next_month\"),\n labelPrevious: () => t(\"calendar_previous_month\"),\n labelMonthDropdown: () => t(\"calendar_month_dropdown\"),\n labelYearDropdown: () => t(\"calendar_year_dropdown\"),\n labelDay: (day) => dayLabelFormatter.format(day),\n labelWeekday: (weekday) => weekdayLabelFormatter.format(weekday),\n labelWeekNumber: (weekNumber) =>\n t(\"calendar_week_number\", {\n number: weekNumberFormatter.format(weekNumber),\n }),\n };\n }, [normalizedLocale, t]);\n\n const dateBadgeLabel = useMemo(() => {\n if (!hasDateSelected) return t(\"task_select_date\");\n\n const diffDays = getLocalCalendarDayDiff(dateOnlyValue, labelNow);\n if (diffDays === 0) return t(\"quick_today\");\n if (diffDays === 1) return t(\"quick_tomorrow\");\n if (\n diffDays != null &&\n diffDays >= 2 &&\n diffDays <= RELATIVE_DATE_MAX_DAYS\n ) {\n return t(\"task_due_in_days\", { count: diffDays });\n }\n\n return formatDateForDisplay(dateOnlyValue, normalizedLocale);\n }, [dateOnlyValue, hasDateSelected, labelNow, normalizedLocale, t]);\n\n const timeBadgeLabel = useMemo(\n () =>\n hasTimeSelected ? formatTimeForDisplay(dueTime, normalizedLocale) : \"\",\n [dueTime, hasTimeSelected, normalizedLocale],\n );\n const dateBadgeAriaLabel = hasTimeSelected\n ? `${dateBadgeLabel}, ${timeBadgeLabel}`\n : dateBadgeLabel;\n\n const submit = () => {\n const trimmed = body.trim();\n if (!trimmed || isSubmitting) return;\n\n onSubmit({\n body: trimmed,\n due_at: dateTimeControlsChanged\n ? composeDueAt(dateOnlyValue, dueTime)\n : (initialDueAt ?? null),\n });\n };\n\n const canSubmit = body.trim().length > 0 && !isSubmitting;\n\n const selectDueDate = (value: string) => {\n setDateTimeControlsChanged(true);\n setDueDate(value);\n setDueTime((currentTime) => currentTime || DEFAULT_DUE_TIME);\n };\n\n const clearDueDate = () => {\n setDateTimeControlsChanged(true);\n setDueDate(null);\n setDueTime(DEFAULT_DUE_TIME);\n setDatePopoverOpen(false);\n };\n\n const handleTimeChange = (value: string) => {\n setDateTimeControlsChanged(true);\n setDueTime(value);\n if (value && !hasDateSelected) setDueDate(isoDate(0, labelNow));\n };\n\n return (\n <div className=\"border-border/50 focus-within:border-foreground/30 rounded-xl border p-3 transition-colors\">\n <div className=\"flex items-start gap-3\">\n <div\n className=\"border-muted-foreground/50 mt-1.5 size-5 shrink-0 rounded-full border-2\"\n aria-hidden=\"true\"\n />\n <input\n ref={inputRef}\n value={body}\n onChange={(e) => setBody(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n submit();\n } else if (e.key === \"Escape\" && onClose) {\n e.preventDefault();\n onClose();\n }\n }}\n placeholder={t(\"task_describe_placeholder\")}\n aria-label={t(\"task_description_aria\")}\n className=\"placeholder:text-muted-foreground/80 text-foreground flex-1 border-0 bg-transparent text-sm font-medium outline-none pointer-coarse:text-base\"\n />\n {onClose && (\n <button\n type=\"button\"\n onClick={onClose}\n aria-label={t(\"task_discard_aria\")}\n className=\"text-muted-foreground hover:bg-muted hover:text-foreground -mt-0.5 -mr-0.5 flex size-7 shrink-0 items-center justify-center rounded-md transition-colors\"\n >\n <X className=\"size-4\" />\n </button>\n )}\n </div>\n\n {/* --row-indent aligns the date row with the input text above (size-5\n circle + gap-3 = 2rem). The mobile Add button cancels it via\n -ml-(--row-indent) + w-[calc(100%+var(--row-indent))] so the two\n values stay locked to a single source. */}\n <div className=\"mt-3 flex flex-wrap items-center gap-1.5 pl-(--row-indent) [--row-indent:2rem]\">\n <Popover open={datePopoverOpen} onOpenChange={setDatePopoverOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-label={\n hasDateSelected\n ? t(\"task_custom_date_selected_aria\", {\n date: dateBadgeAriaLabel,\n })\n : t(\"task_custom_date_aria\")\n }\n className={cn(\n \"flex shrink-0 items-center gap-1 rounded-full px-3 py-1 text-xs font-medium transition-colors\",\n hasDateSelected\n ? \"bg-primary text-primary-foreground\"\n : \"bg-muted text-muted-foreground hover:bg-muted/70\",\n )}\n >\n <CalendarIcon className=\"size-3\" aria-hidden=\"true\" />\n <span>{dateBadgeLabel}</span>\n {hasTimeSelected && (\n <span className=\"inline-flex items-center gap-0.5 text-current/80\">\n <Clock className=\"size-3\" aria-hidden=\"true\" />\n <span>{timeBadgeLabel}</span>\n </span>\n )}\n </button>\n </PopoverTrigger>\n <PopoverContent\n align=\"start\"\n className=\"bg-popover text-popover-foreground pointer-events-auto z-[9999] w-max max-w-[calc(100vw-2rem)] rounded-xl border p-3 shadow-lg\"\n >\n <h3 className=\"text-foreground max-w-full truncate px-1 text-sm font-semibold\">\n {dateBadgeLabel}\n </h3>\n <Separator className=\"bg-border my-3\" />\n <div className=\"min-w-0 space-y-1\">\n <QuickDateRow\n icon={Sun}\n label={t(\"quick_today\")}\n onSelect={() => selectDueDate(isoDate(0, labelNow))}\n />\n <QuickDateRow\n icon={Sunrise}\n label={t(\"quick_tomorrow\")}\n rightLabel={quickDates.tomorrowLabel}\n onSelect={() => selectDueDate(quickDates.tomorrow)}\n />\n <QuickDateRow\n icon={CalendarDays}\n label={t(\"task_next_week\")}\n rightLabel={quickDates.nextWeekLabel}\n onSelect={() => selectDueDate(quickDates.nextWeek)}\n />\n <QuickDateRow\n icon={CircleOff}\n label={t(\"task_no_date\")}\n onSelect={clearDueDate}\n />\n </div>\n <Separator className=\"bg-border my-3\" />\n <div>\n <p className=\"text-muted-foreground px-1 text-xs font-semibold\">\n {t(\"task_custom_calendar\")}\n </p>\n <Calendar\n mode=\"single\"\n formatters={calendarFormatters}\n labels={calendarLabels}\n disabled={{ before: todayLocalMidnight }}\n onSelect={(date) => {\n if (!date) return;\n\n const selectedDate = startOfLocalDay(date);\n if (selectedDate.getTime() < todayLocalMidnight.getTime()) {\n return;\n }\n\n selectDueDate(isoDate(0, selectedDate));\n }}\n className=\"p-0 pt-2\"\n classNames={{\n cell: \"h-9 w-9 p-0 text-center text-sm focus-within:relative focus-within:z-20\",\n day_selected:\n \"rounded-md bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground\",\n }}\n initialFocus\n defaultMonth={calendarDefaultMonth}\n {...(selectedCalendarDate\n ? {\n selected: selectedCalendarDate,\n }\n : {})}\n />\n </div>\n <Separator className=\"bg-border my-3\" />\n <div className=\"flex items-center justify-between gap-4 px-1\">\n <label\n htmlFor={timeInputId}\n className=\"text-muted-foreground text-xs font-semibold\"\n >\n {t(\"task_time_label\")}\n </label>\n <div className=\"border-input bg-background text-foreground focus-within:ring-ring flex h-9 items-center gap-2 rounded-md border px-2 focus-within:ring-2\">\n <Clock\n className=\"text-muted-foreground size-3.5 shrink-0\"\n aria-hidden=\"true\"\n />\n <input\n id={timeInputId}\n type=\"time\"\n value={dueTime}\n onChange={(event) => handleTimeChange(event.target.value)}\n aria-label={t(\"task_time_aria\")}\n className=\"h-full border-0 bg-transparent p-0 text-right text-sm outline-none [&::-webkit-calendar-picker-indicator]:hidden\"\n />\n </div>\n </div>\n </PopoverContent>\n </Popover>\n {metadataControls}\n <button\n type=\"button\"\n onClick={submit}\n disabled={!canSubmit}\n className=\"bg-primary text-primary-foreground hover:bg-primary/90 disabled:bg-muted disabled:text-muted-foreground mt-1 -ml-(--row-indent) inline-flex h-10 w-[calc(100%+var(--row-indent))] items-center justify-center rounded-lg text-sm font-semibold transition-colors disabled:cursor-not-allowed sm:mt-0 sm:ml-auto sm:h-auto sm:w-auto sm:shrink-0 sm:gap-1.5 sm:rounded-full sm:px-4 sm:py-1.5 sm:text-xs\"\n >\n {isSubmitting\n ? (submittingLabel ?? t(\"adding\"))\n : (submitLabel ?? t(\"add_task\"))}\n </button>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"task-composer-form-DTHeuJ9-.mjs","names":["Calendar"],"sources":["../../../contacts/core/src/contacts-api-context.ts","../../../contacts/core/src/translation-api-context.ts","../../../contacts/core/src/parse-task-body.ts","../../../contacts/core/src/iso-date.ts","../../../contacts/ui/src/portal/utils/format-date.ts","../../../contacts/core/src/query-keys.ts","../../../contacts/core/src/hooks/use-infinite-contacts.ts","../../../contacts/ui/src/portal/components/tasks/task-composer-form.tsx"],"sourcesContent":["import { createContext, use, type Provider } from \"react\";\nimport type { ContactsApi } from \"./contacts-api\";\nimport type { NotesApi } from \"./notes-api\";\nimport type { TasksApi } from \"./tasks-api\";\nimport type { GroupsApi } from \"./groups-api\";\n\nexport interface ContactsDomainApi {\n contacts: ContactsApi;\n notes: NotesApi;\n tasks: TasksApi;\n groups?: GroupsApi;\n}\n\nconst ContactsApiContext = createContext<ContactsDomainApi | null>(null);\n\nexport const ContactsApiProvider: Provider<ContactsDomainApi | null> =\n ContactsApiContext.Provider;\n\nexport function useContactsDomainApi(): ContactsDomainApi {\n const api = use(ContactsApiContext);\n if (!api) {\n throw new Error(\n \"useContactsDomainApi must be used within a ContactsApiProvider\",\n );\n }\n return api;\n}\n\nexport function useContactsCrud(): ContactsApi {\n return useContactsDomainApi().contacts;\n}\n\nexport function useNotesApi(): NotesApi {\n return useContactsDomainApi().notes;\n}\n\nexport function useTasksApi(): TasksApi {\n return useContactsDomainApi().tasks;\n}\n\n/** Returns GroupsApi if the provider supplies one, otherwise null. */\nexport function useGroupsApi(): GroupsApi | null {\n return useContactsDomainApi().groups ?? null;\n}\n","import { use, type Provider } from \"react\";\nimport { createTranslationContext } from \"@fluid-app/i18n/translation-api-context-factory\";\nimport type { TranslationApi } from \"@fluid-app/i18n/translation-api\";\nimport type { ContactsDict } from \"./translation-dictionary\";\n\nconst {\n Context,\n Provider: ContactsProvider,\n useTranslation,\n} = createTranslationContext<ContactsDict>(\"Contacts\");\n\nexport const ContactsTranslationProvider: Provider<TranslationApi<ContactsDict> | null> =\n ContactsProvider;\nexport const useContactsTranslation = useTranslation;\n\n/**\n * Like `useContactsTranslation()` but returns `null` instead of throwing\n * when no `ContactsTranslationProvider` is present in the tree.\n * Useful for shared hooks consumed by both portal (has provider) and admin (no provider).\n */\nexport function useOptionalContactsTranslation(): TranslationApi<ContactsDict> | null {\n return use(Context);\n}\n","/**\n * Tasks store both a title (first line) and an optional body separated by a\n * blank line. This is the canonical convention used by the task editor and\n * by every consumer that displays tasks (contacts UI list, portal todo\n * widget). Drift across consumers would mean some surfaces show \"Title\\n\\n\n * body details\" verbatim while others split correctly — keep the delimiter\n * convention in one place.\n */\nexport function parseTaskBody(raw: string): { title: string; body: string } {\n const split = raw.indexOf(\"\\n\\n\");\n if (split >= 0) {\n return {\n title: raw.slice(0, split),\n body: raw.slice(split + 2),\n };\n }\n return { title: raw, body: \"\" };\n}\n","/**\n * Format a date as YYYY-MM-DD in the renderer's local timezone, optionally\n * shifted by `offsetDays`. Use this for due-date inputs where \"today\" must\n * resolve to the user's local calendar date — never `toISOString().slice(0, 10)`,\n * which returns the UTC date and silently rolls over a day for users east/west\n * of UTC at the wrong hours.\n */\nexport function isoDate(offsetDays: number, now: Date = new Date()): string {\n const d = new Date(now);\n d.setDate(d.getDate() + offsetDays);\n const yyyy = d.getFullYear();\n const mm = String(d.getMonth() + 1).padStart(2, \"0\");\n const dd = String(d.getDate()).padStart(2, \"0\");\n return `${yyyy}-${mm}-${dd}`;\n}\n\n/**\n * Return a Date pinned to local midnight of the calendar day represented by\n * `input`. Use this whenever you need to compare two due dates by calendar day\n * (overdue / today / tomorrow / future).\n *\n * Why not just `new Date(input)`? `new Date(\"YYYY-MM-DD\")` parses the string\n * as UTC midnight, which lands on the *previous* calendar day in any UTC−\n * timezone — a task due \"May 1\" then reads as April 30 for a user in the\n * Americas, classifying it as \"Overdue\" all day. Parse the date components\n * directly so the calendar-day intent of the string is preserved.\n */\nexport function startOfLocalDay(input: Date | string): Date {\n if (typeof input === \"string\") {\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})/.exec(input);\n if (match?.[1] && match[2] && match[3]) {\n return new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3]));\n }\n }\n const d = typeof input === \"string\" ? new Date(input) : input;\n return new Date(d.getFullYear(), d.getMonth(), d.getDate());\n}\n","import { isoDate, startOfLocalDay } from \"@fluid-app/contacts-core/iso-date\";\n\n/** Detect bare YYYY-MM-DD and ISO strings whose time is exactly midnight. */\nexport const ALL_DAY_PATTERN =\n /^\\d{4}-\\d{2}-\\d{2}(?:$|T00:00(?::00(?:\\.\\d+)?)?(?:[+-]\\d{2}:\\d{2}|Z)?)$/;\n\n/**\n * Detect non-Z ISO date-time strings that should stay on the timed path instead\n * of being classified as all-day. Editors may read the written date/time fields\n * directly. A trailing `Z` is intentionally excluded; UTC midnight values may\n * still be handled as all-day by ALL_DAY_PATTERN.\n */\nexport const LOCAL_TIMED_DUE_AT_PATTERN =\n /^\\d{4}-\\d{2}-\\d{2}T(\\d{2}):(\\d{2})(?::\\d{2}(?:\\.\\d+)?)?(?:[+-]\\d{2}:\\d{2})?$/;\n\nexport function isAllDay(dateStr: string): boolean {\n return ALL_DAY_PATTERN.test(dateStr);\n}\n\nexport function toDateInputValue(dueDate: string | null | undefined): string {\n if (!dueDate) return \"\";\n if (LOCAL_TIMED_DUE_AT_PATTERN.test(dueDate)) {\n return dueDate.slice(0, 10);\n }\n\n if (isAllDay(dueDate)) {\n const match = /^(\\d{4})-(\\d{2})-(\\d{2})/.exec(dueDate);\n if (match?.[1] && match[2] && match[3])\n return `${match[1]}-${match[2]}-${match[3]}`;\n return \"\";\n }\n\n const d = new Date(dueDate);\n if (Number.isNaN(d.getTime())) return \"\";\n return isoDate(0, d);\n}\n\nexport function getLocalCalendarDayDiff(\n dateStr: string,\n now: Date = new Date(),\n): number | null {\n const date = startOfLocalDay(dateStr);\n if (Number.isNaN(date.getTime())) return null;\n\n const today = startOfLocalDay(now);\n const dateUtc = Date.UTC(date.getFullYear(), date.getMonth(), date.getDate());\n const todayUtc = Date.UTC(\n today.getFullYear(),\n today.getMonth(),\n today.getDate(),\n );\n\n return Math.round((dateUtc - todayUtc) / (1000 * 60 * 60 * 24));\n}\n\nexport function formatDateForDisplay(dateStr: string, locale?: string): string {\n const normalizedLocale = locale?.replace(/_/g, \"-\") ?? \"en-US\";\n // All-day / midnight values: preserve the represented calendar date\n // regardless of local timezone. Genuine timed instants are parsed with\n // new Date() so the locale string reflects the instant.\n const date = isAllDay(dateStr) ? startOfLocalDay(dateStr) : new Date(dateStr);\n return date.toLocaleDateString(normalizedLocale, {\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n });\n}\n","export const CONTACTS_QUERY_KEYS = {\n all: (prefix: string) => [prefix] as const,\n list: (prefix: string) =>\n [...CONTACTS_QUERY_KEYS.all(prefix), \"list\"] as const,\n detail: (prefix: string, id: string) =>\n [...CONTACTS_QUERY_KEYS.all(prefix), \"detail\", id] as const,\n} as const;\n\nexport const contactsKeys = {\n activities: (contactId: string) =>\n [\"portal-contacts\", \"activities\", contactId] as const,\n tasks: (contactId: string) =>\n [\"portal-contacts\", \"tasks\", contactId] as const,\n notes: (contactId: string) =>\n [\"portal-contacts\", \"notes\", contactId] as const,\n orders: (contactId: string) => [\"rep-contacts\", \"orders\", contactId] as const,\n subscriptionOrders: (contactId: string) =>\n [\"rep-contacts\", \"subscription-orders\", contactId] as const,\n groups: () => [\"portal-contacts\", \"groups\"] as const,\n groupMembers: (groupName: string) =>\n [\"portal-contacts\", \"group-members\", groupName] as const,\n groupAddSearch: (groupName: string, search: string) =>\n [\"portal-contacts\", \"group-add-search\", groupName, search] as const,\n} as const;\n","import { useInfiniteQuery } from \"@tanstack/react-query\";\nimport { useContactsCrud } from \"../contacts-api-context\";\nimport { CONTACTS_QUERY_KEYS } from \"../query-keys\";\n\nexport interface UseInfiniteContactsParams {\n search_query?: string;\n status?: string;\n sort_by?: string;\n sort_direction?: string;\n per_page?: number;\n tags?: string[];\n}\n\nexport function useInfiniteContacts(params: UseInfiniteContactsParams) {\n const api = useContactsCrud();\n return useInfiniteQuery({\n queryKey: [...CONTACTS_QUERY_KEYS.list(\"contacts\"), params],\n queryFn: ({ pageParam }) =>\n api.listContacts({\n ...params,\n page: pageParam,\n }),\n getNextPageParam: (lastPage) => {\n const currentPage = lastPage.meta.current_page;\n // Contacts API is page-number based; next_cursor and total_pages\n // are both used as \"has-next-page\" signals.\n if (currentPage == null) return undefined;\n if (lastPage.meta.next_cursor) return currentPage + 1;\n if (\n lastPage.meta.total_pages != null &&\n currentPage < lastPage.meta.total_pages\n ) {\n return currentPage + 1;\n }\n return undefined;\n },\n initialPageParam: 1,\n });\n}\n","\"use client\";\n\nimport React, { useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport {\n CalendarDays,\n CalendarIcon,\n CircleOff,\n Clock,\n Sunrise,\n Sun,\n X,\n type LucideIcon,\n} from \"lucide-react\";\nimport {\n Calendar,\n Popover,\n PopoverContent,\n PopoverTrigger,\n Separator,\n cn,\n type CalendarProps,\n} from \"@fluid-app/ui-primitives\";\nimport { isoDate, startOfLocalDay } from \"@fluid-app/contacts-core/iso-date\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport {\n formatDateForDisplay,\n getLocalCalendarDayDiff,\n isAllDay,\n LOCAL_TIMED_DUE_AT_PATTERN,\n toDateInputValue,\n} from \"../../utils/format-date\";\n\nconst RELATIVE_DATE_MAX_DAYS = 30;\nconst DEFAULT_DUE_TIME = \"12:00\";\nconst TIME_INPUT_PATTERN = /^(\\d{2}):(\\d{2})$/;\n\nfunction isValidTimeInput(timeValue: string): boolean {\n const match = TIME_INPUT_PATTERN.exec(timeValue);\n const hours = match?.[1] ? Number(match[1]) : Number.NaN;\n const minutes = match?.[2] ? Number(match[2]) : Number.NaN;\n\n return (\n Number.isInteger(hours) &&\n Number.isInteger(minutes) &&\n hours >= 0 &&\n hours <= 23 &&\n minutes >= 0 &&\n minutes <= 59\n );\n}\n\nfunction toTimeInputValue(dueDate: string | null | undefined): string {\n if (!dueDate) return \"\";\n\n const localTimedMatch = LOCAL_TIMED_DUE_AT_PATTERN.exec(dueDate);\n if (localTimedMatch?.[1] && localTimedMatch[2]) {\n const timeValue = `${localTimedMatch[1]}:${localTimedMatch[2]}`;\n return isValidTimeInput(timeValue) ? timeValue : \"\";\n }\n\n if (isAllDay(dueDate)) return \"\";\n\n const date = new Date(dueDate);\n if (Number.isNaN(date.getTime())) return \"\";\n\n return `${String(date.getHours()).padStart(2, \"0\")}:${String(\n date.getMinutes(),\n ).padStart(2, \"0\")}`;\n}\n\nfunction formatTimeForDisplay(timeValue: string, locale: string): string {\n const match = TIME_INPUT_PATTERN.exec(timeValue);\n const hours = match?.[1] ? Number(match[1]) : Number.NaN;\n const minutes = match?.[2] ? Number(match[2]) : Number.NaN;\n\n if (!isValidTimeInput(timeValue)) return timeValue;\n\n const date = new Date();\n date.setHours(hours, minutes, 0, 0);\n\n return new Intl.DateTimeFormat(locale, {\n hour: \"numeric\",\n minute: \"2-digit\",\n }).format(date);\n}\n\nfunction formatOffset(date: Date): string {\n const offsetMinutes = -date.getTimezoneOffset();\n const sign = offsetMinutes >= 0 ? \"+\" : \"-\";\n const absoluteOffset = Math.abs(offsetMinutes);\n const hours = String(Math.floor(absoluteOffset / 60)).padStart(2, \"0\");\n const minutes = String(absoluteOffset % 60).padStart(2, \"0\");\n\n return `${sign}${hours}:${minutes}`;\n}\n\nfunction composeDueAt(dateOnlyValue: string, timeValue: string): string | null {\n if (!dateOnlyValue) return null;\n if (isValidTimeInput(timeValue)) {\n const dateMatch = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(dateOnlyValue);\n const timeMatch = TIME_INPUT_PATTERN.exec(timeValue);\n if (\n dateMatch?.[1] &&\n dateMatch[2] &&\n dateMatch[3] &&\n timeMatch?.[1] &&\n timeMatch[2]\n ) {\n const localDate = new Date(\n Number(dateMatch[1]),\n Number(dateMatch[2]) - 1,\n Number(dateMatch[3]),\n Number(timeMatch[1]),\n Number(timeMatch[2]),\n 0,\n 0,\n );\n\n return `${dateOnlyValue}T${timeValue}:00${formatOffset(localDate)}`;\n }\n }\n\n return dateOnlyValue;\n}\n\ninterface QuickDateRowProps {\n icon: LucideIcon;\n label: string;\n rightLabel?: string;\n onSelect: () => void;\n}\n\nfunction QuickDateRow({\n icon: Icon,\n label,\n rightLabel,\n onSelect,\n}: QuickDateRowProps): React.JSX.Element {\n return (\n <button\n type=\"button\"\n onClick={onSelect}\n className=\"text-foreground hover:bg-accent hover:text-accent-foreground focus-visible:ring-ring flex w-full min-w-0 items-center gap-3 rounded-lg px-2 py-2 text-sm transition-colors outline-none focus-visible:ring-2\"\n >\n <Icon className=\"size-4 shrink-0\" aria-hidden=\"true\" />\n <span className=\"min-w-0 flex-1 truncate text-left font-medium\">\n {label}\n </span>\n {rightLabel && (\n <span className=\"ml-auto max-w-[50%] min-w-0 truncate text-right text-xs font-medium text-current/80\">\n {rightLabel}\n </span>\n )}\n </button>\n );\n}\n\nexport interface TaskComposerFormValues {\n body: string;\n due_at: string | null;\n}\n\nexport interface TaskComposerFormProps {\n /** Caller-controlled submit handler. */\n onSubmit: (values: TaskComposerFormValues) => void;\n /** Disable the submit button while the parent mutation is in flight. */\n isSubmitting?: boolean;\n /** Label for the submit button. Defaults to translated \"add_task\". */\n submitLabel?: string;\n /** Label shown while submitting. Defaults to translated \"adding\". */\n submittingLabel?: string;\n /** Optional initial body — used for edit mode. */\n initialBody?: string;\n /** Optional initial due date (ISO string) — used for edit mode. */\n initialDueAt?: string | null;\n /** Optional controls rendered after the date controls in the metadata row. */\n metadataControls?: React.ReactNode;\n /** When provided, an X button is rendered and Escape closes the form. */\n onClose?: () => void;\n /** Focus the body input on mount. Default true. */\n autoFocus?: boolean;\n}\n\nexport function TaskComposerForm({\n onSubmit,\n isSubmitting = false,\n submitLabel,\n submittingLabel,\n initialBody = \"\",\n initialDueAt = null,\n metadataControls,\n onClose,\n autoFocus = true,\n}: TaskComposerFormProps): React.JSX.Element {\n const { t, locale } = useContactsTranslation();\n const [body, setBody] = useState(initialBody);\n const [dueDate, setDueDate] = useState<string | null>(initialDueAt ?? null);\n const [dueTime, setDueTime] = useState(\n () => toTimeInputValue(initialDueAt) || DEFAULT_DUE_TIME,\n );\n const [dateTimeControlsChanged, setDateTimeControlsChanged] = useState(false);\n const [datePopoverOpen, setDatePopoverOpen] = useState(false);\n const [labelNow, setLabelNow] = useState(() => new Date());\n const timeInputId = useId();\n const inputRef = useRef<HTMLInputElement | null>(null);\n\n useEffect(() => {\n if (autoFocus) inputRef.current?.focus();\n }, [autoFocus]);\n\n useEffect(() => {\n let timeoutId: ReturnType<typeof setTimeout> | null = null;\n\n const scheduleNextMidnightUpdate = () => {\n const now = new Date();\n setLabelNow(now);\n\n const nextMidnight = new Date(now);\n nextMidnight.setHours(24, 0, 0, 0);\n\n timeoutId = setTimeout(\n scheduleNextMidnightUpdate,\n nextMidnight.getTime() - now.getTime(),\n );\n };\n\n scheduleNextMidnightUpdate();\n\n return () => {\n if (timeoutId != null) clearTimeout(timeoutId);\n };\n }, []);\n\n const dateOnlyValue = useMemo(() => toDateInputValue(dueDate), [dueDate]);\n const hasDateSelected = dateOnlyValue !== \"\";\n const hasInitialTimedDueAt = toTimeInputValue(initialDueAt) !== \"\";\n const hasTimeSelected =\n dueTime !== \"\" &&\n hasDateSelected &&\n (dateTimeControlsChanged || hasInitialTimedDueAt);\n const selectedCalendarDate = useMemo(\n () => (dateOnlyValue === \"\" ? undefined : startOfLocalDay(dateOnlyValue)),\n [dateOnlyValue],\n );\n const todayLocalMidnight = useMemo(\n () => startOfLocalDay(labelNow),\n [labelNow],\n );\n const normalizedLocale = useMemo(\n () => locale?.replace(/_/g, \"-\") ?? \"en-US\",\n [locale],\n );\n const calendarDefaultMonth = useMemo(() => {\n if (!selectedCalendarDate) return todayLocalMidnight;\n\n return selectedCalendarDate.getTime() < todayLocalMidnight.getTime()\n ? todayLocalMidnight\n : selectedCalendarDate;\n }, [selectedCalendarDate, todayLocalMidnight]);\n\n const quickDates = useMemo(() => {\n const tomorrow = isoDate(1, labelNow);\n const nextWeek = isoDate(7, labelNow);\n const weekdayFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n weekday: \"short\",\n });\n const nextWeekFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n weekday: \"short\",\n month: \"short\",\n day: \"numeric\",\n });\n\n return {\n tomorrow,\n tomorrowLabel: weekdayFormatter.format(startOfLocalDay(tomorrow)),\n nextWeek,\n nextWeekLabel: nextWeekFormatter.format(startOfLocalDay(nextWeek)),\n };\n }, [labelNow, normalizedLocale]);\n\n const calendarFormatters = useMemo<\n NonNullable<CalendarProps[\"formatters\"]>\n >(() => {\n const monthYearFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n month: \"long\",\n year: \"numeric\",\n });\n const monthFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n month: \"long\",\n });\n const yearFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n year: \"numeric\",\n });\n const dayFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n day: \"numeric\",\n });\n const weekdayFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n weekday: \"short\",\n });\n const weekNumberFormatter = new Intl.NumberFormat(normalizedLocale);\n\n return {\n formatCaption: (month) => monthYearFormatter.format(month),\n formatMonthCaption: (month) => monthFormatter.format(month),\n formatYearCaption: (year) => yearFormatter.format(year),\n formatDay: (day) => dayFormatter.format(day),\n formatWeekdayName: (weekday) => weekdayFormatter.format(weekday),\n formatWeekNumber: (weekNumber) => weekNumberFormatter.format(weekNumber),\n };\n }, [normalizedLocale]);\n\n const calendarLabels = useMemo<NonNullable<CalendarProps[\"labels\"]>>(() => {\n const dayLabelFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n weekday: \"long\",\n month: \"long\",\n day: \"numeric\",\n year: \"numeric\",\n });\n const weekdayLabelFormatter = new Intl.DateTimeFormat(normalizedLocale, {\n weekday: \"long\",\n });\n const weekNumberFormatter = new Intl.NumberFormat(normalizedLocale);\n\n return {\n labelNext: () => t(\"calendar_next_month\"),\n labelPrevious: () => t(\"calendar_previous_month\"),\n labelMonthDropdown: () => t(\"calendar_month_dropdown\"),\n labelYearDropdown: () => t(\"calendar_year_dropdown\"),\n labelDay: (day) => dayLabelFormatter.format(day),\n labelWeekday: (weekday) => weekdayLabelFormatter.format(weekday),\n labelWeekNumber: (weekNumber) =>\n t(\"calendar_week_number\", {\n number: weekNumberFormatter.format(weekNumber),\n }),\n };\n }, [normalizedLocale, t]);\n\n const dateBadgeLabel = useMemo(() => {\n if (!hasDateSelected) return t(\"task_select_date\");\n\n const diffDays = getLocalCalendarDayDiff(dateOnlyValue, labelNow);\n if (diffDays === 0) return t(\"quick_today\");\n if (diffDays === 1) return t(\"quick_tomorrow\");\n if (\n diffDays != null &&\n diffDays >= 2 &&\n diffDays <= RELATIVE_DATE_MAX_DAYS\n ) {\n return t(\"task_due_in_days\", { count: diffDays });\n }\n\n return formatDateForDisplay(dateOnlyValue, normalizedLocale);\n }, [dateOnlyValue, hasDateSelected, labelNow, normalizedLocale, t]);\n\n const timeBadgeLabel = useMemo(\n () =>\n hasTimeSelected ? formatTimeForDisplay(dueTime, normalizedLocale) : \"\",\n [dueTime, hasTimeSelected, normalizedLocale],\n );\n const dateBadgeAriaLabel = hasTimeSelected\n ? `${dateBadgeLabel}, ${timeBadgeLabel}`\n : dateBadgeLabel;\n\n const submit = () => {\n const trimmed = body.trim();\n if (!trimmed || isSubmitting) return;\n\n onSubmit({\n body: trimmed,\n due_at: dateTimeControlsChanged\n ? composeDueAt(dateOnlyValue, dueTime)\n : (initialDueAt ?? null),\n });\n };\n\n const canSubmit = body.trim().length > 0 && !isSubmitting;\n\n const selectDueDate = (value: string) => {\n setDateTimeControlsChanged(true);\n setDueDate(value);\n setDueTime((currentTime) => currentTime || DEFAULT_DUE_TIME);\n };\n\n const clearDueDate = () => {\n setDateTimeControlsChanged(true);\n setDueDate(null);\n setDueTime(DEFAULT_DUE_TIME);\n setDatePopoverOpen(false);\n };\n\n const handleTimeChange = (value: string) => {\n setDateTimeControlsChanged(true);\n setDueTime(value);\n if (value && !hasDateSelected) setDueDate(isoDate(0, labelNow));\n };\n\n return (\n <div className=\"border-border/50 focus-within:border-foreground/30 rounded-xl border p-3 transition-colors\">\n <div className=\"flex items-start gap-3\">\n <div\n className=\"border-muted-foreground/50 mt-1.5 size-5 shrink-0 rounded-full border-2\"\n aria-hidden=\"true\"\n />\n <input\n ref={inputRef}\n value={body}\n onChange={(e) => setBody(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n submit();\n } else if (e.key === \"Escape\" && onClose) {\n e.preventDefault();\n onClose();\n }\n }}\n placeholder={t(\"task_describe_placeholder\")}\n aria-label={t(\"task_description_aria\")}\n className=\"placeholder:text-muted-foreground/80 text-foreground flex-1 border-0 bg-transparent text-sm font-medium outline-none pointer-coarse:text-base\"\n />\n {onClose && (\n <button\n type=\"button\"\n onClick={onClose}\n aria-label={t(\"task_discard_aria\")}\n className=\"text-muted-foreground hover:bg-muted hover:text-foreground -mt-0.5 -mr-0.5 flex size-7 shrink-0 items-center justify-center rounded-md transition-colors\"\n >\n <X className=\"size-4\" />\n </button>\n )}\n </div>\n\n {/* --row-indent aligns the date row with the input text above (size-5\n circle + gap-3 = 2rem). The mobile Add button cancels it via\n -ml-(--row-indent) + w-[calc(100%+var(--row-indent))] so the two\n values stay locked to a single source. */}\n <div className=\"mt-3 flex flex-wrap items-center gap-1.5 pl-(--row-indent) [--row-indent:2rem]\">\n <Popover open={datePopoverOpen} onOpenChange={setDatePopoverOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-label={\n hasDateSelected\n ? t(\"task_custom_date_selected_aria\", {\n date: dateBadgeAriaLabel,\n })\n : t(\"task_custom_date_aria\")\n }\n className={cn(\n \"flex shrink-0 items-center gap-1 rounded-full px-3 py-1 text-xs font-medium transition-colors\",\n hasDateSelected\n ? \"bg-primary text-primary-foreground\"\n : \"bg-muted text-muted-foreground hover:bg-muted/70\",\n )}\n >\n <CalendarIcon className=\"size-3\" aria-hidden=\"true\" />\n <span>{dateBadgeLabel}</span>\n {hasTimeSelected && (\n <span className=\"inline-flex items-center gap-0.5 text-current/80\">\n <Clock className=\"size-3\" aria-hidden=\"true\" />\n <span>{timeBadgeLabel}</span>\n </span>\n )}\n </button>\n </PopoverTrigger>\n <PopoverContent\n align=\"start\"\n className=\"bg-popover text-popover-foreground pointer-events-auto z-[9999] w-max max-w-[calc(100vw-2rem)] rounded-xl border p-3 shadow-lg\"\n >\n <h3 className=\"text-foreground max-w-full truncate px-1 text-sm font-semibold\">\n {dateBadgeLabel}\n </h3>\n <Separator className=\"bg-border my-3\" />\n <div className=\"min-w-0 space-y-1\">\n <QuickDateRow\n icon={Sun}\n label={t(\"quick_today\")}\n onSelect={() => selectDueDate(isoDate(0, labelNow))}\n />\n <QuickDateRow\n icon={Sunrise}\n label={t(\"quick_tomorrow\")}\n rightLabel={quickDates.tomorrowLabel}\n onSelect={() => selectDueDate(quickDates.tomorrow)}\n />\n <QuickDateRow\n icon={CalendarDays}\n label={t(\"task_next_week\")}\n rightLabel={quickDates.nextWeekLabel}\n onSelect={() => selectDueDate(quickDates.nextWeek)}\n />\n <QuickDateRow\n icon={CircleOff}\n label={t(\"task_no_date\")}\n onSelect={clearDueDate}\n />\n </div>\n <Separator className=\"bg-border my-3\" />\n <div>\n <p className=\"text-muted-foreground px-1 text-xs font-semibold\">\n {t(\"task_custom_calendar\")}\n </p>\n <Calendar\n mode=\"single\"\n formatters={calendarFormatters}\n labels={calendarLabels}\n disabled={{ before: todayLocalMidnight }}\n onSelect={(date) => {\n if (!date) return;\n\n const selectedDate = startOfLocalDay(date);\n if (selectedDate.getTime() < todayLocalMidnight.getTime()) {\n return;\n }\n\n selectDueDate(isoDate(0, selectedDate));\n }}\n className=\"p-0 pt-2\"\n classNames={{\n cell: \"h-9 w-9 p-0 text-center text-sm focus-within:relative focus-within:z-20\",\n day_selected:\n \"rounded-md bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground\",\n }}\n initialFocus\n defaultMonth={calendarDefaultMonth}\n {...(selectedCalendarDate\n ? {\n selected: selectedCalendarDate,\n }\n : {})}\n />\n </div>\n <Separator className=\"bg-border my-3\" />\n <div className=\"flex items-center justify-between gap-4 px-1\">\n <label\n htmlFor={timeInputId}\n className=\"text-muted-foreground text-xs font-semibold\"\n >\n {t(\"task_time_label\")}\n </label>\n <div className=\"border-input bg-background text-foreground focus-within:ring-ring flex h-9 items-center gap-2 rounded-md border px-2 focus-within:ring-2\">\n <Clock\n className=\"text-muted-foreground size-3.5 shrink-0\"\n aria-hidden=\"true\"\n />\n <input\n id={timeInputId}\n type=\"time\"\n value={dueTime}\n onChange={(event) => handleTimeChange(event.target.value)}\n aria-label={t(\"task_time_aria\")}\n className=\"h-full border-0 bg-transparent p-0 text-right text-sm outline-none [&::-webkit-calendar-picker-indicator]:hidden\"\n />\n </div>\n </div>\n </PopoverContent>\n </Popover>\n {metadataControls}\n <button\n type=\"button\"\n onClick={submit}\n disabled={!canSubmit}\n className=\"bg-primary text-primary-foreground hover:bg-primary/90 disabled:bg-muted disabled:text-muted-foreground mt-1 -ml-(--row-indent) inline-flex h-10 w-[calc(100%+var(--row-indent))] items-center justify-center rounded-lg text-sm font-semibold transition-colors disabled:cursor-not-allowed sm:mt-0 sm:ml-auto sm:h-auto sm:w-auto sm:shrink-0 sm:gap-1.5 sm:rounded-full sm:px-4 sm:py-1.5 sm:text-xs\"\n >\n {isSubmitting\n ? (submittingLabel ?? t(\"adding\"))\n : (submitLabel ?? t(\"add_task\"))}\n </button>\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -5,6 +5,21 @@ var th_default = {
|
|
|
5
5
|
active: "ใช้งาน",
|
|
6
6
|
all: "ทั้งหมด",
|
|
7
7
|
amount: "จำนวนเงิน",
|
|
8
|
+
auto_apply_points_bundle_body: "สมดุลเหล่านี้ต่ออายุในวันเดียวกันและถูกเรียกเก็บเป็นคำสั่งเดียว",
|
|
9
|
+
auto_apply_points_bundle_cancel: "ยกเลิก",
|
|
10
|
+
auto_apply_points_bundle_confirm_all: "ใช้สำหรับทั้งหมด",
|
|
11
|
+
auto_apply_points_bundle_confirm_all_off: "ปิดใช้งานสำหรับทั้งหมด",
|
|
12
|
+
auto_apply_points_bundle_confirm_one: "เฉพาะอันนี้",
|
|
13
|
+
auto_apply_points_bundle_conflict_retry: "กลุ่มการต่ออายุนี้กำลังอัปเดตในที่อื่น โปรดลองอีกครั้ง",
|
|
14
|
+
auto_apply_points_bundle_member_paused: "{{name}} (หยุดชั่วคราว)",
|
|
15
|
+
auto_apply_points_bundle_membership_changed: "กลุ่มการต่ออายุนี้เปลี่ยนแปลงขณะบันทึก ดังนั้นสมดุลที่อัปเดตอาจไม่ตรงกับที่คุณยืนยัน เปิดกลุ่มใหม่เพื่อดูการตั้งค่าปัจจุบัน",
|
|
16
|
+
auto_apply_points_bundle_split_warning: "การเลือกต่างกันสำหรับสมดุลหนึ่งอาจทำให้ต่ออายุเป็นคำสั่งของตัวเอง ค่าจัดส่งจะถูกคำนวณแยกต่างหาก และอาจเป็นไปได้ว่าจะไม่เสียค่าจัดส่ง และวิธีการชำระเงินของแต่ละคำสั่งอาจเปลี่ยนแปลง",
|
|
17
|
+
auto_apply_points_bundle_title: "ใช้ {{label}} สำหรับกลุ่มการต่ออายุนี้หรือไม่?",
|
|
18
|
+
auto_apply_points_bundle_title_off: "หยุดการใช้ {{label}} สำหรับกลุ่มการต่ออายุนี้หรือไม่?",
|
|
19
|
+
auto_apply_points_each_renewal: "ใช้ {{label}} โดยอัตโนมัติในการต่ออายุแต่ละครั้ง",
|
|
20
|
+
auto_apply_points_partial_balance: "หากยอดคงเหลือไม่เพียงพอสำหรับการต่ออายุเต็มจำนวน เราจะใช้เงินที่มีอยู่",
|
|
21
|
+
auto_apply_points_saved_but_not_refreshed: "บันทึกการตั้งค่า {{label}} โดยอัตโนมัติแล้ว แต่ไม่สามารถรีเฟรชหน้านี้ได้ โปรดโหลดใหม่เพื่อดูการตั้งค่าปัจจุบัน",
|
|
22
|
+
auto_apply_points_updated: "อัปเดต {{label}} โดยอัตโนมัติแล้ว",
|
|
8
23
|
bill_date_error: "ไม่สามารถอัปเดตวันที่ออกบิลได้ โปรดลองวันที่อื่น",
|
|
9
24
|
bill_date_preview_prefix: "บิลครั้งถัดไปของคุณจะออกในวันที่",
|
|
10
25
|
bill_date_preview_suffix: ".",
|
|
@@ -91,6 +106,7 @@ var th_default = {
|
|
|
91
106
|
failed_to_reactivate: "ไม่สามารถเปิดใช้งานสมาชิกใหม่ได้",
|
|
92
107
|
failed_to_resume: "ไม่สามารถ恢復สมาชิกได้",
|
|
93
108
|
failed_to_skip: "ไม่สามารถข้ามการออกบิลได้",
|
|
109
|
+
failed_to_update_auto_apply_points: "ไม่สามารถอัปเดตการตั้งค่า {{label}} โดยอัตโนมัติได้",
|
|
94
110
|
failed_to_update_bill_date: "ไม่สามารถอัปเดตวันที่ออกบิลได้",
|
|
95
111
|
failed_to_update_quantity: "ไม่สามารถอัปเดตจำนวนได้",
|
|
96
112
|
generic_error: "เกิดข้อผิดพลาด โปรดลองอีกครั้ง",
|
|
@@ -267,4 +283,4 @@ var th_default = {
|
|
|
267
283
|
//#endregion
|
|
268
284
|
export { th_default as default };
|
|
269
285
|
|
|
270
|
-
//# sourceMappingURL=th-
|
|
286
|
+
//# sourceMappingURL=th-Cvw1o6oJ.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"th-Cvw1o6oJ.mjs","names":[],"sources":["../../../subscriptions/core/src/locale/th.json"],"sourcesContent":[""],"mappings":""}
|