modals.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import { useEffect, useRef } from 'react';
  2. import { useTranslation } from 'react-i18next';
  3. import { View } from 'app/design/view';
  4. import { Modal } from 'app/design/controls';
  5. import { useBottomSheetData } from 'app/context/bottomsheet';
  6. import Confirm from 'app/ui/molecules/dialogs/confirm';
  7. import Msg from 'app/ui/molecules/dialogs/msg';
  8. import FormModal from 'app/ui/molecules/dialogs/form-modal';
  9. import { BlockByDataInt as BlockByData } from 'app/components/block';
  10. import Stripe from 'app/ui/molecules/integrations/stripe';
  11. import { useGrid } from './context';
  12. /**
  13. * Overlay dialogs for the grid: bottom sheet form, Stripe/credits checkout,
  14. * confirm, and calculated-time / error messages.
  15. *
  16. * Actions only put data into the store; JSX lives here.
  17. */
  18. export default function GridModals() {
  19. const { t } = useTranslation();
  20. const { setBottomSheetData } = useBottomSheetData();
  21. const openedRef = useRef(false);
  22. const sheetBlock = useGrid((state) => state.sheetBlock);
  23. const formBlock = useGrid((state) => state.formBlock);
  24. const stripeCheckout = useGrid((state) => state.stripeCheckout);
  25. const pageData = useGrid((state) => state.pageData);
  26. const confirm = useGrid((state) => state.confirm);
  27. const message = useGrid((state) => state.message);
  28. const closeAll = useGrid((state) => state.closeAll);
  29. const closeStripe = useGrid((state) => state.closeStripe);
  30. const closeAndReload = useGrid((state) => state.closeAndReload);
  31. const handlePageModalData = useGrid((state) => state.handlePageModalData);
  32. const cancelConfirm = useGrid((state) => state.cancelConfirm);
  33. const acceptConfirm = useGrid((state) => state.acceptConfirm);
  34. const hideMessage = useGrid((state) => state.hideMessage);
  35. /**
  36. * The sheet mirrors `sheetBlock`. Closing is guarded by `openedRef` so that
  37. * mounting a grid never dismisses a sheet opened by another component.
  38. */
  39. useEffect(() => {
  40. if (sheetBlock) {
  41. openedRef.current = true;
  42. setBottomSheetData({
  43. title: sheetBlock.title,
  44. content: (
  45. <View className="px-1">
  46. <BlockByData
  47. onFormEmpty={() => closeAndReload()}
  48. block={sheetBlock.block}
  49. />
  50. </View>
  51. ),
  52. });
  53. return;
  54. }
  55. if (openedRef.current) {
  56. openedRef.current = false;
  57. setBottomSheetData(false);
  58. }
  59. }, [sheetBlock, setBottomSheetData, closeAndReload]);
  60. return (
  61. <>
  62. {formBlock ? (
  63. <Modal title={formBlock.content[0]?.title ? formBlock.content[0]?.title : " "} onVisible={!!formBlock} onClose={() => closeAll()}>
  64. <View className='px-4'>
  65. <BlockByData onFormEmpty={() => closeAndReload()} block={formBlock} />
  66. </View>
  67. </Modal>
  68. ) : null}
  69. {stripeCheckout ? (
  70. <Modal scrollable title={t('Checkout')} onVisible={!!stripeCheckout} onClose={() => closeStripe()}>
  71. <View className='px-4'>
  72. <Stripe
  73. payment_type={stripeCheckout.payment_type}
  74. seller_id={stripeCheckout.seller_id}
  75. items={stripeCheckout.items}
  76. />
  77. </View>
  78. </Modal>
  79. ) : null}
  80. <FormModal pageData={pageData} setPageData={handlePageModalData} url={pageData?.url} />
  81. <Confirm onVisible={confirm.show} title={t("Are you sure?")} handleCancel={cancelConfirm} handleOk={acceptConfirm} />
  82. <Msg
  83. onVisible={!!message}
  84. title={message}
  85. text={message}
  86. handleOk={hideMessage}
  87. />
  88. </>
  89. );
  90. }