CustomizeLayoutSetting.tsx 3.7 KB

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