diff --git a/components/common/TransferBox/TransferBox.jsx b/components/common/TransferBox/TransferBox.jsx
new file mode 100644
index 0000000..60cea62
--- /dev/null
+++ b/components/common/TransferBox/TransferBox.jsx
@@ -0,0 +1,138 @@
+import React, { useState } from 'react';
+import styled from '@emotion/styled';
+import CheckIcon from '@mui/icons-material/Check';
+import DoNotDisturbIcon from '@mui/icons-material/DoNotDisturb';
+import KeyboardArrowLeftIcon from '@mui/icons-material/KeyboardArrowLeft';
+import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight';
+
+const CenterButton = styled('div')`
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: 30px;
+ height: 30px;
+ border: 1px solid black;
+ border-radius: 5px;
+ margin: 5px;
+ cursor: ${({ buttonEnabled }) => (buttonEnabled ? 'pointer' : 'not-allowed')};
+ transition: background-color 0.3s ease, color 0.3s ease;
+ opacity: ${({ buttonEnabled }) => (buttonEnabled ? 1 : 0.5)};
+
+ ${({ color, buttonEnabled }) => buttonEnabled && color && `
+ &:hover {
+ background-color: ${color};
+ color: white;
+ }
+ `}
+`;
+
+export const TransferBox = ({ fields, leftGroup, rightGroup }) => {
+ const {
+ id,
+ exclusionList,
+ oldListLabel,
+ newListLabel
+ } = fields;
+
+ const [itemSelected, setItemSelected] = useState({});
+ const [containsSelection, setContainsSelection] = useState([]);
+
+ return (
+
+
+
+
{oldListLabel}
+
+
+
+ {leftGroup?.map((j, index) => {
+ return (
+
+ {j?.value}
+
+ )
+ })}
+
+
+
+
+ { console.log('clicked Right') }}
+ color='#A8A8A8'
+ buttonEnabled={itemSelected?.id}
+ >
+
+
+ { console.log('clicked Clear') }}
+ color='#FF6666'
+ buttonEnabled={containsSelection?.length > 0}
+ >
+
+
+ { console.log('clicked Save') }}
+ color='#00B33C'
+ buttonEnabled={containsSelection?.length > 0}
+ >
+
+
+ { console.log('clicked Left') }}
+ color='#A8A8A8'
+ buttonEnabled={itemSelected?.id}
+ >
+
+
+
+
+
+
{newListLabel}
+
+
+
+ {rightGroup?.map((j, index) => {
+ return (
+
+ {j?.value}
+
+ )
+ })}
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/components/common/TransferBox/index.js b/components/common/TransferBox/index.js
new file mode 100644
index 0000000..dcfddff
--- /dev/null
+++ b/components/common/TransferBox/index.js
@@ -0,0 +1 @@
+export { TransferBox } from './TransferBox';
\ No newline at end of file
diff --git a/components/common/index.js b/components/common/index.js
index e36e79e..ccd04d7 100644
--- a/components/common/index.js
+++ b/components/common/index.js
@@ -1 +1,2 @@
-export { ToggleTabs } from './ToggleTabs';
\ No newline at end of file
+export { ToggleTabs } from './ToggleTabs';
+export { TransferBox } from './TransferBox';
\ No newline at end of file
diff --git a/src/pages/Settings/Settings.jsx b/src/pages/Settings/Settings.jsx
index 5a409da..0b2d27d 100644
--- a/src/pages/Settings/Settings.jsx
+++ b/src/pages/Settings/Settings.jsx
@@ -3,7 +3,10 @@ import styled from '@emotion/styled';
import { Stack } from '@mui/material';
import EditIcon from '@mui/icons-material/Edit';
import EditOffIcon from '@mui/icons-material/EditOff';
-import { ToggleTabs, useLocalStore } from '@components';
+import CheckBoxOutlineBlankIcon from '@mui/icons-material/CheckBoxOutlineBlank';
+import CheckBoxIcon from '@mui/icons-material/CheckBox';
+import { ToggleTabs, TransferBox, useLocalStore } from '@components';
+import { settingsFields } from './helpers';
const OuterContainer = styled(Stack)`
position: relative;
@@ -57,7 +60,8 @@ const CardShell = styled('div')`
const Card = styled('div')`
background-color: #C7C7C7;
- width: 1000px;
+ width: 50%;
+ min-width: 750px;
padding: 20px;
border-radius: 10px;
margin: 5px;
@@ -113,14 +117,16 @@ const InnerCard = styled('div')`
flex-direction: column;
padding: 10px;
width: 50%;
+
+ ${({ centered }) => centered && `
+ align-items: center;
+ `}
`;
const InnerCardRow = styled('div')`
display: flex;
flex-direction: row;
- justify-content: space-between;
padding: 5px;
- align-items: center;
`;
const InnerCardRowLabel = styled('label')`
@@ -169,114 +175,13 @@ const FormInputButton = styled('input')`
border-radius: 4px;
`;
-const settingsFields = [
- {
- id: 'deptInfo',
- title: 'Information',
- tab: 'department',
- cards: [
- {
- id: 'companyInfo',
- label: 'Company Information',
- fields: [
- {
- id: 'company',
- label: 'Company Name',
- type: 'text',
- readOnly: true
- },
- {
- id: 'billing_address',
- label: 'Billing Address',
- type: 'text'
- },
- {
- id: 'town',
- label: 'Town',
- type: 'text'
- },
- {
- id: 'state',
- label: 'State',
- type: 'text'
- },
- {
- id: 'postal',
- label: 'Postal Code',
- type: 'text'
- },
- {
- id: 'country',
- label: 'Country',
- type: 'text'
- },
- {
- id: 'phone',
- label: 'Phone Number',
- type: 'phone'
- },
- {
- id: 'display_time',
- label: 'Display Time',
- type: 'select',
- options: [
- { label: '12 Hour AM/PM', value: '12' },
- { label: '24 Hour', value: '24' }
- ]
- },
- {
- id: 'start_day',
- label: 'Calendar Start Day',
- type: 'select',
- options: [
- { label: 'Sunday', value: 'sunday' },
- { label: 'Monday', value: 'monday' }
- ]
- }
- ]
- }
- ]
- },
- {
- id: 'deptPerms',
- title: 'Permissions',
- tab: 'department',
- cards: []
- },
- {
- id: 'deptMgrs',
- title: 'Managers',
- tab: 'department',
- cards: []
- },
- {
- id: 'deptSubs',
- title: 'Subscriptions',
- tab: 'department',
- cards: []
- },
- {
- id: 'personalInfo',
- title: 'Information',
- tab: 'personal',
- cards: []
- },
- {
- id: 'personalNoti',
- title: 'Notifications',
- tab: 'personal',
- cards: []
- },
- {
- id: 'deptNoti',
- title: 'Notifications',
- tab: 'department',
- cards: []
- }
-];
-
export const Settings = () => {
const { user, department, setDepartment } = useLocalStore();
+
+ const isAdministrator = user?.administrator;
+ const isManager = user?.manager;
+ const isScheduler = user?.scheduler;
+
const originalDepartmentRef = useRef(department);
const [formValues, setFormValues] = useState(() => {
const initial = {};
@@ -301,6 +206,7 @@ export const Settings = () => {
}
];
+ const [windowWidth, setWindowWidth] = useState(window.innerWidth);
const [editMode, setEditMode] = useState(null);
const [tabValue, setTabValue] = useState(tabs[0]);
const [pageValue, setPageValue] = useState({});
@@ -354,6 +260,18 @@ export const Settings = () => {
document.title = 'ShiftSync | Settings';
}, []);
+ useEffect(() => {
+ const handleResize = () => setWindowWidth(window.innerWidth);
+ window.addEventListener('resize', handleResize);
+
+ // Initial trigger (in case something else needs it)
+ handleResize();
+
+ return () => {
+ window.removeEventListener('resize', handleResize);
+ };
+ }, []);
+
useEffect(() => {
if (pageValue?.id && pageRefs.current[pageValue.id]) {
const el = pageRefs.current[pageValue.id];
@@ -364,7 +282,7 @@ export const Settings = () => {
width: rect.width
});
}
- }, [pageValue?.id]);
+ }, [pageValue?.id, windowWidth, window.innerHeight]);
useEffect(() => {
setPageValue(settingsFields?.filter((field) => field?.tab === tabValue?.value)[0]);
@@ -372,7 +290,7 @@ export const Settings = () => {
return (
- {user?.administrator ? (
+ {user?.administrator || user?.manager ? (
{
) : null }
- {settingsFields?.filter((field) => field?.tab === tabValue?.value)?.map((field) => {
+ {settingsFields?.filter((field) => field?.tab === tabValue?.value)?.filter((field) => {
+ return ((field?.accessRequired === 'administrator' && isAdministrator) ||
+ (field?.accessRequired === 'manager' && isManager) ||
+ (field?.accessRequired === 'scheduler' && isScheduler) ||
+ (field?.accessRequired === 'user' || !field?.accessRequired))
+ })?.map((field) => {
return (
{
{pageValue?.cards?.map((card) => {
- return (
-
-
- {card?.label}
-
-
-
-
- Employee Count: {department?.employeeCount}
-
-
- Subscription Expiration: {department?.subscriptionExpiration}
-
-
-
-
-
- )
+
+
+
+ )
+ }
+ return null;
})}
diff --git a/src/pages/Settings/helpers.js b/src/pages/Settings/helpers.js
new file mode 100644
index 0000000..1a5b1c0
--- /dev/null
+++ b/src/pages/Settings/helpers.js
@@ -0,0 +1,170 @@
+export const settingsFields = [
+ {
+ id: 'deptInfo',
+ title: 'Information',
+ tab: 'department',
+ cards: [
+ {
+ id: 'companyInfo',
+ label: 'Company Information',
+ fields: [
+ {
+ id: 'employee_count',
+ label: 'Employee Count',
+ type: 'header',
+ readOnly: true
+ },
+ {
+ id: 'subs_expiration',
+ label: 'Subscription Expiration',
+ type: 'header',
+ readOnly: true
+ },
+ {
+ id: 'company',
+ label: 'Company Name',
+ type: 'text',
+ readOnly: true
+ },
+ {
+ id: 'billing_address',
+ label: 'Billing Address',
+ type: 'text'
+ },
+ {
+ id: 'town',
+ label: 'Town',
+ type: 'text'
+ },
+ {
+ id: 'state',
+ label: 'State',
+ type: 'text'
+ },
+ {
+ id: 'postal',
+ label: 'Postal Code',
+ type: 'text'
+ },
+ {
+ id: 'country',
+ label: 'Country',
+ type: 'text'
+ },
+ {
+ id: 'phone',
+ label: 'Phone Number',
+ type: 'phone'
+ },
+ {
+ id: 'display_time',
+ label: 'Display Time',
+ type: 'select',
+ options: [
+ { label: '12 Hour AM/PM', value: '12' },
+ { label: '24 Hour', value: '24' }
+ ]
+ },
+ {
+ id: 'start_day',
+ label: 'Calendar Start Day',
+ type: 'select',
+ options: [
+ { label: 'Sunday', value: 'sunday' },
+ { label: 'Monday', value: 'monday' }
+ ]
+ }
+ ],
+ accessRequired: 'administrator'
+ }
+ ],
+ accessRequired: 'administrator'
+ },
+ {
+ id: 'deptRoles',
+ title: 'Roles',
+ tab: 'department',
+ cards: [
+ {
+ id: 'companyAdmins',
+ label: 'Company Administrators',
+ fields: [
+ {
+ id: 'administrators',
+ type: 'transfer',
+ exclusionList: [],
+ origList: 'users',
+ oldListLabel: 'Users',
+ newListLabel: 'Administrators'
+ },
+ ],
+ accessRequired: 'administrator',
+ removeEdit: true
+ },
+ {
+ id: 'companyMgrs',
+ label: 'Company Managers',
+ fields: [
+ {
+ id: 'managers',
+ type: 'transfer',
+ exclusionList: [
+ 'administrators'
+ ],
+ origList: 'users',
+ oldListLabel: 'Users',
+ newListLabel: 'Managers'
+ },
+ ],
+ accessRequired: 'administrator',
+ removeEdit: true
+ },
+ {
+ id: 'companySched',
+ label: 'Company Schedulers',
+ fields: [
+ {
+ id: 'schedulers',
+ type: 'transfer',
+ exclusionList: [
+ 'administrators',
+ 'managers'
+ ],
+ origList: 'users',
+ oldListLabel: 'Users',
+ newListLabel: 'Schedulers'
+ },
+ ],
+ accessRequired: 'manager',
+ removeEdit: true
+ }
+ ],
+ accessRequired: 'manager'
+ },
+ {
+ id: 'deptSubs',
+ title: 'Subscriptions',
+ tab: 'department',
+ cards: [],
+ accessRequired: 'administrator'
+ },
+ {
+ id: 'personalInfo',
+ title: 'Information',
+ tab: 'personal',
+ cards: []
+ },
+ {
+ id: 'personalNoti',
+ title: 'Notifications',
+ tab: 'personal',
+ cards: []
+ },
+ {
+ id: 'deptNoti',
+ title: 'Notifications',
+ tab: 'department',
+ cards: [],
+ accessRequired: 'administrator'
+ }
+];
\ No newline at end of file
diff --git a/src/router/AppRouter.jsx b/src/router/AppRouter.jsx
index 888dfde..d2ec69c 100644
--- a/src/router/AppRouter.jsx
+++ b/src/router/AppRouter.jsx
@@ -19,26 +19,85 @@ const dept = {
company_logo: '',
employee_count: 1,
subscription_expiration: '10/01/2025',
- schedulers: [],
- managers: [],
+ schedulers: [3],
+ managers: [2],
administrators: [1]
};
+const users = [
+ {
+ id: 1,
+ first_name: 'ShiftSync-Administrator',
+ last_name: 'Test-User',
+ email: 'testuserA@shift-sync.com',
+ is_ss_admin: false
+ },
+ {
+ id: 2,
+ first_name: 'ShiftSync-Manager',
+ last_name: 'Test-User',
+ email: 'testuserM@shift-sync.com',
+ is_ss_admin: false
+ },
+ {
+ id: 3,
+ first_name: 'ShiftSync-Scheduler',
+ last_name: 'Test-User',
+ email: 'testuserS@shift-sync.com',
+ is_ss_admin: false
+ },
+ {
+ id: 4,
+ first_name: 'ShiftSync-User',
+ last_name: 'Test-User',
+ email: 'testuserU@shift-sync.com',
+ is_ss_admin: false
+ },
+]
+
const AppRouter = () => {
const { user, setUser, setDepartment } = useLocalStore();
const [userChanged, setUserChanged] = useState(false);
useEffect(() => {
- setDepartment(dept);
+ // await call for getting the count of employees and any other calls to db.
+ const employee_count = 1;
+ const subs_expiration = '10/22/2025';
setUser({
- id: 1,
- first_name: 'ShiftSync-Manager',
- last_name: 'Test-User',
- email: 'testuser@shift-sync.com',
+ ...users[0],
scheduler: dept?.schedulers?.includes(1),
manager: dept?.managers?.includes(1),
- administrator: dept?.administrators?.includes(1),
- is_ss_admin: false
+ administrator: dept?.administrators?.includes(1)
+ });
+ const newAdministrators = dept?.administrators?.map((admin) => {
+ const user = users?.find((user) => {
+ return user?.id === admin;
+ });
+ return { id: user?.id, value: `${user?.last_name}, ${user?.first_name}` };
+ });
+ const newManagers = dept?.managers?.map((manager) => {
+ const user = users?.find((user) => {
+ return user?.id === manager;
+ });
+ return { id: user?.id, value: `${user?.last_name}, ${user?.first_name}` };
+ });
+ const newSchedulers = dept?.schedulers?.map((scheduler) => {
+ const user = users?.find((user) => {
+ return user?.id === scheduler;
+ });
+ return { id: user?.id, value: `${user?.last_name}, ${user?.first_name}` };
+ });
+ const newUsers = users?.map((user) => {
+ return { id: user?.id, value: `${user?.last_name}, ${user?.first_name}` };
+ });
+ setDepartment({
+ ...dept,
+ users: newUsers,
+ schedulers: newSchedulers,
+ managers: newManagers,
+ administrators: newAdministrators,
+ employee_count,
+ subs_expiration
});
}, []);