diff --git a/converter/svg/sources/name=icon.svg b/converter/svg/sources/name=icon.svg new file mode 100644 index 0000000000..76ab0de05c --- /dev/null +++ b/converter/svg/sources/name=icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/converter/svg/sources/name=ministry.svg b/converter/svg/sources/name=ministry.svg new file mode 100644 index 0000000000..aca2744186 --- /dev/null +++ b/converter/svg/sources/name=ministry.svg @@ -0,0 +1,3 @@ + + + diff --git a/converter/svg/sources/name=outgoind-speaker.svg b/converter/svg/sources/name=outgoind-speaker.svg new file mode 100644 index 0000000000..9d133e58e5 --- /dev/null +++ b/converter/svg/sources/name=outgoind-speaker.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/converter/svg/sources/name=service.svg b/converter/svg/sources/name=service.svg new file mode 100644 index 0000000000..6eb6ce3e43 --- /dev/null +++ b/converter/svg/sources/name=service.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/converter/svg/sources/name=talker.svg b/converter/svg/sources/name=talker.svg new file mode 100644 index 0000000000..76ab0de05c --- /dev/null +++ b/converter/svg/sources/name=talker.svg @@ -0,0 +1,4 @@ + + + + diff --git a/converter/svg/sources/name=watchtower-study.svg b/converter/svg/sources/name=watchtower-study.svg new file mode 100644 index 0000000000..7ff01e4a66 --- /dev/null +++ b/converter/svg/sources/name=watchtower-study.svg @@ -0,0 +1,3 @@ + + + diff --git a/converter/svg/sources/name=waving-hand.svg b/converter/svg/sources/name=waving-hand.svg new file mode 100644 index 0000000000..7683aedae2 --- /dev/null +++ b/converter/svg/sources/name=waving-hand.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/v3/App.tsx b/src/v3/App.tsx index 068d4ab056..57d813b40f 100644 --- a/src/v3/App.tsx +++ b/src/v3/App.tsx @@ -16,6 +16,7 @@ const MidweekMeeting = lazy(() => import('@pages/meetings/midweek')); const MinistryReport = lazy(() => import('@pages/ministry_report')); const VisitingSpeakers = lazy(() => import('@pages/persons/visiting_speakers')); const WeekendMeeting = lazy(() => import('@pages/meetings/weekend')); +const WeeklySchedules = lazy(() => import('@pages/meetings/schedules')); const ComponentsPreview = lazy(() => import('@components/preview')); const PdfPreview = lazy(() => import('@components/preview/PDF_Peview')); @@ -48,6 +49,7 @@ const App = ({ updatePwa }: { updatePwa: VoidFunction }) => { { path: '/visiting-speakers', element: }, { path: '/midweek-meeting', element: }, { path: '/weekend-meeting', element: }, + { path: '/weekly-schedules', element: }, { path: '*', element: }, ], }, diff --git a/src/v3/components/badge/index.tsx b/src/v3/components/badge/index.tsx index 7cf05eed1a..ec176a3fd3 100644 --- a/src/v3/components/badge/index.tsx +++ b/src/v3/components/badge/index.tsx @@ -99,7 +99,7 @@ const CustomBadge = (props: BadgePropsType) => { { sx={{ border: '1px', borderColor: 'var(--accent-350)', - height: '22px', + height: props.multiLine ? 'unset' : '22px', background: getBackgroundColor(), display: 'flex', flexDirection: 'row', @@ -164,7 +164,7 @@ const CustomBadge = (props: BadgePropsType) => { ; +}; + +const IconIcon = ({ color = '#222222', width = 24, height = 24, sx = {} }: IconProps) => { + return ( + + + + + + + ); +}; + +export default IconIcon; diff --git a/src/v3/components/icons/IconMinistry.tsx b/src/v3/components/icons/IconMinistry.tsx new file mode 100644 index 0000000000..3a9b412217 --- /dev/null +++ b/src/v3/components/icons/IconMinistry.tsx @@ -0,0 +1,25 @@ +import { SvgIcon, SxProps, Theme } from '@mui/material'; + +type IconProps = { + color?: string; + width?: number; + height?: number; + sx?: SxProps; +}; + +const IconMinistry = ({ color = '#222222', width = 24, height = 24, sx = {} }: IconProps) => { + return ( + + + + + + ); +}; + +export default IconMinistry; diff --git a/src/v3/components/icons/IconOutgoindSpeaker.tsx b/src/v3/components/icons/IconOutgoindSpeaker.tsx new file mode 100644 index 0000000000..70efc02434 --- /dev/null +++ b/src/v3/components/icons/IconOutgoindSpeaker.tsx @@ -0,0 +1,39 @@ +import { SvgIcon, SxProps, Theme } from '@mui/material'; + +type IconProps = { + color?: string; + width?: number; + height?: number; + sx?: SxProps; +}; + +const IconOutgoindSpeaker = ({ color = '#222222', width = 24, height = 24, sx = {} }: IconProps) => { + return ( + + + + + + + + + ); +}; + +export default IconOutgoindSpeaker; diff --git a/src/v3/components/icons/IconService.tsx b/src/v3/components/icons/IconService.tsx new file mode 100644 index 0000000000..5d23ecfdc4 --- /dev/null +++ b/src/v3/components/icons/IconService.tsx @@ -0,0 +1,37 @@ +import { SvgIcon, SxProps, Theme } from '@mui/material'; + +type IconProps = { + color?: string; + width?: number; + height?: number; + sx?: SxProps; +}; + +const IconService = ({ color = '#222222', width = 24, height = 24, sx = {} }: IconProps) => { + return ( + + + + + + + + ); +}; + +export default IconService; diff --git a/src/v3/components/icons/IconTalker.tsx b/src/v3/components/icons/IconTalker.tsx new file mode 100644 index 0000000000..d64fd69767 --- /dev/null +++ b/src/v3/components/icons/IconTalker.tsx @@ -0,0 +1,31 @@ +import { SvgIcon, SxProps, Theme } from '@mui/material'; + +type IconProps = { + color?: string; + width?: number; + height?: number; + sx?: SxProps; +}; + +const IconTalker = ({ color = '#222222', width = 24, height = 24, sx = {} }: IconProps) => { + return ( + + + + + + + ); +}; + +export default IconTalker; diff --git a/src/v3/components/icons/IconWatchtowerStudy.tsx b/src/v3/components/icons/IconWatchtowerStudy.tsx new file mode 100644 index 0000000000..ae2821dcd9 --- /dev/null +++ b/src/v3/components/icons/IconWatchtowerStudy.tsx @@ -0,0 +1,25 @@ +import { SvgIcon, SxProps, Theme } from '@mui/material'; + +type IconProps = { + color?: string; + width?: number; + height?: number; + sx?: SxProps; +}; + +const IconWatchtowerStudy = ({ color = '#222222', width = 24, height = 24, sx = {} }: IconProps) => { + return ( + + + + + + ); +}; + +export default IconWatchtowerStudy; diff --git a/src/v3/components/icons/IconWavingHand.tsx b/src/v3/components/icons/IconWavingHand.tsx new file mode 100644 index 0000000000..b9f0da594d --- /dev/null +++ b/src/v3/components/icons/IconWavingHand.tsx @@ -0,0 +1,36 @@ +import { SvgIcon, SxProps, Theme } from '@mui/material'; + +type IconProps = { + color?: string; + width?: number; + height?: number; + sx?: SxProps; +}; + +const IconWavingHand = ({ color = '#222222', width = 24, height = 24, sx = {} }: IconProps) => { + return ( + + + + + + + + + + + ); +}; + +export default IconWavingHand; diff --git a/src/v3/components/icons/index.ts b/src/v3/components/icons/index.ts index 52ed8e6b74..9e02cc125c 100644 --- a/src/v3/components/icons/index.ts +++ b/src/v3/components/icons/index.ts @@ -107,6 +107,7 @@ export { default as IconHelp } from './IconHelp'; export { default as IconHide } from './IconHide'; export { default as IconHistory } from './IconHistory'; export { default as IconHome } from './IconHome'; +export { default as IconIcon } from './IconIcon'; export { default as IconImage } from './IconImage'; export { default as IconImgAdd } from './IconImgAdd'; export { default as IconImgDelete } from './IconImgDelete'; @@ -144,6 +145,7 @@ export { default as IconMicrophone } from './IconMicrophone'; export { default as IconMicrosoft } from './IconMicrosoft'; export { default as IconMinistryPart } from './IconMinistryPart'; export { default as IconMinistryReport } from './IconMinistryReport'; +export { default as IconMinistry } from './IconMinistry'; export { default as IconMore } from './IconMore'; export { default as IconMoveAround } from './IconMoveAround'; export { default as IconMoveBack } from './IconMoveBack'; @@ -161,6 +163,7 @@ export { default as IconNormalPin } from './IconNormalPin'; export { default as IconNotifications } from './IconNotifications'; export { default as IconOffCircle } from './IconOffCircle'; export { default as IconOnCircle } from './IconOnCircle'; +export { default as IconOutgoindSpeaker } from './IconOutgoindSpeaker'; export { default as IconPanelClose } from './IconPanelClose'; export { default as IconPanelOpen } from './IconPanelOpen'; export { default as IconPark } from './IconPark'; @@ -221,6 +224,7 @@ export { default as IconSchool } from './IconSchool'; export { default as IconSearch } from './IconSearch'; export { default as IconSend } from './IconSend'; export { default as IconSent } from './IconSent'; +export { default as IconService } from './IconService'; export { default as IconSettings } from './IconSettings'; export { default as IconSetup } from './IconSetup'; export { default as IconShapes } from './IconShapes'; @@ -245,6 +249,7 @@ export { default as IconSun } from './IconSun'; export { default as IconSync } from './IconSync'; export { default as IconSynced } from './IconSynced'; export { default as IconTalk } from './IconTalk'; +export { default as IconTalker } from './IconTalker'; export { default as IconTest } from './IconTest'; export { default as IconTimeChange } from './IconTimeChange'; export { default as IconToggle } from './IconToggle'; @@ -260,6 +265,8 @@ export { default as IconVisibilityOff } from './IconVisibilityOff'; export { default as IconVisitingSpeaker } from './IconVisitingSpeaker'; export { default as IconVisitors } from './IconVisitors'; export { default as IconWallet } from './IconWallet'; +export { default as IconWatchtowerStudy } from './IconWatchtowerStudy'; +export { default as IconWavingHand } from './IconWavingHand'; export { default as IconWeek } from './IconWeek'; export { default as IconWork } from './IconWork'; export { default as IconYahoo } from './IconYahoo'; diff --git a/src/v3/features/meetings/weekly_schedules/ScheduleComponents.tsx b/src/v3/features/meetings/weekly_schedules/ScheduleComponents.tsx new file mode 100644 index 0000000000..79be2a2846 --- /dev/null +++ b/src/v3/features/meetings/weekly_schedules/ScheduleComponents.tsx @@ -0,0 +1,304 @@ +import { Box, IconButton } from '@mui/material'; +import { IconCheckCircle, IconCopy, IconFemale, IconMale } from '@components/icons'; +import { SnackBar } from '@components/index'; +import { useState } from 'react'; +import useAppTranslation from '@hooks/useAppTranslation'; + +const ScheduleGrid = ({ children }: { children?: React.ReactNode }) => { + return ( + + {children} + + ); +}; + +const ScheduleHeader = ({ text, color, icon }: { text: string; color: string; icon?: React.ReactNode }) => { + return ( + + {icon} + + {text} + + + ); +}; + +const ScheduleItem = ({ children }: { children: React.ReactNode }) => { + return ( + + {children} + + ); +}; + +const ScheduleItemTitle = ({ children }: { children: React.ReactNode }) => { + return ( + + {children} + + ); +}; + +const ScheduleWeekTitle = ({ children, color }: { children: React.ReactNode; color: string }) => { + return ( + ({ + ['&, & > *']: { + display: 'flex', + alignItems: 'center', + gap: '16px', + color: color, + [theme.breakpoints.down('desktop')]: { + flexDirection: 'column', + gap: '8px', + alignItems: 'flex-start', + }, + }, + })} + > + {children} + + ); +}; + +const ScheduleTitle = ({ + children, + color, + cssCounter, +}: { + children: React.ReactNode; + color: string; + cssCounter?: boolean; +}) => { + return ( + + + {children} + + + ); +}; + +const CopyButton = ({ value }: { value: string }) => { + const [isCopied, setIsCopied] = useState(false); + const handleClick = () => { + navigator.clipboard.writeText(value); + setIsCopied(true); + }; + const { t } = useAppTranslation(); + + return ( + <> + + + + } + messageHeader={t('tr_textCopied')} + message="" + onClose={() => setIsCopied(false)} + /> + + ); +}; + +const ScheduleSubtitle = ({ children, isCopyable }: { children: React.ReactNode; isCopyable?: boolean }) => { + return ( + + {children} + {isCopyable && } + + ); +}; + +const ScheduleDescription = ({ children }: { children: React.ReactNode }) => { + return ( + + {children} + + ); +}; + +// Use Multiple as Children :) +const ScheduleMemberClassRoom = ({ children, classRoomName }: { children: React.ReactNode; classRoomName: string }) => { + return ( + + + {classRoomName} + + {children} + + ); +}; + +// Use Multiple or as Children :) +const ScheduleMembers = ({ children }: { children: React.ReactNode }) => { + return ( + + {children} + + ); +}; + +const ScheduleMemberRow = ({ + type, + name, + female, + active, +}: { + type?: string; + name: string; + female?: boolean; + active?: boolean; +}) => { + return ( + + + {type} + + + + {female ? : } + + {name} + + + + + ); +}; + +export { + ScheduleGrid, + ScheduleHeader, + ScheduleItem, + ScheduleItemTitle, + ScheduleWeekTitle, + ScheduleTitle, + ScheduleSubtitle, + ScheduleDescription, + ScheduleMembers, + ScheduleMemberClassRoom, + ScheduleMemberRow, +}; diff --git a/src/v3/features/meetings/weekly_schedules/SchedulePickerHeader.tsx b/src/v3/features/meetings/weekly_schedules/SchedulePickerHeader.tsx new file mode 100644 index 0000000000..3ac1443fd2 --- /dev/null +++ b/src/v3/features/meetings/weekly_schedules/SchedulePickerHeader.tsx @@ -0,0 +1,87 @@ +import { IconDate } from '@components/icons'; +import { Badge } from '@components/index'; +import ScrollableTabs from '@components/scrollable_tabs'; +import useAppTranslation from '@hooks/useAppTranslation'; +import { Box } from '@mui/material'; + +const days = []; +for (let i = 0; i < 30; i++) { + days.push({ + label: new Date(new Date('9 oct 2024').getTime() + 1000 * 60 * 60 * 24 * 7 * i).toLocaleString('en-US', { + month: 'short', + day: 'numeric', + }), + }); +} + +const SchedulePickerHeader = ({ lastUpdated }: { lastUpdated: string }) => { + const { t } = useAppTranslation(); + return ( + <> + *': { maxWidth: '100% !important' }, + // Math for the gap : + // Screen = 1144px ; gap = 0px + // Screen = 1250px ; gap = 10px (106px => 10px) + // Screen = 1338px ; gap = ~20px (194px => 20px) + '@media (min-width: 1144px)': { + '.MuiTabs-flexContainer': { + gap: 'min(calc((100vw - 1144px)*10/106), 32px)', + }, + }, + '& > * > * > *:first-child, & > * > * > *:last-child': { + padding: '0 10px', + justifyContent: 'flex-start', + width: '60px', + }, + '& > * > * > *:last-child': { + justifyContent: 'flex-end', + }, + }} + > + + + + + + + To current week + + + + ); +}; + +export default SchedulePickerHeader; diff --git a/src/v3/features/meetings/weekly_schedules/midweekMeeting.tsx b/src/v3/features/meetings/weekly_schedules/midweekMeeting.tsx new file mode 100644 index 0000000000..e133c9b1de --- /dev/null +++ b/src/v3/features/meetings/weekly_schedules/midweekMeeting.tsx @@ -0,0 +1,160 @@ +import useAppTranslation from '@hooks/useAppTranslation'; +import SchedulePickerHeader from './SchedulePickerHeader'; +import { + ScheduleDescription, + ScheduleGrid, + ScheduleHeader, + ScheduleItem, + ScheduleItemTitle, + ScheduleMemberClassRoom, + ScheduleMemberRow, + ScheduleMembers, + ScheduleTitle, + ScheduleWeekTitle, +} from './ScheduleComponents'; +import { IconDiamond, IconLivingPart, IconMinistry, IconSong, IconWavingHand } from '@components/icons'; +import { Box } from '@mui/material'; +import { Badge } from '@components/index'; + +const MidweekMeeting = () => { + const lastUpdated = new Date().toLocaleString('en-US', { + day: 'numeric', + month: 'short', + year: 'numeric', + }); + const { t } = useAppTranslation(); + + return ( + + + + + + + 8 November 2023 |{' '} + + 2 Corinthians 4-6 + + + } + /> + + + + + + + + + Song 109 – “Jehovah’s Warm Appeal: “Be Wise, My Son” + + + + + + } /> + + + + + Song 109 – “Jehovah’s Warm Appeal: “Be Wise, My Son” + + + + + + “God’s Loyal Love Protects Us From Satan’s Lies” + + + + + + + + {t('tr_tgwGems')} + + + + + + + + + {t('tr_bibleReading')} + + (3 Min.) Job 9:20-35 (th study 11) + + + + + + } + /> + + + + {t('tr_initialCall')} + + + (3 Min.) Begin with the sample conversation topic. Offer a publication from the Teaching Toolbox. (th + study 17) + + + + + + + + + + + + + + } /> + + + + “Help Nonreligious People Come to Know Their Creator” + + (3 Min.) Job 9:20-35 (th study 11) + + + + + + + + + Song 109 – “Jehovah’s Warm Appeal: “Be Wise, My Son” + + + + + + + + + ); +}; + +export default MidweekMeeting; diff --git a/src/v3/features/meetings/weekly_schedules/outgoingTalks.tsx b/src/v3/features/meetings/weekly_schedules/outgoingTalks.tsx new file mode 100644 index 0000000000..ca3ef41612 --- /dev/null +++ b/src/v3/features/meetings/weekly_schedules/outgoingTalks.tsx @@ -0,0 +1,136 @@ +import useAppTranslation from '@hooks/useAppTranslation'; +import { Box } from '@mui/material'; +import { Badge } from '@components/index'; + +import { + ScheduleGrid, + ScheduleHeader, + ScheduleItem, + ScheduleMemberRow, + ScheduleMembers, + ScheduleSubtitle, + ScheduleTitle, +} from './ScheduleComponents'; +import { IconCongregation, IconInfo, IconWatchtowerStudy } from '@components/icons'; + +const OutgoingTalks = () => { + const { t } = useAppTranslation(); + const lastUpdated = new Date().toLocaleString('en-US', { + day: 'numeric', + month: 'short', + year: 'numeric', + }); + + return ( + + + + + + {t('tr_infoOutgoingTalk')} + + + + + + + + + + Public talk — {' '} + Berdychyv-Ost + + “The Resurrection — Why That Hope Should Be Real to You” + + + + + + + + + Public talk — {' '} + Berdychyv-Ost + + “Real Help for the Family” + + + + + + + + + + Public talk — {' '} + Berdychyv-Ost + + “The Resurrection — Why That Hope Should Be Real to You” + + + + + + + + + + Public talk — {' '} + Berdychyv-Ost + + “Real Help for the Family” + + + + + + + + + Public talk — {' '} + Berdychyv-Ost + + “The Resurrection” + + + + + + + + + Public talk — {' '} + Berdychyv-Ost + + “The Resurrection — Why That Hope Should Be Real to You” + + + + + + + + ); +}; + +export default OutgoingTalks; diff --git a/src/v3/features/meetings/weekly_schedules/weekendMeeting.tsx b/src/v3/features/meetings/weekly_schedules/weekendMeeting.tsx new file mode 100644 index 0000000000..4644648191 --- /dev/null +++ b/src/v3/features/meetings/weekly_schedules/weekendMeeting.tsx @@ -0,0 +1,95 @@ +import useAppTranslation from '@hooks/useAppTranslation'; +import { Box } from '@mui/material'; +import SchedulePickerHeader from './SchedulePickerHeader'; +import { + ScheduleDescription, + ScheduleGrid, + ScheduleHeader, + ScheduleItem, + ScheduleItemTitle, + ScheduleMemberRow, + ScheduleMembers, + ScheduleSubtitle, + ScheduleTitle, + ScheduleWeekTitle, +} from './ScheduleComponents'; +import { IconSong, IconTalker, IconWatchtowerStudy } from '@components/icons'; + +const WeekendMeeting = () => { + const { t } = useAppTranslation(); + const lastUpdated = new Date().toLocaleString('en-US', { + day: 'numeric', + month: 'short', + year: 'numeric', + }); + + return ( + + + + + 8 November 2023 + + + + + + + + Song 109 – “Jehovah’s Warm Appeal: “Be Wise, My Son” + + + + + + } /> + + + Public talk + “The Resurrection — Why That Hope Should Be Real to You” + + + + + + } /> + + + + + Song 109 – “Jehovah’s Warm Appeal: “Be Wise, My Son” + + + + + + {t('tr_watchtowerStudy')} + + “Carry What You Must, and Throw Off the Rest” + + + + + + + + + + Song 109 – “Jehovah’s Warm Appeal: “Be Wise, My Son” + + + + + + + + ); +}; + +export default WeekendMeeting; diff --git a/src/v3/pages/dashboard/meetings/index.tsx b/src/v3/pages/dashboard/meetings/index.tsx index 5932141c56..a5f4dc43d3 100644 --- a/src/v3/pages/dashboard/meetings/index.tsx +++ b/src/v3/pages/dashboard/meetings/index.tsx @@ -20,7 +20,11 @@ const MeetingsCard = () => { /> - } primaryText={t('tr_viewAssignmentsSchedule')} /> + } + primaryText={t('tr_viewAssignmentsSchedule')} + path="/weekly-schedules" + /> import('@features/meetings/weekly_schedules/midweekMeeting')); +const WeekendMeeting = lazy(() => import('@features/meetings/weekly_schedules/weekendMeeting')); +const OutgoingTalks = lazy(() => import('@features/meetings/weekly_schedules/outgoingTalks')); + +const WeeklySchedules = () => { + const { t } = useAppTranslation(); + + const tabs = [ + { + label: t('tr_midweekMeeting'), + Component: , + }, + { + label: t('tr_weekendMeeting'), + Component: , + }, + { + label: t('tr_outgoingTalks'), + Component: , + }, + ]; + + return ( +
+ + + + + + +
+ ); +}; + +export default WeeklySchedules;