CustomizeLayoutSetting.tsx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. import React, { type JSX, useCallback, useEffect, useState } from 'react';
  2. import { LoadingSpinner } from '@growi/ui/dist/components';
  3. import { useTranslation } from 'next-i18next';
  4. import { toastError, toastSuccess } from '~/client/util/toastr';
  5. import { useSWRxLayoutSetting } from '~/stores/admin/customize';
  6. import { useNextThemes } from '~/stores-universal/use-next-themes';
  7. const useIsContainerFluid = () => {
  8. const { data: layoutSetting, update: updateLayoutSetting } =
  9. useSWRxLayoutSetting();
  10. const [isContainerFluid, setIsContainerFluid] = useState<boolean>();
  11. useEffect(() => {
  12. setIsContainerFluid(layoutSetting?.isContainerFluid);
  13. }, [layoutSetting?.isContainerFluid]);
  14. return {
  15. isContainerFluid,
  16. setIsContainerFluid,
  17. updateLayoutSetting,
  18. };
  19. };
  20. const CustomizeLayoutSetting = (): JSX.Element => {
  21. const { t } = useTranslation('admin');
  22. const { resolvedTheme } = useNextThemes();
  23. const { isContainerFluid, setIsContainerFluid, updateLayoutSetting } =
  24. useIsContainerFluid();
  25. const onClickSubmit = useCallback(async () => {
  26. if (isContainerFluid == null) {
  27. return;
  28. }
  29. try {
  30. await updateLayoutSetting({ isContainerFluid });
  31. toastSuccess(
  32. t('toaster.update_successed', {
  33. target: t('customize_settings.layout'),
  34. ns: 'commons',
  35. }),
  36. );
  37. } catch (err) {
  38. toastError(err);
  39. }
  40. }, [isContainerFluid, updateLayoutSetting, t]);
  41. if (isContainerFluid == null) {
  42. return (
  43. <div className="text-muted text-center fs-3">
  44. <LoadingSpinner />
  45. </div>
  46. );
  47. }
  48. return (
  49. <React.Fragment>
  50. <div className="row">
  51. <div className="col-12">
  52. <h2 className="admin-setting-header">
  53. {t('customize_settings.layout')}
  54. </h2>
  55. <div className="d-flex justify-content-around mt-5">
  56. <div className="row row-cols-2">
  57. <div className="col">
  58. <button
  59. type="button"
  60. className={`card border border-4 ${!isContainerFluid ? 'border-primary' : ''}`}
  61. onClick={() => setIsContainerFluid(false)}
  62. aria-pressed={!isContainerFluid}
  63. >
  64. {/* eslint-disable-next-line @next/next/no-img-element */}
  65. <img
  66. className="card-img-top"
  67. src={`/images/customize-settings/default-${resolvedTheme}.svg`}
  68. alt={t('customize_settings.layout_options.default')}
  69. />
  70. <div className="card-body text-center">
  71. {t('customize_settings.layout_options.default')}
  72. </div>
  73. </button>
  74. </div>
  75. <div className="col">
  76. <button
  77. type="button"
  78. className={`card border border-4 ${isContainerFluid ? 'border-primary' : ''}`}
  79. onClick={() => setIsContainerFluid(true)}
  80. aria-pressed={isContainerFluid}
  81. >
  82. {/* eslint-disable-next-line @next/next/no-img-element */}
  83. <img
  84. className="card-img-top"
  85. src={`/images/customize-settings/fluid-${resolvedTheme}.svg`}
  86. alt={t('customize_settings.layout_options.expanded')}
  87. />
  88. <div className="card-body text-center">
  89. {t('customize_settings.layout_options.expanded')}
  90. </div>
  91. </button>
  92. </div>
  93. </div>
  94. </div>
  95. <div className="row my-3">
  96. <div className="mx-auto">
  97. <button
  98. type="button"
  99. className="btn btn-primary"
  100. onClick={onClickSubmit}
  101. >
  102. {t('Update')}
  103. </button>
  104. </div>
  105. </div>
  106. </div>
  107. </div>
  108. </React.Fragment>
  109. );
  110. };
  111. export default CustomizeLayoutSetting;