Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions converter/svg/sources/name=door.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const MeetingAttendance = lazy(
const FieldServiceReportsPage = lazy(
() => import('@pages/reports/field_service')
);
const MeetingDuties = lazy(() => import('@pages/meetings/duties'));
const MidweekMeeting = lazy(() => import('@pages/meetings/midweek'));
const MinistryReport = lazy(() => import('@pages/ministry/ministry_report'));
const ServiceYear = lazy(() => import('@pages/ministry/service_year'));
Expand Down Expand Up @@ -88,6 +89,7 @@ const App = ({ updatePwa }: { updatePwa: VoidFunction }) => {
isServiceCommittee,
isGroup,
isLanguageGroupOverseer,
isDutiesEditor,
} = useCurrentUser();

const [adapterLocale, setAdapterLocale] = useAtom(appLocaleState);
Expand Down Expand Up @@ -207,6 +209,14 @@ const App = ({ updatePwa }: { updatePwa: VoidFunction }) => {
],
},

// meeeting duties editor routes
{
element: <RouteProtected allowed={isDutiesEditor} />,
children: [
{ path: '/meeting-duties', element: <MeetingDuties /> },
],
},

// midweek editor routes
{
element: <RouteProtected allowed={isMidweekEditor} />,
Expand Down
52 changes: 52 additions & 0 deletions src/components/icons/IconDoor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { SvgIcon, SxProps, Theme } from '@mui/material';

type IconProps = {
color?: string;
width?: number;
height?: number;
sx?: SxProps<Theme>;
className?: string;
};

const IconDoor = ({
color = '#222222',
width = 24,
height = 24,
sx = {},
className,
}: IconProps) => {
return (
<SvgIcon
className={`organized-icon-door ${className}`}
sx={{ width: `${width}px`, height: `${height}px`, ...sx }}
>
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<mask
id="mask0_11463_432745"
style={{ maskType: 'alpha' }}
maskUnits="userSpaceOnUse"
x="0"
y="0"
width="24"
height="24"
>
<rect width="24" height="24" fill="#D9D9D9" />
</mask>
<g mask="url(#mask0_11463_432745)">
<path
d="M11.0002 12.8845C11.2515 12.8845 11.4618 12.7983 11.631 12.626C11.8001 12.4535 11.8847 12.2448 11.8847 12C11.8847 11.7487 11.8001 11.5384 11.631 11.3693C11.4618 11.2001 11.2515 11.1155 11.0002 11.1155C10.7554 11.1155 10.5467 11.2001 10.3742 11.3693C10.2019 11.5384 10.1157 11.7487 10.1157 12C10.1157 12.2448 10.2019 12.4535 10.3742 12.626C10.5467 12.7983 10.7554 12.8845 11.0002 12.8845ZM7.00021 20.5V19L13.5002 18.1538V6.6635C13.5002 6.34933 13.4012 6.073 13.2032 5.8345C13.005 5.59617 12.7573 5.46033 12.46 5.427L7.30796 4.75V3.25L12.6732 3.95775C13.3489 4.05892 13.9056 4.36208 14.3435 4.86725C14.7813 5.37242 15.0002 5.96283 15.0002 6.6385V19.4193L7.00021 20.5ZM3.73096 20.5V19H5.50021V5.05775C5.50021 4.54242 5.67679 4.11225 6.02996 3.76725C6.38329 3.42242 6.80929 3.25 7.30796 3.25H16.6925C17.2078 3.25 17.638 3.42242 17.983 3.76725C18.3278 4.11225 18.5002 4.54242 18.5002 5.05775V19H20.2695V20.5H3.73096ZM7.00021 19H17.0002V5.05775C17.0002 4.96792 16.9714 4.89417 16.9137 4.8365C16.856 4.77883 16.7823 4.75 16.6925 4.75H7.30796C7.21812 4.75 7.14437 4.77883 7.08671 4.8365C7.02904 4.89417 7.00021 4.96792 7.00021 5.05775V19Z"
fill={color}
/>
</g>
</svg>
</SvgIcon>
);
};

export default IconDoor;
1 change: 1 addition & 0 deletions src/components/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ export { default as IconDiamond } from './IconDiamond';
export { default as IconDisqualified } from './IconDisqualified';
export { default as IconDistance } from './IconDistance';
export { default as IconDonate } from './IconDonate';
export { default as IconDoor } from './IconDoor';
export { default as IconDown } from './IconDown';
export { default as IconDownload } from './IconDownload';
export { default as IconDragHandle } from './IconDragHandle';
Expand Down
23 changes: 11 additions & 12 deletions src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -369,18 +369,6 @@ export const APP_READ_ONLY_ROLES: AppRoleType[] = [
'language_group_overseers',
];

export const APP_ROLES: AppRoleType[] = [
'admin',
'coordinator',
'midweek_schedule',
'weekend_schedule',
'public_talk_schedule',
'attendance_tracking',
'secretary',
'service_overseer',
...APP_READ_ONLY_ROLES,
];

export const VIP_ROLES: AppRoleType[] = [
'admin',
'coordinator',
Expand All @@ -392,6 +380,7 @@ export const VIP_ROLES: AppRoleType[] = [
'elder',
'group_overseers',
'language_group_overseers',
'duties_schedule',
];

export const POCKET_ROLES: AppRoleType[] = [
Expand All @@ -401,6 +390,10 @@ export const POCKET_ROLES: AppRoleType[] = [
'view_schedules',
];

export const APP_ROLES = Array.from(
new Set([...APP_READ_ONLY_ROLES, ...VIP_ROLES])
) as AppRoleType[];

export const APP_ENVIRONMENT = import.meta.env.VITE_APP_MODE;

export const isTest = APP_ENVIRONMENT === 'TEST';
Expand Down Expand Up @@ -467,6 +460,12 @@ export const BROTHER_ASSIGNMENT = [
AssignmentCode.WM_SpeakerSymposium,
AssignmentCode.WM_WTStudyConductor,
AssignmentCode.WM_WTStudyReader,
AssignmentCode.DUTIES_Audio,
AssignmentCode.DUTIES_AuditoriumAttendant,
AssignmentCode.DUTIES_EntranceAttendant,
AssignmentCode.DUTIES_Microphone,
AssignmentCode.DUTIES_Stage,
AssignmentCode.DUTIES_Video,
];

export const STUDENT_ASSIGNMENT = [
Expand Down
1 change: 1 addition & 0 deletions src/constants/table_encryption_map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export const TABLE_ENCRYPTION_MAP = {
aux_class_fsg: 'shared',
first_day_week: 'shared',
schedule_songs_weekend: 'shared',
meeting_duties: 'shared',
},
speakers_congregations: {
_deleted: 'private',
Expand Down
5 changes: 3 additions & 2 deletions src/definition/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export type BadgeColor =
| 'accent'
| 'transparent';

export type MeetingType = 'midweek' | 'weekend';
export type MeetingType = 'midweek' | 'weekend' | 'duties';

export type AppRoleType =
| 'admin'
Expand All @@ -65,7 +65,8 @@ export type AppRoleType =
| 'elder'
| 'ms'
| 'group_overseers'
| 'language_group_overseers';
| 'language_group_overseers'
| 'duties_schedule';

export type ReleaseNoteType = {
[version: string]: {
Expand Down
15 changes: 14 additions & 1 deletion src/definition/assignment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ export enum AssignmentCode {
MM_AssistantOnly = 129,
WM_WTStudyConductor = 130,
MINISTRY_HOURS_CREDIT = 300,
DUTIES_Audio = 400,
DUTIES_Video = 401,
DUTIES_Microphone = 402,
DUTIES_Stage = 403,
DUTIES_EntranceAttendant = 404,
DUTIES_AuditoriumAttendant = 405,
}

export type AssignmentType = {
Expand Down Expand Up @@ -119,9 +125,16 @@ export type AssignmentFieldWeekendType =
| 'WM_ClosingPrayer'
| 'WM_SubstituteSpeaker';

export type AssignmentFieldDutiesType =
| 'DUTIES_Audio'
| 'DUTIES_Video'
| 'DUTIES_Stage'
| 'DUTIES_AuditoriumAttendant';

export type AssignmentFieldType =
| AssignmentFieldMidweekType
| AssignmentFieldWeekendType
| 'MM_CircuitOverseer'
| 'WM_CircuitOverseer'
| 'WM_Speaker_Outgoing';
| 'WM_Speaker_Outgoing'
| AssignmentFieldDutiesType;
18 changes: 18 additions & 0 deletions src/definition/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,24 @@ export type SettingsType = {
updatedAt: string;
value: boolean;
}[];
meeting_duties: {
type: string;
_deleted: { value: boolean; updatedAt: string };
conflict_prevent: { value: boolean; updatedAt: string };
mic_sections: { value: boolean; updatedAt: string };
av_amount: { value: number; updatedAt: string };
mic_amount: { value: number; updatedAt: string };
stage_amount: { value: number; updatedAt: string };
entrance_attendant_amount: { value: number; updatedAt: string };
hospitality_amount: { value: number; updatedAt: string };
custom: {
_deleted: boolean;
id: string;
name: string;
updatedAt: string;
amount: number;
}[];
}[];
};
user_settings: {
id?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,14 @@ const AcceptRequest = (props: AcceptRequestProps) => {
}
/>

<SwitchWithLabel
label={t('tr_meetingDutiesScheduling')}
checked={roles.includes('duties_schedule')}
onChange={(checked) =>
handleRolesChange('duties_schedule', checked)
}
/>

<SwitchWithLabel
label={t('tr_attendanceRecordTracking')}
checked={roles.includes('attendance_tracking')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ const UserAdditionalRights = () => {
handleToggleAttendance,
isWeekend,
handleToggleWeekend,
isDuties,
handleToggleDuties,
} = useUserAdditionalRights();

return (
Expand Down Expand Up @@ -53,6 +55,13 @@ const UserAdditionalRights = () => {
onChange={handleTogglePublicTalk}
/>

<SwitchWithLabel
label={t('tr_meetingDutiesScheduling')}
readOnly={isProcessing}
checked={isDuties}
onChange={handleToggleDuties}
/>

<SwitchWithLabel
label={t('tr_attendanceRecordTracking')}
readOnly={isProcessing}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const useUserAdditionalRights = () => {
const [isMidweek, setIsMidweek] = useState(false);
const [isWeekend, setIsWeekend] = useState(false);
const [isPublicTalk, setIsPublicTalk] = useState(false);
const [isDuties, setIsDuties] = useState(false);
const [isAttendance, setIsAttendance] = useState(false);

const handleToggleMidweek = async (value: boolean) => {
Expand Down Expand Up @@ -131,6 +132,36 @@ const useUserAdditionalRights = () => {
}
};

const handleToggleDuties = async (value: boolean) => {
try {
setIsDuties(value);

const newUser = structuredClone(currentUser);

newUser.profile.cong_role = newUser.profile.cong_role || [];

if (value) {
newUser.profile.cong_role.push('duties_schedule');
}

if (!value) {
newUser.profile.cong_role = newUser.profile.cong_role.filter(
(role) => role !== 'duties_schedule'
);
}

await handleSaveDetails(newUser);
} catch (error) {
console.error(error);

displaySnackNotification({
header: getMessageByCode('error_app_generic-title'),
message: getMessageByCode(error.message),
severity: 'error',
});
}
};

useEffect(() => {
const isMidweek =
currentUser.profile.cong_role?.includes('midweek_schedule') ?? false;
Expand All @@ -144,6 +175,10 @@ const useUserAdditionalRights = () => {
currentUser.profile.cong_role?.includes('public_talk_schedule') ?? false;
setIsPublicTalk(isPublicTalk);

const isDuties =
currentUser.profile.cong_role?.includes('duties_schedule') ?? false;
setIsDuties(isDuties);

const isAttendance =
currentUser.profile.cong_role?.includes('attendance_tracking') ?? false;
setIsAttendance(isAttendance);
Expand All @@ -158,6 +193,8 @@ const useUserAdditionalRights = () => {
handleTogglePublicTalk,
isAttendance,
handleToggleAttendance,
isDuties,
handleToggleDuties,
};
};

Expand Down
Loading