diff --git a/src/pages/homepage/components/Applications/AppItem.tsx b/src/pages/homepage/components/Applications/AppItem.tsx index 50f5b9f..9cb2629 100644 --- a/src/pages/homepage/components/Applications/AppItem.tsx +++ b/src/pages/homepage/components/Applications/AppItem.tsx @@ -4,15 +4,14 @@ import { useCommonHooks } from 'hooks'; import { useState } from 'react'; import { stackClasses, textClasses } from 'styles'; -function AppItem({ url, icon, name }: any) { +function AppItem({ url, icon, name, linkDisabled }: any) { const [textDecoration, setTextDecoration] = useState('none'); const [hover, setHover] = useState(false); const { isMobile } = useCommonHooks(); - return ( { setTextDecoration('underline'); setHover(true); diff --git a/src/pages/settings/components/Applications/Applications.tsx b/src/pages/settings/components/Applications/Applications.tsx index affa7a3..d2fd646 100644 --- a/src/pages/settings/components/Applications/Applications.tsx +++ b/src/pages/settings/components/Applications/Applications.tsx @@ -1,39 +1,296 @@ -import { Stack, Text } from '@mantine/core'; -import { ApplicationColumns, DataTable } from 'components'; -import { useQueryAPI } from 'hooks'; +import { + ActionIcon, + Box, + Button, + Divider, + Grid, + GridCol, + Group, + Highlight, + Modal, + Popover, + Stack, + Text, + TextInput, +} from '@mantine/core'; +import { useDebouncedValue, useDisclosure } from '@mantine/hooks'; +import { useCommonHooks, useMutationAPI, useQueryAPI } from 'hooks'; +import AppItem from 'pages/homepage/components/Applications/AppItem'; import { useEffect, useState } from 'react'; -import { textClasses } from 'styles'; +import { FiHelpCircle, FiPlus } from 'react-icons/fi'; +import { + actionIconClasses, + buttonClasses, + modalClasses, + textClasses, + textInputClasses, +} from 'styles'; +import DebouncedApplication from './DebouncedApplication'; const ApplicationSettings = () => { const endpoint = 'api/apps'; - const { - data: apps, - isFetching: isAppsFetching, - isLoading: isAppsLoading, - } = useQueryAPI({ + const { data: apps, isFetching: isAppsFetching } = useQueryAPI({ endpoint: endpoint, }); const [applicationData, setApplicationData] = useState([]); + const { theme } = useCommonHooks(); + const [application, setApplication] = useState({}); + const [update, setUpdate] = useState({}); + const [debounced] = useDebouncedValue(update, 1000); + const [newApplication, setNewApplication] = useState({ + name: '', + url: '', + icon: '', + baseUrl: '', + filterName: '', + }); + const { mutateAsync } = useMutationAPI(); + const [searchValue, setSearchValue] = useState(''); + const [debouncedSearch] = useDebouncedValue(searchValue, 500); + const [modalOpened, { open: openModal, close: closeModal }] = useDisclosure(false); + const handleDelete = (application: any) => { + mutateAsync({ method: 'DELETE', endpoint: endpoint, body: application }); + }; useEffect(() => { if (apps && !isAppsFetching) { - setApplicationData(apps); + setApplicationData( + apps.filter((a: any) => + a.name.toLowerCase().includes(debouncedSearch.toLowerCase()), + ), + ); } - }, [apps, isAppsFetching]); + }, [apps, isAppsFetching, debouncedSearch]); + + useEffect(() => { + if (Object.keys(debounced).length) { + mutateAsync({ method: 'PATCH', endpoint: endpoint, body: debounced }); + } + }, [debounced]); + + useEffect(() => { + if (update !== application && Object.keys(update).length > 0) { + setApplication(update); + } + }, [update]); return ( - - - Applications - - + + { + closeModal(); + }} + style={{ + '--color-text-pri': theme.primaryColor, + '--color-text-acc': theme.accentColor, + '--color-background': theme.backgroundColor, + '--color-border': theme.borderColor, + '--color-search-background': theme.searchColor, + '--image-background': `url(${theme.backgroundImage})`, + }} + closeOnEscape + closeOnClickOutside + > + + + + Add a new application + + + + + { + setNewApplication({ + ...newApplication, + name: event.target.value, + }); + }} + /> + { + setNewApplication({ + ...newApplication, + url: event.target.value, + }); + }} + /> + { + setNewApplication({ + ...newApplication, + icon: event.target.value, + }); + }} + /> + { + setNewApplication({ + ...newApplication, + baseUrl: event.target.value, + }); + }} + /> + { + setNewApplication({ + ...newApplication, + filterName: event.target.value, + }); + }} + /> + + + + + + + + + + + + Applications + + + + + + + + + + + {'Applications are the apps that will be displayed in the homepage.'} + + + {''} + + + + + + { + setSearchValue(event.target.value); + }} + /> + + + + {applicationData?.map((application: any) => ( + + + + { + e.stopPropagation(); + e.preventDefault(); + }} + > + + + + + + + + + ))} + + ); }; diff --git a/src/pages/settings/components/Applications/DebouncedApplication.tsx b/src/pages/settings/components/Applications/DebouncedApplication.tsx new file mode 100644 index 0000000..a581573 --- /dev/null +++ b/src/pages/settings/components/Applications/DebouncedApplication.tsx @@ -0,0 +1,179 @@ +import { + ActionIcon, + Button, + Card, + Group, + Modal, + Stack, + Text, + TextInput, + Tooltip, +} from '@mantine/core'; +import { useDisclosure } from '@mantine/hooks'; +import { IconTrash } from '@tabler/icons-react'; +import { useCommonHooks } from 'hooks'; +import { cardClasses, modalClasses, textInputClasses } from 'styles'; + +function DebouncedApplication({ application, handleDelete, setApplication }: any) { + const { theme } = useCommonHooks(); + const [modalOpened, { open: openModal, close: closeModal }] = useDisclosure(false); + return ( + + { + closeModal(); + }} + style={{ + '--color-text-pri': theme.primaryColor, + '--color-text-acc': theme.accentColor, + '--color-background': theme.backgroundColor, + '--color-border': theme.borderColor, + '--color-search-background': theme.searchColor, + '--image-background': `url(${theme.backgroundImage})`, + }} + closeOnEscape + closeOnClickOutside + > + + + + Add a new message + + + + + Are you sure you want to delete this application? + {`"${application.name}"`} + This action cannot be undone! + + + + + + + + + + { + openModal(); + }} + > + + + + + { + setApplication({ + ...application, + name: event.target.value, + }); + }} + /> + { + setApplication({ + ...application, + baseUrl: event.target.value, + }); + }} + /> + + + { + setApplication({ + ...application, + url: event.target.value, + }); + }} + /> + + + { + setApplication({ + ...application, + icon: event.target.value, + }); + }} + /> + { + setApplication({ + ...application, + filterName: event.target.value, + }); + }} + /> + + + ); +} + +export default DebouncedApplication; diff --git a/src/components/Shared/DebouncedMessage.tsx b/src/pages/settings/components/Messages/DebouncedMessage.tsx similarity index 100% rename from src/components/Shared/DebouncedMessage.tsx rename to src/pages/settings/components/Messages/DebouncedMessage.tsx diff --git a/src/pages/settings/components/Messages/Messages.tsx b/src/pages/settings/components/Messages/Messages.tsx index cb6527f..1c6c210 100644 --- a/src/pages/settings/components/Messages/Messages.tsx +++ b/src/pages/settings/components/Messages/Messages.tsx @@ -1,20 +1,29 @@ import { + ActionIcon, Button, Divider, Grid, GridCol, Group, + Highlight, Modal, + Popover, Stack, Text, TextInput, } from '@mantine/core'; import { useDebouncedValue, useDisclosure } from '@mantine/hooks'; -import DebouncedMessage from 'components/Shared/DebouncedMessage'; import { useCommonHooks, useMutationAPI, useQueryAPI } from 'hooks'; +import DebouncedMessage from 'pages/settings/components/Messages/DebouncedMessage'; import { useEffect, useState } from 'react'; -import { FiPlus } from 'react-icons/fi'; -import { buttonClasses, modalClasses, textClasses, textInputClasses } from 'styles'; +import { FiHelpCircle, FiPlus } from 'react-icons/fi'; +import { + actionIconClasses, + buttonClasses, + modalClasses, + textClasses, + textInputClasses, +} from 'styles'; const MessageSettings = () => { const endpoint = 'api/messages'; const { @@ -32,6 +41,8 @@ const MessageSettings = () => { const [newMessageError, setNewMessageError] = useState(''); const [message, setMessage] = useState({}); const [debounced] = useDebouncedValue(message, 1000); + const [searchValue, setSearchValue] = useState(''); + const [debouncedSearch] = useDebouncedValue(searchValue, 500); const [modalOpened, { open: openModal, close: closeModal }] = useDisclosure(false); const handleDelete = (message: any) => { @@ -40,9 +51,13 @@ const MessageSettings = () => { useEffect(() => { if (messageData && isMessagesFetched) { - setMessages(messageData); + setMessages( + messageData.filter((m: any) => + m.message.toLowerCase().includes(debouncedSearch.toLowerCase()), + ), + ); } - }, [messageData, isMessagesFetched]); + }, [messageData, isMessagesFetched, debouncedSearch]); useEffect(() => { if (Object.keys(debounced).length) { @@ -51,7 +66,7 @@ const MessageSettings = () => { }, [debounced]); return ( - + { Messages + + + + + + + + + + {'Messages may contain any unicode text.'} + + + { + 'Built-in variables include $firstName and $lastName. To force the text to upper case, use a carat (^), ie, $^firstName.' + } + + + + + { + setSearchValue(event.target.value); + }} + /> - - {messages?.map((message: any) => ( - - - - ))} - + + + {messages?.map((message: any) => ( + + + + ))} + + ); }; diff --git a/src/styles/ActionIcon.module.css b/src/styles/ActionIcon.module.css index f4f82db..7827876 100644 --- a/src/styles/ActionIcon.module.css +++ b/src/styles/ActionIcon.module.css @@ -73,6 +73,29 @@ } } +.settingsTooltip { + &.root { + transition: all .1s ease; + width: 30px; + height: 30px; + border-radius: 100%; + border: none; + background-color: transparent; + color: var(--color-text-pri); + .icon { + font-size: 24px; + } + .loader { + display: none; + } + :hover { + background-color: var(--color-text-pri) !important; + color: var(--color-text-acc) !important; + transition: all .1s ease; + } + } +} + .selectOptionActions { &.root { background-color: transparent !important; diff --git a/src/styles/Card.module.css b/src/styles/Card.module.css index a87d114..e85516f 100644 --- a/src/styles/Card.module.css +++ b/src/styles/Card.module.css @@ -1,7 +1,7 @@ .settingsItem { - &.root { - color: var(--color-text-pri); - background-color: transparent; - backdrop-filter: blur(10px) brightness(.75) !important; - } -} \ No newline at end of file + &.root { + color: var(--color-text-pri); + background-color: transparent; + backdrop-filter: blur(10px) brightness(0.75) !important; + } +} diff --git a/src/styles/Text.module.css b/src/styles/Text.module.css index 72478c5..1a3d0c6 100644 --- a/src/styles/Text.module.css +++ b/src/styles/Text.module.css @@ -106,7 +106,6 @@ &.root { font-size: 24px; font-weight: bold; - padding-top: 1.5rem; color: var(--color-text-pri); } }