diff --git a/src/features/about/index.tsx b/src/features/about/index.tsx index f4272810cd..871b4b0bf2 100644 --- a/src/features/about/index.tsx +++ b/src/features/about/index.tsx @@ -1,15 +1,23 @@ -import { Box, IconButton } from '@mui/material'; +import { Box } from '@mui/material'; +import { IconClose, IconInfo, IconLogo, IconRestart } from '@icons/index'; +import { useAppTranslation } from '@hooks/index'; +import { AboutProps } from './index.types'; +import useAbout from './useAbout'; import Button from '@components/button'; import Dialog from '@components/dialog'; +import IconButton from '@components/icon_button'; import TextMarkup from '@components/text_markup'; import Typography from '@components/typography'; -import { IconClose, IconInfo, IconLogo } from '@icons/index'; -import { useAppTranslation } from '@hooks/index'; -import useAbout from './useAbout'; -const About = () => { - const { currentYear, handleClose, isOpen, handleOpenDoc, handleOpenSupport } = - useAbout(); +const About = (props: AboutProps) => { + const { + currentYear, + handleClose, + isOpen, + handleOpenDoc, + handleOpenSupport, + handleForceReload, + } = useAbout(props); const { t } = useAppTranslation(); @@ -47,18 +55,31 @@ const About = () => { - - - Organized - - {import.meta.env.PACKAGE_VERSION} - + + + + Organized + + {import.meta.env.PACKAGE_VERSION} + + + + + + diff --git a/src/features/about/index.types.ts b/src/features/about/index.types.ts new file mode 100644 index 0000000000..86f2c9550b --- /dev/null +++ b/src/features/about/index.types.ts @@ -0,0 +1,3 @@ +export type AboutProps = { + updatePwa: VoidFunction; +}; diff --git a/src/features/about/useAbout.tsx b/src/features/about/useAbout.tsx index 074638e9b0..9898693ae7 100644 --- a/src/features/about/useAbout.tsx +++ b/src/features/about/useAbout.tsx @@ -1,12 +1,25 @@ import { useRecoilValue } from 'recoil'; import { isAboutOpenState } from '@states/app'; import { setIsAboutOpen, setIsSupportOpen } from '@services/recoil/app'; +import { AboutProps } from './index.types'; const currentYear = new Date().getFullYear(); -const useAbout = () => { +const useAbout = ({ updatePwa }: AboutProps) => { const isOpen = useRecoilValue(isAboutOpenState); + const handleForceReload = () => { + try { + updatePwa(); + + setTimeout(() => { + window.location.reload(); + }, 2000); + } catch (error) { + console.error(error.message); + } + }; + const handleClose = async () => { await setIsAboutOpen(false); }; @@ -20,7 +33,14 @@ const useAbout = () => { window.open(`https://guide.organized-app.com`, '_blank'); }; - return { isOpen, handleClose, currentYear, handleOpenDoc, handleOpenSupport }; + return { + isOpen, + handleClose, + currentYear, + handleOpenDoc, + handleOpenSupport, + handleForceReload, + }; }; export default useAbout; diff --git a/src/features/congregation/settings/congregation_privacy/index.tsx b/src/features/congregation/settings/congregation_privacy/index.tsx index d4e5c4a063..fcffdb4c05 100644 --- a/src/features/congregation/settings/congregation_privacy/index.tsx +++ b/src/features/congregation/settings/congregation_privacy/index.tsx @@ -7,6 +7,7 @@ import { useAppTranslation } from '@hooks/index'; import useCongregationPrivacy from './useCongregationPrivacy'; import AccessCodeView from './access_code_view'; import MasterKeyView from './master_key_view'; +import OutgoingTalkAccess from './outgoing_talk_access'; import SwitchWithLabel from '@components/switch_with_label'; const CongregationPrivacy = () => { @@ -15,8 +16,6 @@ const CongregationPrivacy = () => { const { timeAwayPublic, handleTimeAwayPublicToggle, - outgoingTalksPublic, - handleOutgoingTalksPublicToggle, isUserAdmin, isConnected, } = useCongregationPrivacy(); @@ -34,12 +33,8 @@ const CongregationPrivacy = () => { checked={timeAwayPublic} onChange={handleTimeAwayPublicToggle} /> - + + {isConnected && isUserAdmin && ( diff --git a/src/features/congregation/settings/congregation_privacy/outgoing_talk_access/index.tsx b/src/features/congregation/settings/congregation_privacy/outgoing_talk_access/index.tsx new file mode 100644 index 0000000000..fdfddff1fa --- /dev/null +++ b/src/features/congregation/settings/congregation_privacy/outgoing_talk_access/index.tsx @@ -0,0 +1,21 @@ +import { useAppTranslation } from '@hooks/index'; +import useCongregationPrivacy from './useOutgoingTalkAccess'; +import SwitchWithLabel from '@components/switch_with_label'; + +const OutgoingTalkAccess = () => { + const { t } = useAppTranslation(); + + const { outgoingTalksPublic, handleOutgoingTalksPublicToggle } = + useCongregationPrivacy(); + + return ( + + ); +}; + +export default OutgoingTalkAccess; diff --git a/src/features/congregation/settings/congregation_privacy/outgoing_talk_access/useOutgoingTalkAccess.tsx b/src/features/congregation/settings/congregation_privacy/outgoing_talk_access/useOutgoingTalkAccess.tsx new file mode 100644 index 0000000000..1f0c40066e --- /dev/null +++ b/src/features/congregation/settings/congregation_privacy/outgoing_talk_access/useOutgoingTalkAccess.tsx @@ -0,0 +1,43 @@ +import { useEffect, useState } from 'react'; +import { useRecoilValue } from 'recoil'; +import { settingsState, userDataViewState } from '@states/settings'; +import { dbAppSettingsUpdate } from '@services/dexie/settings'; + +const useOutgoingTalkAccess = () => { + const settings = useRecoilValue(settingsState); + const dataView = useRecoilValue(userDataViewState); + + const [outgoingTalksPublic, setOutgoingTalksPublic] = useState(false); + + const handleOutgoingTalksPublicToggle = async () => { + const weekendSettings = structuredClone( + settings.cong_settings.weekend_meeting + ); + + const current = weekendSettings.find((record) => record.type === dataView); + + current.outgoing_talks_schedule_public.value = !outgoingTalksPublic; + current.outgoing_talks_schedule_public.updatedAt = new Date().toISOString(); + + await dbAppSettingsUpdate({ + 'cong_settings.weekend_meeting': weekendSettings, + }); + }; + + useEffect(() => { + const weekendSettings = settings.cong_settings.weekend_meeting.find( + (record) => record.type === dataView + ); + + setOutgoingTalksPublic( + weekendSettings.outgoing_talks_schedule_public.value + ); + }, [settings, dataView]); + + return { + outgoingTalksPublic, + handleOutgoingTalksPublicToggle, + }; +}; + +export default useOutgoingTalkAccess; diff --git a/src/features/congregation/settings/congregation_privacy/useCongregationPrivacy.tsx b/src/features/congregation/settings/congregation_privacy/useCongregationPrivacy.tsx index e3d688905e..2bcdb94904 100644 --- a/src/features/congregation/settings/congregation_privacy/useCongregationPrivacy.tsx +++ b/src/features/congregation/settings/congregation_privacy/useCongregationPrivacy.tsx @@ -1,21 +1,15 @@ import { useEffect, useState } from 'react'; import { useRecoilValue } from 'recoil'; -import { - adminRoleState, - settingsState, - userDataViewState, -} from '@states/settings'; +import { adminRoleState, settingsState } from '@states/settings'; import { dbAppSettingsUpdate } from '@services/dexie/settings'; import { congAccountConnectedState } from '@states/app'; const useCongregationPrivacy = () => { const settings = useRecoilValue(settingsState); - const dataView = useRecoilValue(userDataViewState); const isUserAdmin = useRecoilValue(adminRoleState); const isConnected = useRecoilValue(congAccountConnectedState); const [timeAwayPublic, setTimeAwayPublic] = useState(false); - const [outgoingTalksPublic, setOutgoingTalksPublic] = useState(false); const handleTimeAwayPublicToggle = async () => { const timeAway = structuredClone(settings.cong_settings.time_away_public); @@ -28,38 +22,13 @@ const useCongregationPrivacy = () => { }); }; - const handleOutgoingTalksPublicToggle = async () => { - const weekendSettings = structuredClone( - settings.cong_settings.weekend_meeting - ); - - const current = weekendSettings.find((record) => record.type === dataView); - - current.outgoing_talks_schedule_public.value = !outgoingTalksPublic; - current.outgoing_talks_schedule_public.updatedAt = new Date().toISOString(); - - await dbAppSettingsUpdate({ - 'cong_settings.weekend_meeting': weekendSettings, - }); - }; - useEffect(() => { setTimeAwayPublic(settings.cong_settings.time_away_public.value); - - const weekendSettings = settings.cong_settings.weekend_meeting.find( - (record) => record.type === dataView - ); - - setOutgoingTalksPublic( - weekendSettings.outgoing_talks_schedule_public.value - ); - }, [settings, dataView]); + }, [settings]); return { timeAwayPublic, - outgoingTalksPublic, handleTimeAwayPublicToggle, - handleOutgoingTalksPublicToggle, isUserAdmin, isConnected, }; diff --git a/src/features/congregation/settings/meeting_forms/display_name/index.tsx b/src/features/congregation/settings/meeting_forms/display_name/index.tsx new file mode 100644 index 0000000000..96720d15f6 --- /dev/null +++ b/src/features/congregation/settings/meeting_forms/display_name/index.tsx @@ -0,0 +1,20 @@ +import { useAppTranslation } from '@hooks/index'; +import useDisplayName from './useDisplayName'; +import SwitchWithLabel from '@components/switch_with_label'; + +const DisplayName = () => { + const { t } = useAppTranslation(); + + const { displayNameMeeting, handleDisplayNameMeetingToggle } = + useDisplayName(); + + return ( + + ); +}; + +export default DisplayName; diff --git a/src/features/congregation/settings/meeting_forms/display_name/useDisplayName.tsx b/src/features/congregation/settings/meeting_forms/display_name/useDisplayName.tsx new file mode 100644 index 0000000000..ca9eb6eb76 --- /dev/null +++ b/src/features/congregation/settings/meeting_forms/display_name/useDisplayName.tsx @@ -0,0 +1,37 @@ +import { useEffect, useState } from 'react'; +import { useRecoilValue } from 'recoil'; +import { settingsState, userDataViewState } from '@states/settings'; +import { dbAppSettingsUpdate } from '@services/dexie/settings'; + +const useMeetingForms = () => { + const settings = useRecoilValue(settingsState); + const dataView = useRecoilValue(userDataViewState); + + const [displayNameMeeting, setDisplayNameMeeting] = useState(false); + + const handleDisplayNameMeetingToggle = async () => { + const displayNameEnabled = structuredClone( + settings.cong_settings.display_name_enabled.meetings + ); + + displayNameEnabled.value = !displayNameMeeting; + displayNameEnabled.updatedAt = new Date().toISOString(); + + await dbAppSettingsUpdate({ + 'cong_settings.display_name_enabled.meetings': displayNameEnabled, + }); + }; + + useEffect(() => { + setDisplayNameMeeting( + settings.cong_settings.display_name_enabled.meetings.value + ); + }, [settings, dataView]); + + return { + displayNameMeeting, + handleDisplayNameMeetingToggle, + }; +}; + +export default useMeetingForms; diff --git a/src/features/congregation/settings/meeting_forms/index.tsx b/src/features/congregation/settings/meeting_forms/index.tsx index f52d323cad..37e0660697 100644 --- a/src/features/congregation/settings/meeting_forms/index.tsx +++ b/src/features/congregation/settings/meeting_forms/index.tsx @@ -1,13 +1,13 @@ +import { Stack } from '@mui/material'; import { formatDate } from '@services/dateformat'; import { useAppTranslation } from '@hooks/index'; -import { - CardSection, - CardSectionContent, - CardSectionHeader, -} from '../../shared_styles/components'; +import { CardSection, CardSectionHeader } from '../../shared_styles/components'; import { FullnameOption, SourceFrequency } from '@definition/settings'; import useMeetingForms from './useMeetingForms'; +import DisplayName from './display_name'; +import Divider from '@components/divider'; import MenuItem from '@components/menuitem'; +import MidweekExactDate from './midweek_exact_date'; import Select from '@components/select'; import SwitchWithLabel from '@components/switch_with_label'; @@ -19,10 +19,6 @@ const MeetingForms = () => { handleSourceAutoUpdateToggle, handleSourceUpdateFrequencyChange, sourceUpdateFrequency, - displayExactDate, - handleDisplayExactDateToggle, - displayNameMeeting, - handleDisplayNameMeetingToggle, fullnameOption, handleFullnameOptionChange, handleShortDateFormatChange, @@ -32,76 +28,71 @@ const MeetingForms = () => { return ( - - + }> + + - + - {sourceAutoUpdate && ( + {sourceAutoUpdate && ( + + )} + + + + + + + + + - )} - - - - - - - - - - - - + + + ); }; diff --git a/src/features/congregation/settings/meeting_forms/midweek_exact_date/index.tsx b/src/features/congregation/settings/meeting_forms/midweek_exact_date/index.tsx new file mode 100644 index 0000000000..d6ba1932d2 --- /dev/null +++ b/src/features/congregation/settings/meeting_forms/midweek_exact_date/index.tsx @@ -0,0 +1,21 @@ +import { useAppTranslation } from '@hooks/index'; +import useMidweekExactDate from './useMidweekExactDate'; +import SwitchWithLabel from '@components/switch_with_label'; + +const MidweekExactDate = () => { + const { t } = useAppTranslation(); + + const { displayExactDate, handleDisplayExactDateToggle } = + useMidweekExactDate(); + + return ( + + ); +}; + +export default MidweekExactDate; diff --git a/src/features/congregation/settings/meeting_forms/midweek_exact_date/useMidweekExactDate.tsx b/src/features/congregation/settings/meeting_forms/midweek_exact_date/useMidweekExactDate.tsx new file mode 100644 index 0000000000..b70af51f01 --- /dev/null +++ b/src/features/congregation/settings/meeting_forms/midweek_exact_date/useMidweekExactDate.tsx @@ -0,0 +1,37 @@ +import { useEffect, useState } from 'react'; +import { useRecoilValue } from 'recoil'; +import { settingsState, userDataViewState } from '@states/settings'; +import { dbAppSettingsUpdate } from '@services/dexie/settings'; + +const useMidweekExactDate = () => { + const settings = useRecoilValue(settingsState); + const dataView = useRecoilValue(userDataViewState); + + const [displayExactDate, setDisplayExactDate] = useState(false); + + const handleDisplayExactDateToggle = async () => { + const exactDate = structuredClone( + settings.cong_settings.schedule_exact_date_enabled + ); + + exactDate.value = !displayExactDate; + exactDate.updatedAt = new Date().toISOString(); + + await dbAppSettingsUpdate({ + 'cong_settings.schedule_exact_date_enabled': exactDate, + }); + }; + + useEffect(() => { + setDisplayExactDate( + settings.cong_settings.schedule_exact_date_enabled.value + ); + }, [settings, dataView]); + + return { + displayExactDate, + handleDisplayExactDateToggle, + }; +}; + +export default useMidweekExactDate; diff --git a/src/features/congregation/settings/meeting_forms/useMeetingForms.tsx b/src/features/congregation/settings/meeting_forms/useMeetingForms.tsx index ee3a7632f0..29e600de8e 100644 --- a/src/features/congregation/settings/meeting_forms/useMeetingForms.tsx +++ b/src/features/congregation/settings/meeting_forms/useMeetingForms.tsx @@ -16,8 +16,6 @@ const useMeetingForms = () => { const [sourceUpdateFrequency, setSourceUpdateFrequency] = useState( SourceFrequency.WEEKLY ); - const [displayExactDate, setDisplayExactDate] = useState(false); - const [displayNameMeeting, setDisplayNameMeeting] = useState(false); const [fullnameOption, setFullnameOption] = useState( FullnameOption.FIRST_BEFORE_LAST ); @@ -59,32 +57,6 @@ const useMeetingForms = () => { }); }; - const handleDisplayExactDateToggle = async () => { - const exactDate = structuredClone( - settings.cong_settings.schedule_exact_date_enabled - ); - - exactDate.value = !displayExactDate; - exactDate.updatedAt = new Date().toISOString(); - - await dbAppSettingsUpdate({ - 'cong_settings.schedule_exact_date_enabled': exactDate, - }); - }; - - const handleDisplayNameMeetingToggle = async () => { - const displayNameEnabled = structuredClone( - settings.cong_settings.display_name_enabled.meetings - ); - - displayNameEnabled.value = !displayNameMeeting; - displayNameEnabled.updatedAt = new Date().toISOString(); - - await dbAppSettingsUpdate({ - 'cong_settings.display_name_enabled.meetings': displayNameEnabled, - }); - }; - const handleFullnameOptionChange = async (value: FullnameOption) => { const fullnameOption = structuredClone( settings.cong_settings.fullname_option @@ -128,14 +100,6 @@ const useMeetingForms = () => { settings.cong_settings.source_material_auto_import.frequency.value ); - setDisplayExactDate( - settings.cong_settings.schedule_exact_date_enabled.value - ); - - setDisplayNameMeeting( - settings.cong_settings.display_name_enabled.meetings.value - ); - const fullname = settings.cong_settings.fullname_option.find( (record) => record.type === dataView ); @@ -154,10 +118,6 @@ const useMeetingForms = () => { handleSourceAutoUpdateToggle, sourceUpdateFrequency, handleSourceUpdateFrequencyChange, - displayExactDate, - handleDisplayExactDateToggle, - displayNameMeeting, - handleDisplayNameMeetingToggle, fullnameOption, handleFullnameOptionChange, shortDateFormat, diff --git a/src/features/congregation/settings/meeting_settings/midweek/assignment_preferences/index.tsx b/src/features/congregation/settings/meeting_settings/midweek/assignment_preferences/index.tsx new file mode 100644 index 0000000000..b39e8df55e --- /dev/null +++ b/src/features/congregation/settings/meeting_settings/midweek/assignment_preferences/index.tsx @@ -0,0 +1,32 @@ +import { useAppTranslation } from '@hooks/index'; +import useAssignmentPreferences from './useAssignmentPreferences'; +import SwitchWithLabel from '@components/switch_with_label'; + +const AssignmentPreferences = () => { + const { t } = useAppTranslation(); + + const { + autoAssignOpeningPrayer, + handleAutoOpeningPrayerToggle, + autoAssignClosingPrayer, + handleAutoClosingPrayerToggle, + } = useAssignmentPreferences(); + + return ( + <> + + + + + ); +}; + +export default AssignmentPreferences; diff --git a/src/features/congregation/settings/meeting_settings/midweek/assignment_preferences/useAssignmentPreferences.tsx b/src/features/congregation/settings/meeting_settings/midweek/assignment_preferences/useAssignmentPreferences.tsx new file mode 100644 index 0000000000..0595e37240 --- /dev/null +++ b/src/features/congregation/settings/meeting_settings/midweek/assignment_preferences/useAssignmentPreferences.tsx @@ -0,0 +1,64 @@ +import { useEffect, useState } from 'react'; +import { useRecoilValue } from 'recoil'; +import { settingsState, userDataViewState } from '@states/settings'; +import { dbAppSettingsUpdate } from '@services/dexie/settings'; + +const useAssignmentPreferences = () => { + const settings = useRecoilValue(settingsState); + const dataView = useRecoilValue(userDataViewState); + + const [autoAssignOpeningPrayer, setAutoAssignOpeningPrayer] = useState(false); + const [autoAssignClosingPrayer, setAutoAssignClosingPrayer] = useState(false); + + const handleAutoOpeningPrayerToggle = async () => { + const midweekSettings = structuredClone( + settings.cong_settings.midweek_meeting + ); + + const current = midweekSettings.find((record) => record.type === dataView); + + current.opening_prayer_auto_assigned.value = !autoAssignOpeningPrayer; + current.opening_prayer_auto_assigned.updatedAt = new Date().toISOString(); + + await dbAppSettingsUpdate({ + 'cong_settings.midweek_meeting': midweekSettings, + }); + }; + + const handleAutoClosingPrayerToggle = async () => { + const midweekSettings = structuredClone( + settings.cong_settings.midweek_meeting + ); + + const current = midweekSettings.find((record) => record.type === dataView); + + current.closing_prayer_auto_assigned.value = !autoAssignClosingPrayer; + current.closing_prayer_auto_assigned.updatedAt = new Date().toISOString(); + + await dbAppSettingsUpdate({ + 'cong_settings.midweek_meeting': midweekSettings, + }); + }; + + useEffect(() => { + const midweekSettings = settings.cong_settings.midweek_meeting.find( + (record) => record.type === dataView + ); + + setAutoAssignOpeningPrayer( + midweekSettings.opening_prayer_auto_assigned.value + ); + setAutoAssignClosingPrayer( + midweekSettings.closing_prayer_auto_assigned.value + ); + }, [settings, dataView]); + + return { + autoAssignOpeningPrayer, + handleAutoOpeningPrayerToggle, + autoAssignClosingPrayer, + handleAutoClosingPrayerToggle, + }; +}; + +export default useAssignmentPreferences; diff --git a/src/features/congregation/settings/meeting_settings/midweek/auxiliary_classroom/index.tsx b/src/features/congregation/settings/meeting_settings/midweek/auxiliary_classroom/index.tsx new file mode 100644 index 0000000000..3ff0c8c1db --- /dev/null +++ b/src/features/congregation/settings/meeting_settings/midweek/auxiliary_classroom/index.tsx @@ -0,0 +1,63 @@ +import { TwoColumnsRow } from '@features/congregation/shared_styles/components'; +import { useAppTranslation, useBreakpoints } from '@hooks/index'; +import useAuxiliaryClassroom from './useAuxiliaryClassroom'; +import MenuItem from '@components/menuitem'; +import Select from '@components/select'; +import SwitchWithLabel from '@components/switch_with_label'; +import Typography from '@components/typography'; + +const AuxiliaryClassroom = () => { + const { t } = useAppTranslation(); + + const { laptopUp } = useBreakpoints(); + + const { + auxClassEnabled, + handleAuxClassToggle, + auxCounselorMainEnabled, + handleAuxCounselorMainToggle, + personsAuxCounselorList, + auxCounselorMainPerson, + handleAuxCounselorMainPersonChange, + } = useAuxiliaryClassroom(); + + return ( + <> + + + {auxClassEnabled && ( + + + + + + )} + + ); +}; + +export default AuxiliaryClassroom; diff --git a/src/features/congregation/settings/meeting_settings/midweek/useMidweek.tsx b/src/features/congregation/settings/meeting_settings/midweek/auxiliary_classroom/useAuxiliaryClassroom.tsx similarity index 55% rename from src/features/congregation/settings/meeting_settings/midweek/useMidweek.tsx rename to src/features/congregation/settings/meeting_settings/midweek/auxiliary_classroom/useAuxiliaryClassroom.tsx index 74f4629195..df67fccb75 100644 --- a/src/features/congregation/settings/meeting_settings/midweek/useMidweek.tsx +++ b/src/features/congregation/settings/meeting_settings/midweek/auxiliary_classroom/useAuxiliaryClassroom.tsx @@ -6,9 +6,7 @@ import { settingsState, userDataViewState, } from '@states/settings'; -import { generateDateFromTime } from '@utils/date'; import { dbAppSettingsUpdate } from '@services/dexie/settings'; -import { formatDate } from '@services/dateformat'; import { personsActiveState } from '@states/persons'; import { AssignmentCode } from '@definition/assignment'; import { personGetDisplayName } from '@utils/common'; @@ -20,11 +18,6 @@ const useMidweekSettings = () => { const useDisplayName = useRecoilValue(displayNameMeetingsEnableState); const fullnameOption = useRecoilValue(fullnameOptionState); - const [hour24, setHour24] = useState(false); - const [meetingDay, setMeetingDay] = useState(''); - const [meetingTime, setMeetingTime] = useState(null); - const [autoAssignOpeningPrayer, setAutoAssignOpeningPrayer] = useState(false); - const [autoAssignClosingPrayer, setAutoAssignClosingPrayer] = useState(false); const [auxClassEnabled, setAuxClassEnabled] = useState(false); const [auxCounselorMainEnabled, setAuxCounselorMainEnabled] = useState(false); const [auxCounselorMainPerson, setAuxCounselorMainPerson] = useState(''); @@ -48,68 +41,6 @@ const useMidweekSettings = () => { return result; }, [persons, useDisplayName, fullnameOption]); - const handleMeetingDayChange = async (value: number) => { - const midweekSettings = structuredClone( - settings.cong_settings.midweek_meeting - ); - - const current = midweekSettings.find((record) => record.type === dataView); - - current.weekday.value = value; - current.weekday.updatedAt = new Date().toISOString(); - - await dbAppSettingsUpdate({ - 'cong_settings.midweek_meeting': midweekSettings, - }); - }; - - const handleMeetingTimeChange = async (value: Date) => { - const time = value ? formatDate(value, 'HH:mm') : '00:00'; - - const midweekSettings = structuredClone( - settings.cong_settings.midweek_meeting - ); - - const current = midweekSettings.find((record) => record.type === dataView); - - current.time.value = time; - current.time.updatedAt = new Date().toISOString(); - - await dbAppSettingsUpdate({ - 'cong_settings.midweek_meeting': midweekSettings, - }); - }; - - const handleAutoOpeningPrayerToggle = async () => { - const midweekSettings = structuredClone( - settings.cong_settings.midweek_meeting - ); - - const current = midweekSettings.find((record) => record.type === dataView); - - current.opening_prayer_auto_assigned.value = !autoAssignOpeningPrayer; - current.opening_prayer_auto_assigned.updatedAt = new Date().toISOString(); - - await dbAppSettingsUpdate({ - 'cong_settings.midweek_meeting': midweekSettings, - }); - }; - - const handleAutoClosingPrayerToggle = async () => { - const midweekSettings = structuredClone( - settings.cong_settings.midweek_meeting - ); - - const current = midweekSettings.find((record) => record.type === dataView); - - current.closing_prayer_auto_assigned.value = !autoAssignClosingPrayer; - current.closing_prayer_auto_assigned.updatedAt = new Date().toISOString(); - - await dbAppSettingsUpdate({ - 'cong_settings.midweek_meeting': midweekSettings, - }); - }; - const handleAuxClassToggle = async () => { const midweekSettings = structuredClone( settings.cong_settings.midweek_meeting @@ -159,24 +90,10 @@ const useMidweekSettings = () => { }; useEffect(() => { - const hourFormat = settings.cong_settings.format_24h_enabled.find( - (record) => record.type === dataView - ); - - setHour24(hourFormat.value); - const midweekSettings = settings.cong_settings.midweek_meeting.find( (record) => record.type === dataView ); - setMeetingDay(midweekSettings.weekday.value); - setMeetingTime(generateDateFromTime(midweekSettings.time.value)); - setAutoAssignOpeningPrayer( - midweekSettings.opening_prayer_auto_assigned.value - ); - setAutoAssignClosingPrayer( - midweekSettings.closing_prayer_auto_assigned.value - ); setAuxClassEnabled(midweekSettings.class_count.value === 2); setAuxCounselorMainEnabled( midweekSettings.aux_class_counselor_default.enabled.value @@ -187,15 +104,6 @@ const useMidweekSettings = () => { }, [settings, dataView]); return { - meetingDay, - handleMeetingDayChange, - hour24, - meetingTime, - handleMeetingTimeChange, - autoAssignOpeningPrayer, - handleAutoOpeningPrayerToggle, - autoAssignClosingPrayer, - handleAutoClosingPrayerToggle, auxClassEnabled, handleAuxClassToggle, auxCounselorMainEnabled, diff --git a/src/features/congregation/settings/meeting_settings/midweek/day_time/index.tsx b/src/features/congregation/settings/meeting_settings/midweek/day_time/index.tsx new file mode 100644 index 0000000000..9a8735bb81 --- /dev/null +++ b/src/features/congregation/settings/meeting_settings/midweek/day_time/index.tsx @@ -0,0 +1,36 @@ +import { useAppTranslation } from '@hooks/index'; +import { TwoColumnsRow } from '@features/congregation/shared_styles/components'; +import useDayTime from './useDayTime'; +import DaySelector from '@components/day_selector'; +import TimePicker from '@components/time_picker'; + +const DayTime = () => { + const { t } = useAppTranslation(); + + const { + handleMeetingDayChange, + handleMeetingTimeChange, + hour24, + meetingDay, + meetingTime, + } = useDayTime(); + + return ( + + + + handleMeetingTimeChange(time)} + /> + + ); +}; + +export default DayTime; diff --git a/src/features/congregation/settings/meeting_settings/midweek/day_time/useDayTime.tsx b/src/features/congregation/settings/meeting_settings/midweek/day_time/useDayTime.tsx new file mode 100644 index 0000000000..ebc098ac7f --- /dev/null +++ b/src/features/congregation/settings/meeting_settings/midweek/day_time/useDayTime.tsx @@ -0,0 +1,73 @@ +import { useEffect, useMemo, useState } from 'react'; +import { useRecoilValue } from 'recoil'; +import { settingsState, userDataViewState } from '@states/settings'; +import { generateDateFromTime } from '@utils/date'; +import { dbAppSettingsUpdate } from '@services/dexie/settings'; +import { formatDate } from '@services/dateformat'; + +const useDayTime = () => { + const settings = useRecoilValue(settingsState); + const dataView = useRecoilValue(userDataViewState); + + const [meetingDay, setMeetingDay] = useState(''); + const [meetingTime, setMeetingTime] = useState(null); + + const hour24 = useMemo(() => { + const hourFormat = settings.cong_settings.format_24h_enabled.find( + (record) => record.type === dataView + ); + + return hourFormat.value; + }, [settings, dataView]); + + const handleMeetingDayChange = async (value: number) => { + const midweekSettings = structuredClone( + settings.cong_settings.midweek_meeting + ); + + const current = midweekSettings.find((record) => record.type === dataView); + + current.weekday.value = value; + current.weekday.updatedAt = new Date().toISOString(); + + await dbAppSettingsUpdate({ + 'cong_settings.midweek_meeting': midweekSettings, + }); + }; + + const handleMeetingTimeChange = async (value: Date) => { + const time = value ? formatDate(value, 'HH:mm') : '00:00'; + + const midweekSettings = structuredClone( + settings.cong_settings.midweek_meeting + ); + + const current = midweekSettings.find((record) => record.type === dataView); + + current.time.value = time; + current.time.updatedAt = new Date().toISOString(); + + await dbAppSettingsUpdate({ + 'cong_settings.midweek_meeting': midweekSettings, + }); + }; + + useEffect(() => { + const midweekSettings = settings.cong_settings.midweek_meeting.find( + (record) => record.type === dataView + ); + + setMeetingDay(midweekSettings.weekday.value); + setMeetingTime(generateDateFromTime(midweekSettings.time.value)); + }, [settings, dataView]); + + return { + meetingDay, + handleMeetingDayChange, + hour24, + meetingTime, + handleMeetingTimeChange, + }; +}; + +export default useDayTime; diff --git a/src/features/congregation/settings/meeting_settings/midweek/index.tsx b/src/features/congregation/settings/meeting_settings/midweek/index.tsx index 40854df896..9c83441a6d 100644 --- a/src/features/congregation/settings/meeting_settings/midweek/index.tsx +++ b/src/features/congregation/settings/meeting_settings/midweek/index.tsx @@ -1,54 +1,12 @@ import { Box } from '@mui/material'; -import { useAppTranslation, useBreakpoints } from '@hooks/index'; -import { TwoColumnsRow } from '../../../shared_styles/components'; -import useMidweekSettings from './useMidweek'; -import DaySelector from '@components/day_selector'; -import MenuItem from '@components/menuitem'; -import Select from '@components/select'; -import SwitchWithLabel from '@components/switch_with_label'; -import TimePicker from '@components/time_picker'; -import Typography from '@components/typography'; +import AssignmentPreferences from './assignment_preferences'; +import DayTime from './day_time'; +import AuxiliaryClassroom from './auxiliary_classroom'; const MidweekSettings = () => { - const { t } = useAppTranslation(); - - const { laptopUp } = useBreakpoints(); - - const { - meetingDay, - handleMeetingDayChange, - hour24, - meetingTime, - handleMeetingTimeChange, - autoAssignOpeningPrayer, - handleAutoOpeningPrayerToggle, - autoAssignClosingPrayer, - handleAutoClosingPrayerToggle, - auxClassEnabled, - handleAuxClassToggle, - auxCounselorMainEnabled, - handleAuxCounselorMainToggle, - personsAuxCounselorList, - auxCounselorMainPerson, - handleAuxCounselorMainPersonChange, - } = useMidweekSettings(); - return ( - - - - handleMeetingTimeChange(time)} - /> - + { gap: '16px', }} > - - - - - - - {auxClassEnabled && ( - - + - - - )} + ); diff --git a/src/features/congregation/settings/meeting_settings/weekend/assignment_preferences/index.tsx b/src/features/congregation/settings/meeting_settings/weekend/assignment_preferences/index.tsx new file mode 100644 index 0000000000..9db4a9beb7 --- /dev/null +++ b/src/features/congregation/settings/meeting_settings/weekend/assignment_preferences/index.tsx @@ -0,0 +1,32 @@ +import { useAppTranslation } from '@hooks/index'; +import useAssignmentPreferences from './useAssignmentPreferences'; +import SwitchWithLabel from '@components/switch_with_label'; + +const AssignmentPreferences = () => { + const { t } = useAppTranslation(); + + const { + autoAssignOpeningPrayer, + handleAutoOpeningPrayerToggle, + handleSubstituteSpeakerToggle, + substituteSpeakerEnabled, + } = useAssignmentPreferences(); + + return ( + <> + + + + + ); +}; + +export default AssignmentPreferences; diff --git a/src/features/congregation/settings/meeting_settings/weekend/assignment_preferences/useAssignmentPreferences.tsx b/src/features/congregation/settings/meeting_settings/weekend/assignment_preferences/useAssignmentPreferences.tsx new file mode 100644 index 0000000000..f94928bc59 --- /dev/null +++ b/src/features/congregation/settings/meeting_settings/weekend/assignment_preferences/useAssignmentPreferences.tsx @@ -0,0 +1,65 @@ +import { useEffect, useState } from 'react'; +import { useRecoilValue } from 'recoil'; +import { settingsState, userDataViewState } from '@states/settings'; +import { dbAppSettingsUpdate } from '@services/dexie/settings'; + +const useAssignmentPreferences = () => { + const settings = useRecoilValue(settingsState); + const dataView = useRecoilValue(userDataViewState); + + const [autoAssignOpeningPrayer, setAutoAssignOpeningPrayer] = useState(false); + const [substituteSpeakerEnabled, setSubstituteSpeakerEnabled] = + useState(false); + + const handleAutoOpeningPrayerToggle = async () => { + const weekendSettings = structuredClone( + settings.cong_settings.weekend_meeting + ); + + const current = weekendSettings.find((record) => record.type === dataView); + + current.opening_prayer_auto_assigned.value = !autoAssignOpeningPrayer; + current.opening_prayer_auto_assigned.updatedAt = new Date().toISOString(); + + await dbAppSettingsUpdate({ + 'cong_settings.weekend_meeting': weekendSettings, + }); + }; + + const handleSubstituteSpeakerToggle = async () => { + const weekendSettings = structuredClone( + settings.cong_settings.weekend_meeting + ); + + const current = weekendSettings.find((record) => record.type === dataView); + + current.substitute_speaker_enabled.value = !substituteSpeakerEnabled; + current.substitute_speaker_enabled.updatedAt = new Date().toISOString(); + + await dbAppSettingsUpdate({ + 'cong_settings.weekend_meeting': weekendSettings, + }); + }; + + useEffect(() => { + const weekendSettings = settings.cong_settings.weekend_meeting.find( + (record) => record.type === dataView + ); + + setAutoAssignOpeningPrayer( + weekendSettings.opening_prayer_auto_assigned.value + ); + setSubstituteSpeakerEnabled( + weekendSettings.substitute_speaker_enabled.value + ); + }, [settings, dataView]); + + return { + autoAssignOpeningPrayer, + handleAutoOpeningPrayerToggle, + handleSubstituteSpeakerToggle, + substituteSpeakerEnabled, + }; +}; + +export default useAssignmentPreferences; diff --git a/src/features/congregation/settings/meeting_settings/weekend/day_time/index.tsx b/src/features/congregation/settings/meeting_settings/weekend/day_time/index.tsx new file mode 100644 index 0000000000..f39c66364e --- /dev/null +++ b/src/features/congregation/settings/meeting_settings/weekend/day_time/index.tsx @@ -0,0 +1,36 @@ +import { TwoColumnsRow } from '@features/congregation/shared_styles/components'; +import { useAppTranslation } from '@hooks/index'; +import useDayTime from './useDayTime'; +import DaySelector from '@components/day_selector'; +import TimePicker from '@components/time_picker'; + +const DayTime = () => { + const { t } = useAppTranslation(); + + const { + handleMeetingDayChange, + handleMeetingTimeChange, + hour24, + meetingDay, + meetingTime, + } = useDayTime(); + + return ( + + + + handleMeetingTimeChange(time)} + /> + + ); +}; + +export default DayTime; diff --git a/src/features/congregation/settings/meeting_settings/weekend/day_time/useDayTime.tsx b/src/features/congregation/settings/meeting_settings/weekend/day_time/useDayTime.tsx new file mode 100644 index 0000000000..3f1996c376 --- /dev/null +++ b/src/features/congregation/settings/meeting_settings/weekend/day_time/useDayTime.tsx @@ -0,0 +1,73 @@ +import { useEffect, useMemo, useState } from 'react'; +import { useRecoilValue } from 'recoil'; +import { settingsState, userDataViewState } from '@states/settings'; +import { generateDateFromTime } from '@utils/date'; +import { dbAppSettingsUpdate } from '@services/dexie/settings'; +import { formatDate } from '@services/dateformat'; + +const useDayTime = () => { + const settings = useRecoilValue(settingsState); + const dataView = useRecoilValue(userDataViewState); + + const [meetingDay, setMeetingDay] = useState(''); + const [meetingTime, setMeetingTime] = useState(null); + + const hour24 = useMemo(() => { + const hourFormat = settings.cong_settings.format_24h_enabled.find( + (record) => record.type === dataView + ); + + return hourFormat.value; + }, [settings, dataView]); + + const handleMeetingDayChange = async (value: number) => { + const weekendSettings = structuredClone( + settings.cong_settings.weekend_meeting + ); + + const current = weekendSettings.find((record) => record.type === dataView); + + current.weekday.value = value; + current.weekday.updatedAt = new Date().toISOString(); + + await dbAppSettingsUpdate({ + 'cong_settings.weekend_meeting': weekendSettings, + }); + }; + + const handleMeetingTimeChange = async (value: Date) => { + const time = value ? formatDate(value, 'HH:mm') : '00:00'; + + const weekendSettings = structuredClone( + settings.cong_settings.weekend_meeting + ); + + const current = weekendSettings.find((record) => record.type === dataView); + + current.time.value = time; + current.time.updatedAt = new Date().toISOString(); + + await dbAppSettingsUpdate({ + 'cong_settings.weekend_meeting': weekendSettings, + }); + }; + + useEffect(() => { + const weekendSettings = settings.cong_settings.weekend_meeting.find( + (record) => record.type === dataView + ); + + setMeetingDay(weekendSettings.weekday.value); + setMeetingTime(generateDateFromTime(weekendSettings.time.value)); + }, [settings, dataView]); + + return { + meetingDay, + handleMeetingDayChange, + hour24, + meetingTime, + handleMeetingTimeChange, + }; +}; + +export default useDayTime; diff --git a/src/features/congregation/settings/meeting_settings/weekend/index.tsx b/src/features/congregation/settings/meeting_settings/weekend/index.tsx index 76a02bb3d6..6ca03866b2 100644 --- a/src/features/congregation/settings/meeting_settings/weekend/index.tsx +++ b/src/features/congregation/settings/meeting_settings/weekend/index.tsx @@ -1,54 +1,13 @@ import { Box } from '@mui/material'; -import { useAppTranslation, useBreakpoints } from '@hooks/index'; -import { TwoColumnsRow } from '../../../shared_styles/components'; -import useWeekendSettings from './useWeekend'; -import DaySelector from '@components/day_selector'; -import MenuItem from '@components/menuitem'; -import Select from '@components/select'; -import SwitchWithLabel from '@components/switch_with_label'; -import TimePicker from '@components/time_picker'; -import Typography from '@components/typography'; +import AssignmentPreferences from '../midweek/assignment_preferences'; +import DayTime from './day_time'; +import MonthlyWarning from './monthly_warning'; +import StudyConductor from './study_conductor'; const WeekendSettings = () => { - const { t } = useAppTranslation(); - - const { laptopUp } = useBreakpoints(); - - const { - autoAssignOpeningPrayer, - handleAutoOpeningPrayerToggle, - handleMeetingDayChange, - handleMeetingTimeChange, - handleMonthlyOverlapToggle, - handleSubstituteSpeakerToggle, - handleWTConductorMainPersonChange, - handleWTConductorToggle, - hour24, - meetingDay, - meetingTime, - monthlyOverlapShown, - personsWTCondcutorList, - substituteSpeakerEnabled, - subtituteWTConductorDisplayed, - wtConductorMainPerson, - } = useWeekendSettings(); - return ( - - - - handleMeetingTimeChange(time)} - /> - + { gap: '16px', }} > - - - - - - + - - + - + ); diff --git a/src/features/congregation/settings/meeting_settings/weekend/monthly_warning/index.tsx b/src/features/congregation/settings/meeting_settings/weekend/monthly_warning/index.tsx new file mode 100644 index 0000000000..37ba71a962 --- /dev/null +++ b/src/features/congregation/settings/meeting_settings/weekend/monthly_warning/index.tsx @@ -0,0 +1,21 @@ +import { useAppTranslation } from '@hooks/index'; +import useWeekendSettings from './useMonthlyWarning'; +import SwitchWithLabel from '@components/switch_with_label'; + +const MonthlyWarning = () => { + const { t } = useAppTranslation(); + + const { handleMonthlyOverlapToggle, monthlyOverlapShown } = + useWeekendSettings(); + + return ( + + ); +}; + +export default MonthlyWarning; diff --git a/src/features/congregation/settings/meeting_settings/weekend/monthly_warning/useMonthlyWarning.tsx b/src/features/congregation/settings/meeting_settings/weekend/monthly_warning/useMonthlyWarning.tsx new file mode 100644 index 0000000000..3c37b234bf --- /dev/null +++ b/src/features/congregation/settings/meeting_settings/weekend/monthly_warning/useMonthlyWarning.tsx @@ -0,0 +1,44 @@ +import { useEffect, useState } from 'react'; +import { useRecoilValue } from 'recoil'; +import { settingsState, userDataViewState } from '@states/settings'; +import { dbAppSettingsUpdate } from '@services/dexie/settings'; + +const useMonthlyWarning = () => { + const settings = useRecoilValue(settingsState); + const dataView = useRecoilValue(userDataViewState); + + const [monthlyOverlapShown, setMonthlyOverlapShown] = useState(true); + + const handleMonthlyOverlapToggle = async () => { + const weekendSettings = structuredClone( + settings.cong_settings.weekend_meeting + ); + + const current = weekendSettings.find((record) => record.type === dataView); + + current.consecutive_monthly_parts_notice_shown.value = !monthlyOverlapShown; + current.consecutive_monthly_parts_notice_shown.updatedAt = + new Date().toISOString(); + + await dbAppSettingsUpdate({ + 'cong_settings.weekend_meeting': weekendSettings, + }); + }; + + useEffect(() => { + const weekendSettings = settings.cong_settings.weekend_meeting.find( + (record) => record.type === dataView + ); + + setMonthlyOverlapShown( + weekendSettings.consecutive_monthly_parts_notice_shown.value + ); + }, [settings, dataView]); + + return { + handleMonthlyOverlapToggle, + monthlyOverlapShown, + }; +}; + +export default useMonthlyWarning; diff --git a/src/features/congregation/settings/meeting_settings/weekend/study_conductor/index.tsx b/src/features/congregation/settings/meeting_settings/weekend/study_conductor/index.tsx new file mode 100644 index 0000000000..b71f11eacc --- /dev/null +++ b/src/features/congregation/settings/meeting_settings/weekend/study_conductor/index.tsx @@ -0,0 +1,51 @@ +import { TwoColumnsRow } from '@features/congregation/shared_styles/components'; +import { useAppTranslation, useBreakpoints } from '@hooks/index'; +import useStudyConductor from './useStudyConductor'; +import MenuItem from '@components/menuitem'; +import Select from '@components/select'; +import SwitchWithLabel from '@components/switch_with_label'; +import Typography from '@components/typography'; + +const StudyConductor = () => { + const { t } = useAppTranslation(); + + const { laptopUp } = useBreakpoints(); + + const { + handleWTConductorMainPersonChange, + handleWTConductorToggle, + personsWTCondcutorList, + subtituteWTConductorDisplayed, + wtConductorMainPerson, + } = useStudyConductor(); + + return ( + + + + + + ); +}; + +export default StudyConductor; diff --git a/src/features/congregation/settings/meeting_settings/weekend/study_conductor/useStudyConductor.tsx b/src/features/congregation/settings/meeting_settings/weekend/study_conductor/useStudyConductor.tsx new file mode 100644 index 0000000000..4253ee9d4c --- /dev/null +++ b/src/features/congregation/settings/meeting_settings/weekend/study_conductor/useStudyConductor.tsx @@ -0,0 +1,96 @@ +import { useEffect, useMemo, useState } from 'react'; +import { useRecoilValue } from 'recoil'; +import { + displayNameMeetingsEnableState, + fullnameOptionState, + settingsState, + userDataViewState, +} from '@states/settings'; +import { dbAppSettingsUpdate } from '@services/dexie/settings'; +import { personsActiveState } from '@states/persons'; +import { AssignmentCode } from '@definition/assignment'; +import { personGetDisplayName } from '@utils/common'; + +const useStudyConductor = () => { + const settings = useRecoilValue(settingsState); + const dataView = useRecoilValue(userDataViewState); + const persons = useRecoilValue(personsActiveState); + const useDisplayName = useRecoilValue(displayNameMeetingsEnableState); + const fullnameOption = useRecoilValue(fullnameOptionState); + + const [subtituteWTConductorDisplayed, setSubtituteWTConductorDisplayed] = + useState(true); + const [wtConductorMainPerson, setWTConductorMainPerson] = useState(''); + + const personsWTCondcutorList = useMemo(() => { + const elligiblePersons = persons.filter((record) => + record.person_data.assignments.find( + (item) => + item._deleted === false && + item.code === AssignmentCode.WM_WTStudyConductor + ) + ); + + const result = elligiblePersons.map((person) => { + return { + label: personGetDisplayName(person, useDisplayName, fullnameOption), + value: person.person_uid, + }; + }); + + return result; + }, [persons, useDisplayName, fullnameOption]); + + const handleWTConductorToggle = async () => { + const weekendSettings = structuredClone( + settings.cong_settings.weekend_meeting + ); + + const current = weekendSettings.find((record) => record.type === dataView); + + current.substitute_w_study_conductor_displayed.value = + !subtituteWTConductorDisplayed; + current.substitute_w_study_conductor_displayed.updatedAt = + new Date().toISOString(); + + await dbAppSettingsUpdate({ + 'cong_settings.weekend_meeting': weekendSettings, + }); + }; + + const handleWTConductorMainPersonChange = async (value: string) => { + const weekendSettings = structuredClone( + settings.cong_settings.weekend_meeting + ); + + const current = weekendSettings.find((record) => record.type === dataView); + + current.w_study_conductor_default.value = value; + current.w_study_conductor_default.updatedAt = new Date().toISOString(); + + await dbAppSettingsUpdate({ + 'cong_settings.weekend_meeting': weekendSettings, + }); + }; + + useEffect(() => { + const weekendSettings = settings.cong_settings.weekend_meeting.find( + (record) => record.type === dataView + ); + + setSubtituteWTConductorDisplayed( + weekendSettings.substitute_w_study_conductor_displayed.value + ); + setWTConductorMainPerson(weekendSettings.w_study_conductor_default.value); + }, [settings, dataView]); + + return { + handleWTConductorMainPersonChange, + wtConductorMainPerson, + personsWTCondcutorList, + handleWTConductorToggle, + subtituteWTConductorDisplayed, + }; +}; + +export default useStudyConductor; diff --git a/src/features/congregation/settings/meeting_settings/weekend/useWeekend.tsx b/src/features/congregation/settings/meeting_settings/weekend/useWeekend.tsx deleted file mode 100644 index 8eff245938..0000000000 --- a/src/features/congregation/settings/meeting_settings/weekend/useWeekend.tsx +++ /dev/null @@ -1,211 +0,0 @@ -import { useEffect, useMemo, useState } from 'react'; -import { useRecoilValue } from 'recoil'; -import { - displayNameMeetingsEnableState, - fullnameOptionState, - settingsState, - userDataViewState, -} from '@states/settings'; -import { generateDateFromTime } from '@utils/date'; -import { dbAppSettingsUpdate } from '@services/dexie/settings'; -import { formatDate } from '@services/dateformat'; -import { personsActiveState } from '@states/persons'; -import { AssignmentCode } from '@definition/assignment'; -import { personGetDisplayName } from '@utils/common'; - -const useWeekendSettings = () => { - const settings = useRecoilValue(settingsState); - const dataView = useRecoilValue(userDataViewState); - const persons = useRecoilValue(personsActiveState); - const useDisplayName = useRecoilValue(displayNameMeetingsEnableState); - const fullnameOption = useRecoilValue(fullnameOptionState); - - const [hour24, setHour24] = useState(false); - const [meetingDay, setMeetingDay] = useState(''); - const [meetingTime, setMeetingTime] = useState(null); - const [autoAssignOpeningPrayer, setAutoAssignOpeningPrayer] = useState(false); - const [substituteSpeakerEnabled, setSubstituteSpeakerEnabled] = - useState(false); - const [subtituteWTConductorDisplayed, setSubtituteWTConductorDisplayed] = - useState(true); - const [wtConductorMainPerson, setWTConductorMainPerson] = useState(''); - const [monthlyOverlapShown, setMonthlyOverlapShown] = useState(true); - - const personsWTCondcutorList = useMemo(() => { - const elligiblePersons = persons.filter((record) => - record.person_data.assignments.find( - (item) => - item._deleted === false && - item.code === AssignmentCode.WM_WTStudyConductor - ) - ); - - const result = elligiblePersons.map((person) => { - return { - label: personGetDisplayName(person, useDisplayName, fullnameOption), - value: person.person_uid, - }; - }); - - return result; - }, [persons, useDisplayName, fullnameOption]); - - const handleMeetingDayChange = async (value: number) => { - const weekendSettings = structuredClone( - settings.cong_settings.weekend_meeting - ); - - const current = weekendSettings.find((record) => record.type === dataView); - - current.weekday.value = value; - current.weekday.updatedAt = new Date().toISOString(); - - await dbAppSettingsUpdate({ - 'cong_settings.weekend_meeting': weekendSettings, - }); - }; - - const handleMeetingTimeChange = async (value: Date) => { - const time = value ? formatDate(value, 'HH:mm') : '00:00'; - - const weekendSettings = structuredClone( - settings.cong_settings.weekend_meeting - ); - - const current = weekendSettings.find((record) => record.type === dataView); - - current.time.value = time; - current.time.updatedAt = new Date().toISOString(); - - await dbAppSettingsUpdate({ - 'cong_settings.weekend_meeting': weekendSettings, - }); - }; - - const handleAutoOpeningPrayerToggle = async () => { - const weekendSettings = structuredClone( - settings.cong_settings.weekend_meeting - ); - - const current = weekendSettings.find((record) => record.type === dataView); - - current.opening_prayer_auto_assigned.value = !autoAssignOpeningPrayer; - current.opening_prayer_auto_assigned.updatedAt = new Date().toISOString(); - - await dbAppSettingsUpdate({ - 'cong_settings.weekend_meeting': weekendSettings, - }); - }; - - const handleSubstituteSpeakerToggle = async () => { - const weekendSettings = structuredClone( - settings.cong_settings.weekend_meeting - ); - - const current = weekendSettings.find((record) => record.type === dataView); - - current.substitute_speaker_enabled.value = !substituteSpeakerEnabled; - current.substitute_speaker_enabled.updatedAt = new Date().toISOString(); - - await dbAppSettingsUpdate({ - 'cong_settings.weekend_meeting': weekendSettings, - }); - }; - - const handleWTConductorToggle = async () => { - const weekendSettings = structuredClone( - settings.cong_settings.weekend_meeting - ); - - const current = weekendSettings.find((record) => record.type === dataView); - - current.substitute_w_study_conductor_displayed.value = - !subtituteWTConductorDisplayed; - current.substitute_w_study_conductor_displayed.updatedAt = - new Date().toISOString(); - - await dbAppSettingsUpdate({ - 'cong_settings.weekend_meeting': weekendSettings, - }); - }; - - const handleMonthlyOverlapToggle = async () => { - const weekendSettings = structuredClone( - settings.cong_settings.weekend_meeting - ); - - const current = weekendSettings.find((record) => record.type === dataView); - - current.consecutive_monthly_parts_notice_shown.value = !monthlyOverlapShown; - current.consecutive_monthly_parts_notice_shown.updatedAt = - new Date().toISOString(); - - await dbAppSettingsUpdate({ - 'cong_settings.weekend_meeting': weekendSettings, - }); - }; - - const handleWTConductorMainPersonChange = async (value: string) => { - const weekendSettings = structuredClone( - settings.cong_settings.weekend_meeting - ); - - const current = weekendSettings.find((record) => record.type === dataView); - - current.w_study_conductor_default.value = value; - current.w_study_conductor_default.updatedAt = new Date().toISOString(); - - await dbAppSettingsUpdate({ - 'cong_settings.weekend_meeting': weekendSettings, - }); - }; - - useEffect(() => { - const hourFormat = settings.cong_settings.format_24h_enabled.find( - (record) => record.type === dataView - ); - - setHour24(hourFormat.value); - - const weekendSettings = settings.cong_settings.weekend_meeting.find( - (record) => record.type === dataView - ); - - setMeetingDay(weekendSettings.weekday.value); - setMeetingTime(generateDateFromTime(weekendSettings.time.value)); - setAutoAssignOpeningPrayer( - weekendSettings.opening_prayer_auto_assigned.value - ); - setSubstituteSpeakerEnabled( - weekendSettings.substitute_speaker_enabled.value - ); - setSubtituteWTConductorDisplayed( - weekendSettings.substitute_w_study_conductor_displayed.value - ); - setWTConductorMainPerson(weekendSettings.w_study_conductor_default.value); - setMonthlyOverlapShown( - weekendSettings.consecutive_monthly_parts_notice_shown.value - ); - }, [settings, dataView]); - - return { - meetingDay, - handleMeetingDayChange, - hour24, - meetingTime, - handleMeetingTimeChange, - autoAssignOpeningPrayer, - handleAutoOpeningPrayerToggle, - handleWTConductorMainPersonChange, - wtConductorMainPerson, - personsWTCondcutorList, - handleWTConductorToggle, - handleMonthlyOverlapToggle, - handleSubstituteSpeakerToggle, - substituteSpeakerEnabled, - subtituteWTConductorDisplayed, - monthlyOverlapShown, - }; -}; - -export default useWeekendSettings; diff --git a/src/features/meetings/midweek_editor/quick_settings/index.tsx b/src/features/meetings/midweek_editor/quick_settings/index.tsx new file mode 100644 index 0000000000..3271fd7988 --- /dev/null +++ b/src/features/meetings/midweek_editor/quick_settings/index.tsx @@ -0,0 +1,49 @@ +import { Stack } from '@mui/material'; +import { useAppTranslation } from '@hooks/index'; +import { QuickSettingsMidweekMeetingProps } from './index.types'; +import AssignmentPreferences from '@features/congregation/settings/meeting_settings/midweek/assignment_preferences'; +import AuxiliaryClassroom from '@features/congregation/settings/meeting_settings/midweek/auxiliary_classroom'; +import DayTime from '@features/congregation/settings/meeting_settings/midweek/day_time'; +import DisplayName from '@features/congregation/settings/meeting_forms/display_name'; +import Divider from '@components/divider'; +import MidweekExactDate from '@features/congregation/settings/meeting_forms/midweek_exact_date'; +import QuickSettings from '@features/quick_settings'; +import Typography from '@components/typography'; + +const QuickSettingsMidweekMeeting = ({ + onClose, + open, +}: QuickSettingsMidweekMeetingProps) => { + const { t } = useAppTranslation(); + + return ( + + } + > + + + + + + + + + + + + + + + {t('tr_assignmentPreferences')} + + + + + + ); +}; + +export default QuickSettingsMidweekMeeting; diff --git a/src/features/meetings/midweek_editor/quick_settings/index.types.ts b/src/features/meetings/midweek_editor/quick_settings/index.types.ts new file mode 100644 index 0000000000..35e0b8b3de --- /dev/null +++ b/src/features/meetings/midweek_editor/quick_settings/index.types.ts @@ -0,0 +1,4 @@ +export type QuickSettingsMidweekMeetingProps = { + open: boolean; + onClose: VoidFunction; +}; diff --git a/src/features/meetings/weekend_editor/quick_settings/index.tsx b/src/features/meetings/weekend_editor/quick_settings/index.tsx new file mode 100644 index 0000000000..a9d8b6512f --- /dev/null +++ b/src/features/meetings/weekend_editor/quick_settings/index.tsx @@ -0,0 +1,52 @@ +import { Stack } from '@mui/material'; +import { useAppTranslation } from '@hooks/index'; +import { QuickSettingsWeekendMeetingProps } from './index.types'; +import DayTime from '@features/congregation/settings/meeting_settings/weekend/day_time'; +import AssignmentPreferences from '@features/congregation/settings/meeting_settings/weekend/assignment_preferences'; +import DisplayName from '@features/congregation/settings/meeting_forms/display_name'; +import Divider from '@components/divider'; +import MonthlyWarning from '@features/congregation/settings/meeting_settings/weekend/monthly_warning'; +import OutgoingTalkAccess from '@features/congregation/settings/congregation_privacy/outgoing_talk_access'; +import QuickSettings from '@features/quick_settings'; +import StudyConductor from '@features/congregation/settings/meeting_settings/weekend/study_conductor'; +import Typography from '@components/typography'; + +const QuickSettingsWeekendMeeting = ({ + onClose, + open, +}: QuickSettingsWeekendMeetingProps) => { + const { t } = useAppTranslation(); + + return ( + + } + > + + + + + + + + + + + + + + + + + {t('tr_assignmentPreferences')} + + + + + + ); +}; + +export default QuickSettingsWeekendMeeting; diff --git a/src/features/meetings/weekend_editor/quick_settings/index.types.ts b/src/features/meetings/weekend_editor/quick_settings/index.types.ts new file mode 100644 index 0000000000..f663d2e3f2 --- /dev/null +++ b/src/features/meetings/weekend_editor/quick_settings/index.types.ts @@ -0,0 +1,4 @@ +export type QuickSettingsWeekendMeetingProps = { + open: boolean; + onClose: VoidFunction; +}; diff --git a/src/layouts/root_layout/index.tsx b/src/layouts/root_layout/index.tsx index 0f8ec290ff..3aa600bab5 100644 --- a/src/layouts/root_layout/index.tsx +++ b/src/layouts/root_layout/index.tsx @@ -72,7 +72,7 @@ const RootLayout = ({ updatePwa }: { updatePwa: VoidFunction }) => { {isSupported && ( <> {isOpenContact && } - {isOpenAbout && } + {isOpenAbout && } {isOpenSupport && } {isAppLoad && !isDemo && } diff --git a/src/locales/en/meetings.json b/src/locales/en/meetings.json index 67199e0d37..e04dd3a90c 100644 --- a/src/locales/en/meetings.json +++ b/src/locales/en/meetings.json @@ -144,5 +144,6 @@ "tr_outgoingTalkDeleteDesc": "Are you sure you want to delete this outgoing talk schedule?", "tr_deliveredBy": "Delivered by {{ name }}", "tr_toCurrentWeek": "To current week", - "tr_recordAttendance": "Record attendance" + "tr_recordAttendance": "Record attendance", + "tr_assignmentPreferences": "Assignment preferences" } diff --git a/src/pages/meetings/midweek/index.tsx b/src/pages/meetings/midweek/index.tsx index 3ee8dd0f61..36ad1360f1 100644 --- a/src/pages/meetings/midweek/index.tsx +++ b/src/pages/meetings/midweek/index.tsx @@ -10,6 +10,7 @@ import useMidweek from './useMidweek'; import Button from '@components/button'; import MidweekEditor from '@features/meetings/midweek_editor'; import PageTitle from '@components/page_title'; +import QuickSettingsMidweekMeeting from '@features/meetings/midweek_editor/quick_settings'; import SchedulePublish from '@features/meetings/schedule_publish'; const MidweekMeeting = () => { @@ -29,6 +30,9 @@ const MidweekMeeting = () => { handleOpenPublish, openPublish, isConnected, + handleCloseQuickSettings, + handleOpenQuickSettings, + quickSettingsOpen, } = useMidweek(); return ( @@ -39,6 +43,13 @@ const MidweekMeeting = () => { flexDirection: 'column', }} > + {quickSettingsOpen && ( + + )} + {openExport && ( )} @@ -61,6 +72,7 @@ const MidweekMeeting = () => { diff --git a/src/pages/meetings/midweek/useMidweek.tsx b/src/pages/meetings/midweek/useMidweek.tsx index ec4aec9fcc..b640d93d00 100644 --- a/src/pages/meetings/midweek/useMidweek.tsx +++ b/src/pages/meetings/midweek/useMidweek.tsx @@ -10,6 +10,11 @@ const useMidweek = () => { const [openAutofill, setOpenAutofill] = useState(false); const [openExport, setOpenExport] = useState(false); const [openPublish, setOpenPublish] = useState(false); + const [quickSettingsOpen, setQuickSettingsOpen] = useState(false); + + const handleOpenQuickSettings = () => setQuickSettingsOpen(true); + + const handleCloseQuickSettings = () => setQuickSettingsOpen(false); const hasWeeks = sources.length > 0; @@ -37,6 +42,9 @@ const useMidweek = () => { handleOpenPublish, handleClosePublish, isConnected, + quickSettingsOpen, + handleOpenQuickSettings, + handleCloseQuickSettings, }; }; diff --git a/src/pages/meetings/weekend/index.tsx b/src/pages/meetings/weekend/index.tsx index 3a09c51067..cdb364a867 100644 --- a/src/pages/meetings/weekend/index.tsx +++ b/src/pages/meetings/weekend/index.tsx @@ -4,8 +4,9 @@ import { ScheduleAutofillDialog, WeekSelector } from '@features/index'; import { useAppTranslation, useBreakpoints } from '@hooks/index'; import useWeekend from './useWeekend'; import Button from '@components/button'; -import PageTitle from '@components/page_title'; import OutgoingTalks from '@features/meetings/outgoing_talks'; +import PageTitle from '@components/page_title'; +import QuickSettingsWeekendMeeting from '@features/meetings/weekend_editor/quick_settings'; import SchedulePublish from '@features/meetings/schedule_publish'; import WeekendEditor from '@features/meetings/weekend_editor'; import WeekendExport from '@features/meetings/weekend_export'; @@ -27,6 +28,9 @@ const WeekendMeeting = () => { handleOpenPublish, isConnected, openPublish, + handleCloseQuickSettings, + handleOpenQuickSettings, + quickSettingsOpen, } = useWeekend(); return ( @@ -37,6 +41,13 @@ const WeekendMeeting = () => { flexDirection: 'column', }} > + {quickSettingsOpen && ( + + )} + {openExport && ( )} @@ -59,6 +70,7 @@ const WeekendMeeting = () => { diff --git a/src/pages/meetings/weekend/useWeekend.tsx b/src/pages/meetings/weekend/useWeekend.tsx index 320c3f65ff..eb2d853951 100644 --- a/src/pages/meetings/weekend/useWeekend.tsx +++ b/src/pages/meetings/weekend/useWeekend.tsx @@ -10,9 +10,14 @@ const useWeekend = () => { const [openAutofill, setOpenAutofill] = useState(false); const [openExport, setOpenExport] = useState(false); const [openPublish, setOpenPublish] = useState(false); + const [quickSettingsOpen, setQuickSettingsOpen] = useState(false); const hasWeeks = sources.length > 0; + const handleOpenQuickSettings = () => setQuickSettingsOpen(true); + + const handleCloseQuickSettings = () => setQuickSettingsOpen(false); + const handleOpenAutofill = () => setOpenAutofill(true); const handleCloseAutofill = () => setOpenAutofill(false); @@ -37,6 +42,9 @@ const useWeekend = () => { handleOpenPublish, handleClosePublish, isConnected, + quickSettingsOpen, + handleOpenQuickSettings, + handleCloseQuickSettings, }; };