diff --git a/apps/meteor/client/views/admin/settings/MemoizedSetting.tsx b/apps/meteor/client/views/admin/settings/MemoizedSetting.tsx
index a7433afc66c25..b3a29b8a30305 100644
--- a/apps/meteor/client/views/admin/settings/MemoizedSetting.tsx
+++ b/apps/meteor/client/views/admin/settings/MemoizedSetting.tsx
@@ -101,8 +101,8 @@ const MemoizedSetting = ({
{callout}
)}
+ {showUpgradeButton}
- {showUpgradeButton}
);
};
diff --git a/apps/meteor/client/views/admin/settings/Setting.tsx b/apps/meteor/client/views/admin/settings/Setting.tsx
index eb0413d53d84f..d9076e5fb4f62 100644
--- a/apps/meteor/client/views/admin/settings/Setting.tsx
+++ b/apps/meteor/client/views/admin/settings/Setting.tsx
@@ -2,7 +2,6 @@ import type { ISettingColor, SettingEditor, SettingValue } from '@rocket.chat/co
import { isSettingColor, isSetting } from '@rocket.chat/core-typings';
import { Button } from '@rocket.chat/fuselage';
import { useDebouncedCallback } from '@rocket.chat/fuselage-hooks';
-import { ExternalLink } from '@rocket.chat/ui-client';
import { useSettingStructure, useTranslation } from '@rocket.chat/ui-contexts';
import type { ReactElement } from 'react';
import React, { useEffect, useMemo, useState, useCallback } from 'react';
@@ -113,9 +112,9 @@ function Setting({ className = undefined, settingId, sectionChanged }: SettingPr
const showUpgradeButton = useMemo(
() =>
shouldDisableEnterprise ? (
-
-
-
+
) : undefined,
[shouldDisableEnterprise, t],
);
diff --git a/apps/meteor/client/views/omnichannel/additionalForms.tsx b/apps/meteor/client/views/omnichannel/additionalForms.tsx
index 16f6c9bcb440f..9978aba5586dc 100644
--- a/apps/meteor/client/views/omnichannel/additionalForms.tsx
+++ b/apps/meteor/client/views/omnichannel/additionalForms.tsx
@@ -1,4 +1,4 @@
-import BusinessHoursMultipleContainer from '../../../ee/client/omnichannel/additionalForms/BusinessHoursMultipleContainer';
+import BusinessHoursMultiple from '../../../ee/client/omnichannel/additionalForms/BusinessHoursMultiple';
import ContactManager from '../../../ee/client/omnichannel/additionalForms/ContactManager';
import CurrentChatTags from '../../../ee/client/omnichannel/additionalForms/CurrentChatTags';
import CustomFieldsAdditionalForm from '../../../ee/client/omnichannel/additionalForms/CustomFieldsAdditionalForm';
@@ -18,7 +18,7 @@ export {
MaxChatsPerAgentDisplay,
EeNumberInput,
EeTextAreaInput,
- BusinessHoursMultipleContainer,
+ BusinessHoursMultiple,
EeTextInput,
ContactManager,
CurrentChatTags,
diff --git a/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursForm.js b/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursForm.js
deleted file mode 100644
index ba01289ffe455..0000000000000
--- a/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursForm.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import { Field, MultiSelect } from '@rocket.chat/fuselage';
-import { useTranslation } from '@rocket.chat/ui-contexts';
-import React, { useMemo } from 'react';
-
-import TimeRangeFieldsAssembler from './TimeRangeFieldsAssembler';
-
-export const DAYS_OF_WEEK = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
-
-const BusinessHoursForm = ({ values, handlers, className = undefined }) => {
- const t = useTranslation();
-
- const daysOptions = useMemo(() => DAYS_OF_WEEK.map((day) => [day, t(day)]), [t]);
-
- const { daysOpen, daysTime } = values;
-
- const { handleDaysOpen, handleDaysTime } = handlers;
-
- return (
- <>
-
- {t('Open_days_of_the_week')}
-
-
-
-
-
- >
- );
-};
-
-export default BusinessHoursForm;
diff --git a/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursForm.stories.tsx b/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursForm.stories.tsx
index d2861a33fa564..3bfbcb7aa4fed 100644
--- a/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursForm.stories.tsx
+++ b/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursForm.stories.tsx
@@ -1,5 +1,4 @@
import { Box } from '@rocket.chat/fuselage';
-import { action } from '@storybook/addon-actions';
import type { ComponentMeta, ComponentStory } from '@storybook/react';
import React from 'react';
@@ -19,17 +18,3 @@ export default {
export const Default: ComponentStory = (args) => ;
Default.storyName = 'BusinessHoursForm';
-Default.args = {
- values: {
- daysOpen: ['Monday', 'Tuesday', 'Saturday'],
- daysTime: {
- Monday: { start: '00:00', finish: '08:00' },
- Tuesday: { start: '00:00', finish: '08:00' },
- Saturday: { start: '00:00', finish: '08:00' },
- },
- },
- handlers: {
- handleDaysOpen: action('handleDaysOpen'),
- handleDaysTime: action('handleDaysTime'),
- },
-};
diff --git a/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursForm.tsx b/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursForm.tsx
new file mode 100644
index 0000000000000..71a3a5b27ed42
--- /dev/null
+++ b/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursForm.tsx
@@ -0,0 +1,123 @@
+import type { SelectOption } from '@rocket.chat/fuselage';
+import { InputBox, Field, MultiSelect, FieldGroup, Box, Select, FieldLabel, FieldRow } from '@rocket.chat/fuselage';
+import { useUniqueId } from '@rocket.chat/fuselage-hooks';
+import type { TranslationKey } from '@rocket.chat/ui-contexts';
+import { useTranslation } from '@rocket.chat/ui-contexts';
+import React, { useMemo } from 'react';
+import { useFormContext, Controller, useFieldArray } from 'react-hook-form';
+
+import { useTimezoneNameList } from '../../../hooks/useTimezoneNameList';
+import { BusinessHoursMultiple } from '../additionalForms';
+import { defaultWorkHours, DAYS_OF_WEEK } from './mapBusinessHoursForm';
+
+type mappedDayTime = {
+ day: string;
+ start: {
+ time: string;
+ };
+ finish: {
+ time: string;
+ };
+ open: boolean;
+};
+
+export type BusinessHoursFormData = {
+ name: string;
+ timezoneName: string;
+ daysOpen: string[];
+ daysTime: mappedDayTime[];
+ departmentsToApplyBusinessHour: string;
+ active: boolean;
+ departments: {
+ value: string;
+ label: string;
+ }[];
+};
+
+// TODO: replace `Select` in favor `SelectFiltered`
+// TODO: add time validation for start and finish not be equal on UI
+// TODO: add time validation for start not be higher than finish on UI
+const BusinessHoursForm = ({ type }: { type?: 'default' | 'custom' }) => {
+ const t = useTranslation();
+ const timeZones = useTimezoneNameList();
+ const timeZonesOptions: SelectOption[] = useMemo(() => timeZones.map((name) => [name, t(name as TranslationKey)]), [t, timeZones]);
+ const daysOptions: SelectOption[] = useMemo(() => DAYS_OF_WEEK.map((day) => [day, t(day as TranslationKey)]), [t]);
+
+ const { watch, control } = useFormContext();
+ const { daysTime } = watch();
+ const { fields: daysTimeFields, replace } = useFieldArray({ control, name: 'daysTime' });
+
+ const timezoneField = useUniqueId();
+ const daysOpenField = useUniqueId();
+ const daysTimeField = useUniqueId();
+
+ const handleChangeDaysTime = (values: string[]) => {
+ const newValues = values
+ .map((item) => daysTime.find(({ day }) => day === item) || defaultWorkHours(true).find(({ day }) => day === item))
+ .filter((item): item is mappedDayTime => Boolean(item));
+ replace(newValues);
+ };
+
+ return (
+
+ {type === 'custom' && }
+
+ {t('Timezone')}
+
+ }
+ />
+
+
+
+ {t('Open_days_of_the_week')}
+
+ (
+ {
+ handleChangeDaysTime(values);
+ onChange(values);
+ }}
+ options={daysOptions}
+ value={value}
+ placeholder={t('Select_an_option')}
+ w='full'
+ />
+ )}
+ />
+
+
+ {daysTimeFields.map((dayTime, index) => (
+
+ {t(dayTime.day as TranslationKey)}
+
+
+ {t('Open')}
+ }
+ />
+
+
+ {t('Close')}
+ }
+ />
+
+
+
+ ))}
+
+ );
+};
+
+export default BusinessHoursForm;
diff --git a/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursFormContainer.js b/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursFormContainer.js
deleted file mode 100644
index b13fc9b2e1695..0000000000000
--- a/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursFormContainer.js
+++ /dev/null
@@ -1,59 +0,0 @@
-import { FieldGroup, Box } from '@rocket.chat/fuselage';
-import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
-import React, { useEffect, useState } from 'react';
-
-import { businessHourManager } from '../../../../app/livechat/client/views/app/business-hours/BusinessHours';
-import { useForm } from '../../../hooks/useForm';
-import { useReactiveValue } from '../../../hooks/useReactiveValue';
-import { BusinessHoursMultipleContainer } from '../additionalForms';
-import BusinessHourForm from './BusinessHoursForm';
-import BusinessHoursTimeZone from './BusinessHoursTimeZone';
-
-const useChangeHandler = (name, ref) =>
- useMutableCallback((val) => {
- ref.current[name] = { ...ref.current[name], ...val };
- });
-
-const getInitalData = ({ workHours }) => ({
- daysOpen: workHours.filter(({ open }) => !!open).map(({ day }) => day),
- daysTime: workHours.reduce((acc, { day, start: { time: start }, finish: { time: finish } }) => {
- acc = { ...acc, [day]: { start, finish } };
- return acc;
- }, {}),
-});
-
-const BusinessHoursFormContainer = ({ data, saveRef, onChange = () => {} }) => {
- const [hasChangesMultiple, setHasChangesMultiple] = useState(false);
- const [hasChangesTimeZone, setHasChangesTimeZone] = useState(false);
-
- const showMultipleBHForm = useReactiveValue(useMutableCallback(() => businessHourManager.showCustomTemplate(data)));
-
- const onChangeTimezone = useChangeHandler('timezone', saveRef);
- const onChangeMultipleBHForm = useChangeHandler('multiple', saveRef);
-
- const { values, handlers, hasUnsavedChanges } = useForm(getInitalData(data));
-
- saveRef.current.form = values;
-
- useEffect(() => {
- onChange(hasUnsavedChanges || (showMultipleBHForm && hasChangesMultiple) || hasChangesTimeZone);
- });
-
- return (
-
-
- {showMultipleBHForm && (
-
- )}
-
-
-
-
- );
-};
-
-export default BusinessHoursFormContainer;
diff --git a/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursPage.js b/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursMultiplePage.tsx
similarity index 52%
rename from apps/meteor/client/views/omnichannel/businessHours/BusinessHoursPage.js
rename to apps/meteor/client/views/omnichannel/businessHours/BusinessHoursMultiplePage.tsx
index 2e738f75009db..1d6c40d58255b 100644
--- a/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursPage.js
+++ b/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursMultiplePage.tsx
@@ -1,27 +1,20 @@
import { Button, ButtonGroup } from '@rocket.chat/fuselage';
-import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
-import { useRoute, useTranslation } from '@rocket.chat/ui-contexts';
+import { useRouter, useTranslation } from '@rocket.chat/ui-contexts';
import React, { lazy, useMemo } from 'react';
import { Page, PageHeader, PageContent } from '../../../components/Page';
-const BusinessHoursPage = () => {
+const BusinessHoursMultiplePage = () => {
const t = useTranslation();
- const router = useRoute('omnichannel-businessHours');
+ const router = useRouter();
- const BusinessHoursTable = useMemo(() => lazy(() => import('../../../../ee/client/omnichannel/BusinessHoursTable')), []);
-
- const handleNew = useMutableCallback(() => {
- router.push({
- context: 'new',
- });
- });
+ const BusinessHoursTable = useMemo(() => lazy(() => import('../../../../ee/client/omnichannel/businessHours/BusinessHoursTable')), []);
return (
-
@@ -33,4 +26,4 @@ const BusinessHoursPage = () => {
);
};
-export default BusinessHoursPage;
+export default BusinessHoursMultiplePage;
diff --git a/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursRouter.js b/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursRouter.js
deleted file mode 100644
index 6ef6cc5af0269..0000000000000
--- a/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursRouter.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
-import { useRoute, useRouteParameter } from '@rocket.chat/ui-contexts';
-import React, { useEffect } from 'react';
-
-import { businessHourManager } from '../../../../app/livechat/client/views/app/business-hours/BusinessHours';
-import { useReactiveValue } from '../../../hooks/useReactiveValue';
-import BusinessHoursPage from './BusinessHoursPage';
-import EditBusinessHoursPage from './EditBusinessHoursPage';
-import NewBusinessHoursPage from './NewBusinessHoursPage';
-
-export const useIsSingleBusinessHours = () =>
- useReactiveValue(useMutableCallback(() => businessHourManager.getTemplate())) === 'livechatBusinessHoursForm';
-
-const BusinessHoursRouter = () => {
- const context = useRouteParameter('context');
- const id = useRouteParameter('id');
- const type = useRouteParameter('type');
- const isSingleBH = useIsSingleBusinessHours();
-
- const router = useRoute('omnichannel-businessHours');
-
- useEffect(() => {
- if (isSingleBH) {
- router.push({
- context: 'edit',
- type: 'default',
- });
- }
- }, [isSingleBH, router, context, type]);
-
- if (context === 'edit' || isSingleBH) {
- return type ? : null;
- }
-
- if (context === 'new') {
- return ;
- }
-
- return ;
-};
-
-export default BusinessHoursRouter;
diff --git a/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursRouter.tsx b/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursRouter.tsx
new file mode 100644
index 0000000000000..f25b00a87c1a8
--- /dev/null
+++ b/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursRouter.tsx
@@ -0,0 +1,35 @@
+import { LivechatBusinessHourTypes } from '@rocket.chat/core-typings';
+import { useRouteParameter, useRouter } from '@rocket.chat/ui-contexts';
+import React, { useEffect } from 'react';
+
+import BusinessHoursMultiplePage from './BusinessHoursMultiplePage';
+import EditBusinessHours from './EditBusinessHours';
+import EditBusinessHoursWithData from './EditBusinessHoursWithData';
+import { useIsSingleBusinessHours } from './useIsSingleBusinessHours';
+
+const BusinessHoursRouter = () => {
+ const context = useRouteParameter('context');
+ const id = useRouteParameter('id');
+ const type = useRouteParameter('type') as LivechatBusinessHourTypes;
+ const isSingleBH = useIsSingleBusinessHours();
+
+ const router = useRouter();
+
+ useEffect(() => {
+ if (isSingleBH) {
+ router.navigate('/omnichannel/businessHours/edit/default');
+ }
+ }, [isSingleBH, router, context, type]);
+
+ if (context === 'edit' || isSingleBH) {
+ return type ? : null;
+ }
+
+ if (context === 'new') {
+ return ;
+ }
+
+ return ;
+};
+
+export default BusinessHoursRouter;
diff --git a/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursTimeZone.js b/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursTimeZone.js
deleted file mode 100644
index 8826fc621455c..0000000000000
--- a/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursTimeZone.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import { SelectFiltered, Field } from '@rocket.chat/fuselage';
-import { useTranslation } from '@rocket.chat/ui-contexts';
-import React, { useMemo } from 'react';
-
-import { useForm } from '../../../hooks/useForm';
-import { useTimezoneNameList } from '../../../hooks/useTimezoneNameList';
-
-const getInitialData = (data = {}) => ({
- name: data ?? '',
-});
-
-const BusinessHoursTimeZone = ({ onChange, data, className, hasChanges = () => {} }) => {
- const t = useTranslation();
-
- const { values, handlers, hasUnsavedChanges } = useForm(getInitialData(data));
-
- const { name } = values;
- const { handleName } = handlers;
-
- const timeZones = useTimezoneNameList();
-
- const timeZonesOptions = useMemo(() => timeZones.map((name) => [name, t(name)]), [t, timeZones]);
-
- onChange && onChange({ name });
- hasChanges(hasUnsavedChanges);
-
- return (
-
- {t('Timezone')}
-
-
-
-
- );
-};
-
-export default BusinessHoursTimeZone;
diff --git a/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursTimeZone.stories.tsx b/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursTimeZone.stories.tsx
deleted file mode 100644
index af00db33322ee..0000000000000
--- a/apps/meteor/client/views/omnichannel/businessHours/BusinessHoursTimeZone.stories.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-import { Box } from '@rocket.chat/fuselage';
-import type { ComponentMeta, ComponentStory } from '@storybook/react';
-import React from 'react';
-
-import BusinessHoursTimeZone from './BusinessHoursTimeZone';
-
-export default {
- title: 'Omnichannel/BusinessHoursTimeZone',
- component: BusinessHoursTimeZone,
- decorators: [
- (fn) => (
-
- {fn()}
-
- ),
- ],
-} as ComponentMeta;
-
-export const Default: ComponentStory = (args) => ;
-Default.storyName = 'BusinessHoursTimeZone';
diff --git a/apps/meteor/client/views/omnichannel/businessHours/EditBusinessHours.tsx b/apps/meteor/client/views/omnichannel/businessHours/EditBusinessHours.tsx
new file mode 100644
index 0000000000000..f6ef54c1fbb6e
--- /dev/null
+++ b/apps/meteor/client/views/omnichannel/businessHours/EditBusinessHours.tsx
@@ -0,0 +1,115 @@
+import type { ILivechatBusinessHour, LivechatBusinessHourTypes, Serialized } from '@rocket.chat/core-typings';
+import { Box, Button, ButtonGroup } from '@rocket.chat/fuselage';
+import { useMutableCallback, useUniqueId } from '@rocket.chat/fuselage-hooks';
+import { useToastMessageDispatch, useMethod, useTranslation, useRouter } from '@rocket.chat/ui-contexts';
+import React from 'react';
+import { FormProvider, useForm } from 'react-hook-form';
+
+import { useRemoveBusinessHour } from '../../../../ee/client/omnichannel/businessHours/useRemoveBusinessHour';
+import { Page, PageFooter, PageHeader, PageScrollableContentWithShadow } from '../../../components/Page';
+import type { BusinessHoursFormData } from './BusinessHoursForm';
+import BusinessHoursForm from './BusinessHoursForm';
+import { defaultWorkHours } from './mapBusinessHoursForm';
+import { useIsSingleBusinessHours } from './useIsSingleBusinessHours';
+
+const getInitialData = (businessHourData: Serialized | undefined) => ({
+ name: businessHourData?.name || '',
+ timezoneName: businessHourData?.timezone?.name || 'America/Sao_Paulo',
+ daysOpen: (businessHourData?.workHours || defaultWorkHours()).filter(({ open }) => !!open).map(({ day }) => day),
+ daysTime: (businessHourData?.workHours || defaultWorkHours())
+ .filter(({ open }) => !!open)
+ .map(({ day, start: { time: startTime }, finish: { time: finishTime }, open }) => ({
+ day,
+ start: { time: startTime },
+ finish: { time: finishTime },
+ open,
+ })),
+ departmentsToApplyBusinessHour: '',
+ active: businessHourData?.active || true,
+ departments: businessHourData?.departments?.map(({ _id, name }) => ({ value: _id, label: name })) || [],
+});
+
+type EditBusinessHoursProps = {
+ businessHourData?: Serialized;
+ type: LivechatBusinessHourTypes;
+};
+
+const EditBusinessHours = ({ businessHourData, type }: EditBusinessHoursProps) => {
+ const t = useTranslation();
+ const dispatchToastMessage = useToastMessageDispatch();
+ const isSingleBH = useIsSingleBusinessHours();
+
+ const saveBusinessHour = useMethod('livechat:saveBusinessHour');
+ const handleRemove = useRemoveBusinessHour();
+
+ const router = useRouter();
+
+ const methods = useForm({ values: getInitialData(businessHourData) });
+ const {
+ reset,
+ handleSubmit,
+ formState: { isDirty },
+ } = methods;
+
+ const handleSave = useMutableCallback(async ({ departments, ...data }: BusinessHoursFormData) => {
+ const departmentsToApplyBusinessHour = departments?.map((dep) => dep.value).join(',') || '';
+
+ try {
+ const payload = {
+ ...data,
+ ...(businessHourData?._id && { _id: businessHourData._id }),
+ type,
+ departmentsToApplyBusinessHour,
+ timezone: data.timezoneName,
+ workHours: data.daysTime.map(({ day, start: { time: startTime }, finish: { time: finishTime }, open }) => ({
+ day,
+ start: startTime,
+ finish: finishTime,
+ open,
+ })),
+ };
+
+ await saveBusinessHour(payload as any);
+ dispatchToastMessage({ type: 'success', message: t('Business_hours_updated') });
+ router.navigate('/omnichannel/businessHours');
+ } catch (error) {
+ dispatchToastMessage({ type: 'error', message: error });
+ }
+ });
+
+ const formId = useUniqueId();
+
+ return (
+
+
+
+ {!isSingleBH && router.navigate('/omnichannel/businessHours')}>{t('Back')}}
+ {type === 'custom' && businessHourData?._id && (
+ handleRemove(businessHourData?._id, type)}>
+ {t('Delete')}
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+ reset()}>{t('Cancel')}
+
+ {t('Save')}
+
+
+
+
+ );
+};
+
+export default EditBusinessHours;
diff --git a/apps/meteor/client/views/omnichannel/businessHours/EditBusinessHoursPage.js b/apps/meteor/client/views/omnichannel/businessHours/EditBusinessHoursPage.js
deleted file mode 100644
index 1b3b687b35677..0000000000000
--- a/apps/meteor/client/views/omnichannel/businessHours/EditBusinessHoursPage.js
+++ /dev/null
@@ -1,126 +0,0 @@
-import { Button, ButtonGroup, Callout } from '@rocket.chat/fuselage';
-import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
-import { useToastMessageDispatch, useRoute, useMethod, useTranslation } from '@rocket.chat/ui-contexts';
-import React, { useRef, useMemo, useState } from 'react';
-
-import { Page, PageHeader, PageScrollableContentWithShadow } from '../../../components/Page';
-import PageSkeleton from '../../../components/PageSkeleton';
-import { AsyncStatePhase } from '../../../hooks/useAsyncState';
-import { useEndpointData } from '../../../hooks/useEndpointData';
-import BusinessHoursFormContainer from './BusinessHoursFormContainer';
-import { useIsSingleBusinessHours } from './BusinessHoursRouter';
-import { mapBusinessHoursForm } from './mapBusinessHoursForm';
-
-const EditBusinessHoursPage = ({ id, type }) => {
- const t = useTranslation();
- const dispatchToastMessage = useToastMessageDispatch();
- const isSingleBH = useIsSingleBusinessHours();
-
- const { value: data, phase: state } = useEndpointData('/v1/livechat/business-hour', {
- params: useMemo(() => ({ _id: id, type }), [id, type]),
- });
-
- const saveData = useRef({ form: {} });
-
- const [hasChanges, setHasChanges] = useState(false);
-
- const save = useMethod('livechat:saveBusinessHour');
- const deleteBH = useMethod('livechat:removeBusinessHour');
-
- const router = useRoute('omnichannel-businessHours');
-
- const handleSave = useMutableCallback(async () => {
- if (state !== AsyncStatePhase.RESOLVED || !data.success) {
- return;
- }
-
- const {
- current: { form, multiple: { departments, ...multiple } = {}, timezone: { name: timezoneName } = {} },
- } = saveData;
-
- if (data.businessHour.type !== 'default' && multiple.name === '') {
- return dispatchToastMessage({
- type: 'error',
- message: t('error-the-field-is-required', { field: t('Name') }),
- });
- }
-
- const mappedForm = mapBusinessHoursForm(form, data.businessHour);
-
- const departmentsToApplyBusinessHour = departments?.map((dep) => dep.value).join(',') || '';
-
- try {
- const payload = {
- ...data.businessHour,
- ...multiple,
- departmentsToApplyBusinessHour: departmentsToApplyBusinessHour ?? '',
- timezoneName: timezoneName || data.businessHour.timezone.name,
- workHours: mappedForm,
- };
-
- await save(payload);
- dispatchToastMessage({ type: 'success', message: t('Business_hours_updated') });
- router.push({});
- } catch (error) {
- dispatchToastMessage({ type: 'error', message: error });
- }
- });
-
- const handleDelete = useMutableCallback(async () => {
- if (type !== 'custom') {
- return;
- }
-
- try {
- await deleteBH(id, type);
- dispatchToastMessage({ type: 'success', message: t('Business_Hour_Removed') });
- router.push({});
- } catch (error) {
- dispatchToastMessage({ type: 'error', message: error });
- }
- });
-
- const handleReturn = useMutableCallback(() => {
- router.push({});
- });
-
- if (state === AsyncStatePhase.LOADING) {
- return ;
- }
-
- if (state === AsyncStatePhase.REJECTED || (AsyncStatePhase.RESOLVED && !data.businessHour)) {
- return (
-
-
- {t('Back')}
-
-
- {t('Error')}
-
-
- );
- }
-
- return (
-
-
-
- {!isSingleBH && {t('Back')}}
- {type === 'custom' && (
-
- {t('Delete')}
-
- )}
-
- {t('Save')}
-
-
-
-
-
-
-
- );
-};
-
-export default EditBusinessHoursPage;
diff --git a/apps/meteor/client/views/omnichannel/businessHours/EditBusinessHoursWithData.tsx b/apps/meteor/client/views/omnichannel/businessHours/EditBusinessHoursWithData.tsx
new file mode 100644
index 0000000000000..cb810b419bcf3
--- /dev/null
+++ b/apps/meteor/client/views/omnichannel/businessHours/EditBusinessHoursWithData.tsx
@@ -0,0 +1,50 @@
+import type { ILivechatBusinessHour, LivechatBusinessHourTypes } from '@rocket.chat/core-typings';
+import { Button, States, StatesAction, StatesActions, StatesIcon, StatesTitle } from '@rocket.chat/fuselage';
+import { useEndpoint, useRouter, useTranslation } from '@rocket.chat/ui-contexts';
+import { useQuery } from '@tanstack/react-query';
+import React from 'react';
+
+import { Page, PageHeader, PageContent } from '../../../components/Page';
+import PageSkeleton from '../../../components/PageSkeleton';
+import EditBusinessHours from './EditBusinessHours';
+
+const EditBusinessHoursWidthData = ({ id, type }: { id?: ILivechatBusinessHour['_id']; type: LivechatBusinessHourTypes }) => {
+ const t = useTranslation();
+ const router = useRouter();
+ const getBusinessHour = useEndpoint('GET', '/v1/livechat/business-hour');
+
+ const { data, isLoading, isError, refetch } = useQuery(
+ ['livechat-getBusinessHourById', id, type],
+ async () => getBusinessHour({ _id: id, type }),
+ {
+ refetchOnWindowFocus: false,
+ },
+ );
+
+ if (isLoading) {
+ return ;
+ }
+
+ if (isError) {
+ return (
+
+
+ router.navigate('/omnichannel/businessHours')}>{t('Back')}
+
+
+
+
+ {t('Something_went_wrong')}
+
+ refetch()}>{t('Reload_page')}
+
+
+
+
+ );
+ }
+
+ return ;
+};
+
+export default EditBusinessHoursWidthData;
diff --git a/apps/meteor/client/views/omnichannel/businessHours/NewBusinessHoursPage.js b/apps/meteor/client/views/omnichannel/businessHours/NewBusinessHoursPage.js
deleted file mode 100644
index fb8759ba8a3ce..0000000000000
--- a/apps/meteor/client/views/omnichannel/businessHours/NewBusinessHoursPage.js
+++ /dev/null
@@ -1,97 +0,0 @@
-import { Button, ButtonGroup } from '@rocket.chat/fuselage';
-import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
-import { useToastMessageDispatch, useRoute, useMethod, useTranslation } from '@rocket.chat/ui-contexts';
-import React, { useRef, useState } from 'react';
-
-import { Page, PageHeader, PageScrollableContentWithShadow } from '../../../components/Page';
-import { DAYS_OF_WEEK } from './BusinessHoursForm';
-import BusinessHoursFormContainer from './BusinessHoursFormContainer';
-import { mapBusinessHoursForm } from './mapBusinessHoursForm';
-
-const closedDays = ['Saturday', 'Sunday'];
-const createDefaultBusinessHours = () => ({
- name: '',
- workHours: DAYS_OF_WEEK.map((day) => ({
- day,
- start: {
- time: '00:00',
- },
- finish: {
- time: '00:00',
- },
- open: !closedDays.includes(day),
- })),
- departments: [],
- timezoneName: 'America/Sao_Paulo',
- departmentsToApplyBusinessHour: '',
-});
-
-const defaultBusinessHour = createDefaultBusinessHours();
-
-const NewBusinessHoursPage = () => {
- const t = useTranslation();
- const dispatchToastMessage = useToastMessageDispatch();
-
- const [hasChanges, setHasChanges] = useState(false);
-
- const saveData = useRef({ form: {} });
-
- const save = useMethod('livechat:saveBusinessHour');
- const router = useRoute('omnichannel-businessHours');
-
- const handleSave = useMutableCallback(async () => {
- const {
- current: { form, multiple: { departments, ...multiple } = {}, timezone: { name: timezoneName } = {} },
- } = saveData;
-
- if (multiple.name === '') {
- return dispatchToastMessage({
- type: 'error',
- message: t('error-the-field-is-required', { field: t('Name') }),
- });
- }
-
- const mappedForm = mapBusinessHoursForm(form, defaultBusinessHour);
-
- const departmentsToApplyBusinessHour = departments?.map((dep) => dep.value).join(',') || '';
-
- try {
- const payload = {
- ...defaultBusinessHour,
- ...multiple,
- ...(departmentsToApplyBusinessHour && { departmentsToApplyBusinessHour }),
- timezoneName,
- workHours: mappedForm,
- type: 'custom',
- };
-
- await save(payload);
- dispatchToastMessage({ type: 'success', message: t('Saved') });
- router.push({});
- } catch (error) {
- dispatchToastMessage({ type: 'error', message: error });
- }
- });
-
- const handleReturn = useMutableCallback(() => {
- router.push({});
- });
-
- return (
-
-
-
- {t('Back')}
-
- {t('Save')}
-
-
-
-
-
-
-
- );
-};
-
-export default NewBusinessHoursPage;
diff --git a/apps/meteor/client/views/omnichannel/businessHours/TimeRangeFieldsAssembler.js b/apps/meteor/client/views/omnichannel/businessHours/TimeRangeFieldsAssembler.js
deleted file mode 100644
index 7ddcf3fd0d733..0000000000000
--- a/apps/meteor/client/views/omnichannel/businessHours/TimeRangeFieldsAssembler.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import { Field } from '@rocket.chat/fuselage';
-import { useStableArray } from '@rocket.chat/fuselage-hooks';
-import { useTranslation } from '@rocket.chat/ui-contexts';
-import React, { useMemo } from 'react';
-
-import { DAYS_OF_WEEK } from './BusinessHoursForm';
-import TimeRangeInput from './TimeRangeInput';
-
-const TimeRangeFieldsAssembler = ({ onChange, daysOpen, daysTime, className }) => {
- const t = useTranslation();
- const handleChange = (day) => (start, finish) => onChange({ ...daysTime, [day]: { start, finish } });
-
- const stableDaysOpen = useStableArray(daysOpen);
- const daysList = useMemo(() => DAYS_OF_WEEK.filter((day) => stableDaysOpen.includes(day)), [stableDaysOpen]);
-
- return (
- <>
- {daysList.map((day) => (
-
- {t(day)}
-
-
-
-
- ))}
- >
- );
-};
-
-export default TimeRangeFieldsAssembler;
diff --git a/apps/meteor/client/views/omnichannel/businessHours/TimeRangeInput.js b/apps/meteor/client/views/omnichannel/businessHours/TimeRangeInput.js
deleted file mode 100644
index 8187167c464c6..0000000000000
--- a/apps/meteor/client/views/omnichannel/businessHours/TimeRangeInput.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import { Box, InputBox } from '@rocket.chat/fuselage';
-import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
-import { useTranslation } from '@rocket.chat/ui-contexts';
-import React, { useState } from 'react';
-
-const TimeRangeInput = ({ onChange, start: startDefault, finish: finishDefault }) => {
- const t = useTranslation();
-
- const [start, setStart] = useState(startDefault);
- const [finish, setFinish] = useState(finishDefault);
-
- const handleChangeFrom = useMutableCallback(({ currentTarget: { value } }) => {
- setStart(value);
- onChange(value, finish);
- });
-
- const handleChangeTo = useMutableCallback(({ currentTarget: { value } }) => {
- setFinish(value);
- onChange(start, value);
- });
-
- return (
- <>
-
- {t('Open')}:
-
-
-
- {t('Close')}:
-
-
- >
- );
-};
-
-export default TimeRangeInput;
diff --git a/apps/meteor/client/views/omnichannel/businessHours/mapBusinessHoursForm.js b/apps/meteor/client/views/omnichannel/businessHours/mapBusinessHoursForm.js
deleted file mode 100644
index c1b277c14966e..0000000000000
--- a/apps/meteor/client/views/omnichannel/businessHours/mapBusinessHoursForm.js
+++ /dev/null
@@ -1,17 +0,0 @@
-export const mapBusinessHoursForm = (formData, data) => {
- const { daysOpen, daysTime } = formData;
-
- return data.workHours?.map((day) => {
- const {
- day: currentDay,
- start: { time: start },
- finish: { time: finish },
- } = day;
- const open = daysOpen.includes(currentDay);
- if (daysTime[currentDay]) {
- const { start, finish } = daysTime[currentDay];
- return { day: currentDay, start, finish, open };
- }
- return { day: currentDay, start, finish, open };
- });
-};
diff --git a/apps/meteor/client/views/omnichannel/businessHours/mapBusinessHoursForm.ts b/apps/meteor/client/views/omnichannel/businessHours/mapBusinessHoursForm.ts
new file mode 100644
index 0000000000000..33bf5afb413c6
--- /dev/null
+++ b/apps/meteor/client/views/omnichannel/businessHours/mapBusinessHoursForm.ts
@@ -0,0 +1,14 @@
+export const DAYS_OF_WEEK = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
+const closedDays = ['Saturday', 'Sunday'];
+
+export const defaultWorkHours = (allDays = false) =>
+ DAYS_OF_WEEK.map((day) => ({
+ day,
+ start: {
+ time: '08:00',
+ },
+ finish: {
+ time: '18:00',
+ },
+ open: allDays ? true : !closedDays.includes(day),
+ }));
diff --git a/apps/meteor/client/views/omnichannel/businessHours/useIsSingleBusinessHours.ts b/apps/meteor/client/views/omnichannel/businessHours/useIsSingleBusinessHours.ts
new file mode 100644
index 0000000000000..3f997d20ebfd8
--- /dev/null
+++ b/apps/meteor/client/views/omnichannel/businessHours/useIsSingleBusinessHours.ts
@@ -0,0 +1,7 @@
+import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
+
+import { businessHourManager } from '../../../../app/livechat/client/views/app/business-hours/BusinessHours';
+import { useReactiveValue } from '../../../hooks/useReactiveValue';
+
+export const useIsSingleBusinessHours = () =>
+ useReactiveValue(useMutableCallback(() => businessHourManager.getTemplate())) === 'livechatBusinessHoursForm';
diff --git a/apps/meteor/ee/app/livechat-enterprise/server/api/business-hours.ts b/apps/meteor/ee/app/livechat-enterprise/server/api/business-hours.ts
index f0f7ea5646e61..663c489e114a1 100644
--- a/apps/meteor/ee/app/livechat-enterprise/server/api/business-hours.ts
+++ b/apps/meteor/ee/app/livechat-enterprise/server/api/business-hours.ts
@@ -1,4 +1,5 @@
import type { ILivechatBusinessHour } from '@rocket.chat/core-typings';
+import type { PaginatedRequest } from '@rocket.chat/rest-typings';
import { API } from '../../../../../app/api/server';
import { getPaginationItems } from '../../../../../app/api/server/helpers/getPaginationItems';
@@ -8,7 +9,7 @@ declare module '@rocket.chat/rest-typings' {
// eslint-disable-next-line @typescript-eslint/naming-convention
interface Endpoints {
'/v1/livechat/business-hours': {
- GET: (params: { name?: string; offset: number; count: number; sort: Record }) => {
+ GET: (params: PaginatedRequest) => {
businessHours: ILivechatBusinessHour[];
count: number;
offset: number;
diff --git a/apps/meteor/ee/client/omnichannel/BusinessHoursRow.js b/apps/meteor/ee/client/omnichannel/BusinessHoursRow.js
deleted file mode 100644
index 005c3aa464c4d..0000000000000
--- a/apps/meteor/ee/client/omnichannel/BusinessHoursRow.js
+++ /dev/null
@@ -1,60 +0,0 @@
-import { useRoute, useTranslation } from '@rocket.chat/ui-contexts';
-import React, { memo, useMemo } from 'react';
-
-import { GenericTableRow, GenericTableCell } from '../../../client/components/GenericTable';
-import RemoveBusinessHourButton from './RemoveBusinessHourButton';
-
-function BusinessHoursRow(props) {
- const { _id, name, timezone, workHours, active, type, reload } = props;
-
- const t = useTranslation();
-
- const bhRoute = useRoute('omnichannel-businessHours');
-
- const handleClick = () => {
- bhRoute.push({
- context: 'edit',
- type,
- id: _id,
- });
- };
-
- const handleKeyDown = (e) => {
- if (!['Enter', 'Space'].includes(e.nativeEvent.code)) {
- return;
- }
-
- handleClick();
- };
-
- const openDays = useMemo(
- () =>
- workHours.reduce((acc, day) => {
- if (day.open) {
- acc.push(t(day.day));
- }
- return acc;
- }, []),
- [t, workHours],
- );
-
- const preventClickPropagation = (e) => {
- e.stopPropagation();
- };
-
- return (
-
- {name || t('Default')}
- {t(timezone.name)}
- {openDays.join(', ')}
- {active ? t('Yes') : t('No')}
- {name && (
-
-
-
- )}
-
- );
-}
-
-export default memo(BusinessHoursRow);
diff --git a/apps/meteor/ee/client/omnichannel/RemoveBusinessHourButton.js b/apps/meteor/ee/client/omnichannel/RemoveBusinessHourButton.js
deleted file mode 100644
index 9857eef2603c4..0000000000000
--- a/apps/meteor/ee/client/omnichannel/RemoveBusinessHourButton.js
+++ /dev/null
@@ -1,46 +0,0 @@
-import { IconButton } from '@rocket.chat/fuselage';
-import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
-import { useSetModal, useToastMessageDispatch, useMethod, useTranslation } from '@rocket.chat/ui-contexts';
-import React from 'react';
-
-import GenericModal from '../../../client/components/GenericModal';
-import { GenericTableCell } from '../../../client/components/GenericTable';
-
-function RemoveBusinessHourButton({ _id, type, reload }) {
- const removeBusinessHour = useMethod('livechat:removeBusinessHour');
- const setModal = useSetModal();
- const dispatchToastMessage = useToastMessageDispatch();
- const t = useTranslation();
-
- const handleRemoveClick = useMutableCallback(async () => {
- try {
- await removeBusinessHour(_id, type);
- } catch (error) {
- console.log(error);
- }
- reload();
- });
-
- const handleDelete = useMutableCallback((e) => {
- e.stopPropagation();
- const onBusinessHour = async () => {
- try {
- await handleRemoveClick();
- dispatchToastMessage({ type: 'success', message: t('Business_Hour_Removed') });
- } catch (error) {
- dispatchToastMessage({ type: 'error', message: error });
- }
- setModal();
- };
-
- setModal( setModal()} confirmText={t('Delete')} />);
- });
-
- return (
-
-
-
- );
-}
-
-export default RemoveBusinessHourButton;
diff --git a/apps/meteor/ee/client/omnichannel/additionalForms/BusinessHoursMultiple.js b/apps/meteor/ee/client/omnichannel/additionalForms/BusinessHoursMultiple.js
deleted file mode 100644
index ba168826b435f..0000000000000
--- a/apps/meteor/ee/client/omnichannel/additionalForms/BusinessHoursMultiple.js
+++ /dev/null
@@ -1,40 +0,0 @@
-import { Field, TextInput, ToggleSwitch, Box } from '@rocket.chat/fuselage';
-import { useTranslation } from '@rocket.chat/ui-contexts';
-import React from 'react';
-
-import AutoCompleteDepartmentMultiple from '../../../../client/components/AutoCompleteDepartmentMultiple';
-
-const BusinessHoursMultiple = ({ values = {}, handlers = {}, className }) => {
- const t = useTranslation();
-
- const { active, name, departments } = values;
-
- const { handleActive, handleName, handleDepartments } = handlers;
-
- return (
- <>
-
-
- {t('Enabled')}
-
-
-
-
-
-
- {t('Name')}*
-
-
-
-
-
- {t('Departments')}
-
-
-
-
- >
- );
-};
-
-export default BusinessHoursMultiple;
diff --git a/apps/meteor/ee/client/omnichannel/additionalForms/BusinessHoursMultiple.tsx b/apps/meteor/ee/client/omnichannel/additionalForms/BusinessHoursMultiple.tsx
new file mode 100644
index 0000000000000..f5fc4838ba7ec
--- /dev/null
+++ b/apps/meteor/ee/client/omnichannel/additionalForms/BusinessHoursMultiple.tsx
@@ -0,0 +1,80 @@
+import { Field, FieldLabel, FieldRow, FieldError, TextInput, ToggleSwitch } from '@rocket.chat/fuselage';
+import { useUniqueId } from '@rocket.chat/fuselage-hooks';
+import { useTranslation } from '@rocket.chat/ui-contexts';
+import type { ComponentProps } from 'react';
+import React from 'react';
+import { Controller, useFormContext } from 'react-hook-form';
+
+import AutoCompleteDepartmentMultiple from '../../../../client/components/AutoCompleteDepartmentMultiple';
+import { useHasLicenseModule } from '../../hooks/useHasLicenseModule';
+
+const BusinessHoursMultiple = ({ className }: { className?: ComponentProps['className'] }) => {
+ const t = useTranslation();
+ const {
+ control,
+ formState: { errors },
+ } = useFormContext();
+ const hasLicense = useHasLicenseModule('livechat-enterprise');
+
+ const enabledField = useUniqueId();
+ const nameField = useUniqueId();
+ const departmentsField = useUniqueId();
+
+ if (!hasLicense) {
+ return null;
+ }
+
+ return (
+ <>
+
+
+ {t('Enabled')}
+ }
+ />
+
+
+
+
+ {t('Name')}
+
+
+ }
+ />
+
+ {errors?.name && (
+
+ {errors.name.message}
+
+ )}
+
+
+ {t('Departments')}
+
+ (
+
+ )}
+ />
+
+
+ >
+ );
+};
+
+export default BusinessHoursMultiple;
diff --git a/apps/meteor/ee/client/omnichannel/additionalForms/BusinessHoursMultipleContainer.js b/apps/meteor/ee/client/omnichannel/additionalForms/BusinessHoursMultipleContainer.js
deleted file mode 100644
index 747b6e5538e0a..0000000000000
--- a/apps/meteor/ee/client/omnichannel/additionalForms/BusinessHoursMultipleContainer.js
+++ /dev/null
@@ -1,25 +0,0 @@
-import React from 'react';
-
-import { useForm } from '../../../../client/hooks/useForm';
-import BusinessHoursMultiple from './BusinessHoursMultiple';
-
-const mapDepartments = (departments) => departments.map(({ _id, name }) => ({ value: _id, label: name }));
-
-const getInitialData = (data = {}) => ({
- active: data.active ?? true,
- name: data.name ?? '',
- departments: mapDepartments(data.departments),
-});
-
-const BusinessHoursMultipleContainer = ({ onChange, data: initialData, className, hasChangesAndIsValid = () => {} }) => {
- const { values, handlers, hasUnsavedChanges } = useForm(getInitialData(initialData));
-
- const { name } = values;
-
- onChange(values);
- hasChangesAndIsValid(hasUnsavedChanges && !!name);
-
- return ;
-};
-
-export default BusinessHoursMultipleContainer;
diff --git a/apps/meteor/ee/client/omnichannel/businessHours/BusinessHoursRow.tsx b/apps/meteor/ee/client/omnichannel/businessHours/BusinessHoursRow.tsx
new file mode 100644
index 0000000000000..0ab3a518075cb
--- /dev/null
+++ b/apps/meteor/ee/client/omnichannel/businessHours/BusinessHoursRow.tsx
@@ -0,0 +1,51 @@
+import type { ILivechatBusinessHour, Serialized } from '@rocket.chat/core-typings';
+import { IconButton } from '@rocket.chat/fuselage';
+import type { TranslationKey } from '@rocket.chat/ui-contexts';
+import { useRouter, useTranslation } from '@rocket.chat/ui-contexts';
+import type { KeyboardEvent } from 'react';
+import React, { memo, useMemo } from 'react';
+
+import { GenericTableRow, GenericTableCell } from '../../../../client/components/GenericTable';
+import { useRemoveBusinessHour } from './useRemoveBusinessHour';
+
+const BusinessHoursRow = ({ _id, name, timezone, workHours, active, type }: Serialized) => {
+ const t = useTranslation();
+ const router = useRouter();
+ const handleRemove = useRemoveBusinessHour();
+
+ const handleClick = () => router.navigate(`/omnichannel/businessHours/edit/${type}/${_id}`);
+
+ const handleKeyDown = (e: KeyboardEvent) => {
+ if (!['Enter', 'Space'].includes(e.nativeEvent.code)) {
+ return;
+ }
+
+ handleClick();
+ };
+
+ const openDays = useMemo(() => workHours.filter(({ open }) => !!open).map(({ day }) => day), [workHours]);
+
+ return (
+
+ {name || t('Default')}
+ {t(timezone.name as TranslationKey)}
+ {openDays.join(', ')}
+ {active ? t('Yes') : t('No')}
+
+ {name && (
+ {
+ e.stopPropagation();
+ handleRemove(_id, type);
+ }}
+ />
+ )}
+
+
+ );
+};
+
+export default memo(BusinessHoursRow);
diff --git a/apps/meteor/ee/client/omnichannel/BusinessHoursTable.stories.tsx b/apps/meteor/ee/client/omnichannel/businessHours/BusinessHoursTable.stories.tsx
similarity index 100%
rename from apps/meteor/ee/client/omnichannel/BusinessHoursTable.stories.tsx
rename to apps/meteor/ee/client/omnichannel/businessHours/BusinessHoursTable.stories.tsx
diff --git a/apps/meteor/ee/client/omnichannel/BusinessHoursTable.js b/apps/meteor/ee/client/omnichannel/businessHours/BusinessHoursTable.tsx
similarity index 82%
rename from apps/meteor/ee/client/omnichannel/BusinessHoursTable.js
rename to apps/meteor/ee/client/omnichannel/businessHours/BusinessHoursTable.tsx
index 3d2c0a27f167a..2da634cff9d50 100644
--- a/apps/meteor/ee/client/omnichannel/BusinessHoursTable.js
+++ b/apps/meteor/ee/client/omnichannel/businessHours/BusinessHoursTable.tsx
@@ -3,16 +3,16 @@ import { useTranslation, useEndpoint } from '@rocket.chat/ui-contexts';
import { useQuery } from '@tanstack/react-query';
import React, { useMemo, useState } from 'react';
-import FilterByText from '../../../client/components/FilterByText';
-import GenericNoResults from '../../../client/components/GenericNoResults';
+import FilterByText from '../../../../client/components/FilterByText';
+import GenericNoResults from '../../../../client/components/GenericNoResults';
import {
GenericTable,
GenericTableBody,
GenericTableHeaderCell,
GenericTableHeader,
GenericTableLoadingRow,
-} from '../../../client/components/GenericTable';
-import { usePagination } from '../../../client/components/GenericTable/hooks/usePagination';
+} from '../../../../client/components/GenericTable';
+import { usePagination } from '../../../../client/components/GenericTable/hooks/usePagination';
import BusinessHoursRow from './BusinessHoursRow';
const BusinessHoursTable = () => {
@@ -23,15 +23,17 @@ const BusinessHoursTable = () => {
const query = useMemo(
() => ({
- count: itemsPerPage,
- offset: current,
+ ...(itemsPerPage && { count: itemsPerPage }),
+ ...(current && { offset: current }),
name: text,
}),
[itemsPerPage, current, text],
);
const getBusinessHours = useEndpoint('GET', '/v1/livechat/business-hours');
- const { data, isLoading, isSuccess, isError, refetch } = useQuery(['livechat-buiness-hours', query], async () => getBusinessHours(query));
+ const { data, isLoading, isSuccess, isError, refetch } = useQuery(['livechat-getBusinessHours', query], async () =>
+ getBusinessHours(query),
+ );
const headers = (
<>
@@ -61,7 +63,7 @@ const BusinessHoursTable = () => {
{headers}
{data?.businessHours.map((businessHour) => (
-
+
))}
diff --git a/apps/meteor/ee/client/omnichannel/businessHours/useRemoveBusinessHour.tsx b/apps/meteor/ee/client/omnichannel/businessHours/useRemoveBusinessHour.tsx
new file mode 100644
index 0000000000000..f30cb75b2977d
--- /dev/null
+++ b/apps/meteor/ee/client/omnichannel/businessHours/useRemoveBusinessHour.tsx
@@ -0,0 +1,32 @@
+import { useMutableCallback } from '@rocket.chat/fuselage-hooks';
+import { useSetModal, useToastMessageDispatch, useMethod, useTranslation } from '@rocket.chat/ui-contexts';
+import { useQueryClient } from '@tanstack/react-query';
+import React from 'react';
+
+import GenericModal from '../../../../client/components/GenericModal';
+
+export const useRemoveBusinessHour = () => {
+ const t = useTranslation();
+ const setModal = useSetModal();
+ const dispatchToastMessage = useToastMessageDispatch();
+ const removeBusinessHour = useMethod('livechat:removeBusinessHour');
+ const queryClient = useQueryClient();
+
+ const handleRemove = useMutableCallback((_id, type) => {
+ const onDeleteBusinessHour = async () => {
+ try {
+ await removeBusinessHour(_id, type);
+ dispatchToastMessage({ type: 'success', message: t('Business_Hour_Removed') });
+ queryClient.invalidateQueries(['livechat-getBusinessHours']);
+ } catch (error) {
+ dispatchToastMessage({ type: 'error', message: error });
+ } finally {
+ setModal();
+ }
+ };
+
+ setModal( setModal()} confirmText={t('Delete')} />);
+ });
+
+ return handleRemove;
+};