diff --git a/UserForm.tsx b/UserForm.tsx new file mode 100644 index 0000000..9f27a34 --- /dev/null +++ b/UserForm.tsx @@ -0,0 +1,97 @@ +import React from 'react'; + +import { Stack } from '@chakra-ui/react'; +import { + isEmail, + isMaxLength, + isMinLength, + isPattern, +} from '@formiz/validations'; +import { useTranslation } from 'react-i18next'; + +import { FieldCheckboxes } from '@/components/FieldCheckboxes'; +import { FieldInput } from '@/components/FieldInput'; +import { FieldSelect } from '@/components/FieldSelect'; +import { AVAILABLE_LANGUAGES, DEFAULT_LANGUAGE_KEY } from '@/constants/i18n'; + +const AUTHORITIES = { + ADMIN: 'ROLE_ADMIN', + USER: 'ROLE_USER', +}; + +export const UserForm = () => { + const { t } = useTranslation(['common', 'users']); + + const authorities = Object.values(AUTHORITIES).map((value) => ({ value })); + return ( + + + + + + + + ({ + label: t(`common:languages.${key}`), + value: key, + }))} + defaultValue={DEFAULT_LANGUAGE_KEY} + /> + + + ); +}; diff --git a/functions/src/index.ts b/functions/src/index.ts index a538121..f997ae6 100644 --- a/functions/src/index.ts +++ b/functions/src/index.ts @@ -1,13 +1,13 @@ -import * as functions from 'firebase-functions'; -import express, { Request, Response } from 'express'; -import cors from 'cors'; -import { Client } from '@hubspot/api-client'; +import {Client} from "@hubspot/api-client"; +import cors from "cors"; +import express, {Request, Response} from "express"; +import * as functions from "firebase-functions"; -const TOKEN = 'pat-eu1-cf82e317-f47b-4cf7-b305-be8371c973cf'; +const TOKEN = "pat-eu1-cf82e317-f47b-4cf7-b305-be8371c973cf"; const app = express(); -app.use(cors({ origin: true })); +app.use(cors({origin: true})); // Start writing Firebase Functions // https://firebase.google.com/docs/functions/typescript @@ -21,22 +21,33 @@ app.use(cors({ origin: true })); // functions.logger.info("Hello logs!", {structuredData: true}); // response.send("Hello from Firebase!"); // } -app.get('/', async (request: Request, response: Response) => { - const LIMIT = 'limit=100'; - const ASSOCIATIONS = 'associations=contacts'; - const PROPERTIES = 'properties=hs_meeting_title,hs_meeting_start_time,hs_meeting_outcome,hs_internal_meeting_notes'; - const hubspotClient = new Client({ accessToken: TOKEN }); +app.get("/", async (request: Request, response: Response) => { + const LIMIT = "limit=100"; + const ASSOCIATIONS = "associations=contacts"; + const PROPERTIES = "properties=hs_meeting_title,hs_meeting_start_time,hs_meeting_outcome,hs_internal_meeting_notes"; + const hubspotClient = new Client({accessToken: TOKEN}); const contacts = await hubspotClient.crm.contacts.getAll(); const meetings = await hubspotClient - .apiRequest({ - method: 'get', - path: `/crm/v3/objects/meetings?${LIMIT}&${ASSOCIATIONS}&${PROPERTIES}`, - }) - .then((data) => data.json()); - // functions.logger.info("Hello logs!", {structuredData: true}); - // response.send("Hello from Fireba); - // send meetings and contacts as json - response.send({ meetings: meetings.results, contacts }); + .apiRequest({ + method: "get", + path: `/crm/v3/objects/meetings?${LIMIT}&${ASSOCIATIONS}&${PROPERTIES}`, + }) + .then((data) => data.json()); + return response.send({meetings: meetings.results, contacts}); +}); + +app.delete("/:id", async (request: Request, response: Response) => { + const hubspotClient = new Client({accessToken: TOKEN}); + if (!request.params.id) { + return response.status(400).send({error: "No id provided"}); + } + const ids = request.params.id.split(","); + const data = await Promise.all( + ids.map((id: string) => + hubspotClient.apiRequest({method: "delete", path: `/crm/v3/objects/meetings/${id}`}).then((data) => data.status) + ) + ); + return response.send({statuses: data}); }); exports.meetings = functions.https.onRequest(app); diff --git a/package-lock.json b/package-lock.json index cb78a83..46db1a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,8 @@ "@emotion/react": "^11.11.0", "@emotion/styled": "^11.11.0", "@fontsource/inter": "^4.5.15", + "@formiz/core": "^1.8.1", + "@formiz/validations": "^1.0.0", "@formkit/auto-animate": "^1.0.0-beta.6", "@lukemorales/query-key-factory": "^1.2.0", "@tanstack/react-query": "^4.29.5", @@ -3662,6 +3664,49 @@ "resolved": "https://registry.npmjs.org/@fontsource/inter/-/inter-4.5.15.tgz", "integrity": "sha512-FzleM9AxZQK2nqsTDtBiY0PMEVWvnKnuu2i09+p6DHvrHsuucoV2j0tmw+kAT3L4hvsLdAIDv6MdGehsPIdT+Q==" }, + "node_modules/@formiz/core": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@formiz/core/-/core-1.8.1.tgz", + "integrity": "sha512-1+hzKqJYqMO1cjnWPo5D85A7oRVdrbPxUzDKFgQZpZcE58z//64lbtkS9yrkrmI3Eor126bt1XM5bq+BieoGug==", + "dependencies": { + "lodash": "4.17.21", + "lodash-es": "4.17.21", + "rxjs": "6.6.3" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/@formiz/core/node_modules/rxjs": { + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/@formiz/core/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/@formiz/validations": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@formiz/validations/-/validations-1.0.0.tgz", + "integrity": "sha512-pGTf0IQmSDhK7+4oTYjwtkn5TXqts33URSFXcUBMidDJgd1bSUzTQMNftg7YCeRPY8ROSsaJNWP7bFwtwHQeSA==", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, "node_modules/@formkit/auto-animate": { "version": "1.0.0-beta.6", "resolved": "https://registry.npmjs.org/@formkit/auto-animate/-/auto-animate-1.0.0-beta.6.tgz", @@ -14439,6 +14484,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", diff --git a/package.json b/package.json index d79ddb9..3411579 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,8 @@ "@emotion/react": "^11.11.0", "@emotion/styled": "^11.11.0", "@fontsource/inter": "^4.5.15", + "@formiz/core": "^1.8.1", + "@formiz/validations": "^1.0.0", "@formkit/auto-animate": "^1.0.0-beta.6", "@lukemorales/query-key-factory": "^1.2.0", "@tanstack/react-query": "^4.29.5", diff --git a/src/components/Toast/index.ts b/src/components/Toast/index.ts new file mode 100644 index 0000000..5eace02 --- /dev/null +++ b/src/components/Toast/index.ts @@ -0,0 +1,33 @@ +import { UseToastOptions, useToast } from '@chakra-ui/react'; + +export const toastDefaultConfig: UseToastOptions = { + duration: 3000, + isClosable: true, + position: 'top-right', + variant: 'solid', +}; + +export const useToastError = () => + useToast({ + ...toastDefaultConfig, + status: 'error', + duration: 5000, + }); + +export const useToastWarning = () => + useToast({ + ...toastDefaultConfig, + status: 'warning', + }); + +export const useToastSuccess = () => + useToast({ + ...toastDefaultConfig, + status: 'success', + }); + +export const useToastInfo = () => + useToast({ + ...toastDefaultConfig, + status: 'info', + }); diff --git a/src/containers/ColorModeSwitcher.tsx b/src/containers/ColorModeSwitcher.tsx deleted file mode 100644 index 4500cc2..0000000 --- a/src/containers/ColorModeSwitcher.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import * as React from 'react'; -import { useColorMode, useColorModeValue, IconButton, IconButtonProps } from '@chakra-ui/react'; -import { FaMoon, FaSun } from 'react-icons/fa'; - -type ColorModeSwitcherProps = Omit; - -export const ColorModeSwitcher: React.FC = (props) => { - const { toggleColorMode } = useColorMode(); - const text = useColorModeValue('dark', 'light'); - const SwitchIcon = useColorModeValue(FaMoon, FaSun); - - return ( - } - aria-label={`Switch to ${text} mode`} - {...props} - /> - ); -}; diff --git a/src/containers/MeetingCreateView/MeetingCreateView.tsx b/src/containers/MeetingCreateView/MeetingCreateView.tsx new file mode 100644 index 0000000..5f88b11 --- /dev/null +++ b/src/containers/MeetingCreateView/MeetingCreateView.tsx @@ -0,0 +1,84 @@ +import React from 'react'; + +import { Button, ButtonGroup, Heading } from '@chakra-ui/react'; +import { Formiz, useForm } from '@formiz/core'; +import { useNavigate } from 'react-router-dom'; + +import { useToastError, useToastSuccess } from '../../components/Toast'; +// import { UserForm } from '@/spa/admin/users/UserForm'; +// import { useUserCreate } from '@/spa/admin/users/users.service'; +import { Page, PageBottomBar, PageContent, PageTopBar } from '../Page/Page'; + +export const MeetingCreateView = () => { + const navigate = useNavigate(); + const form = useForm({ subscribe: false }); + + const toastError = useToastError(); + const toastSuccess = useToastSuccess(); + + // const createUser = useUserCreate({ + // onError: (error) => { + // if (error.response) { + // const { title, errorKey } = error.response.data; + // toastError({ + // title: t('users:create.feedbacks.updateError.title'), + // description: title, + // }); + // switch (errorKey) { + // case 'userexists': + // form.invalidateFields({ + // login: t('users:data.login.alreadyUsed'), + // }); + // break; + // case 'emailexists': + // form.invalidateFields({ + // email: t('users:data.email.alreadyUsed'), + // }); + // break; + // } + // } + // }, + // onSuccess: () => { + // toastSuccess({ + // title: t('users:create.feedbacks.updateSuccess.title'), + // }); + // navigate('/admin/users'); + // }, + // }); + + // const submitCreateUser = async (values: TODO) => { + // const newUser = { + // ...values, + // }; + // await createUser.mutate(newUser); + // }; + + return ( + + { + console.log('ok'); + }} + connect={form} + > +
+ navigate(-1)}> + New Meeting + + {/* */} + + + + + + +
+
+
+ ); +}; + +export default MeetingCreateView; diff --git a/src/containers/MeetingUpdateView/MeetingUpdateView.tsx b/src/containers/MeetingUpdateView/MeetingUpdateView.tsx new file mode 100644 index 0000000..b252343 --- /dev/null +++ b/src/containers/MeetingUpdateView/MeetingUpdateView.tsx @@ -0,0 +1,103 @@ +import React from 'react'; + +import { Box, Button, ButtonGroup, HStack, Heading, SkeletonText, Stack, Text } from '@chakra-ui/react'; +import { Formiz, useForm } from '@formiz/core'; +import { useNavigate, useParams } from 'react-router-dom'; + +import { ErrorPage } from '../../components/ErrorPage'; +import { useToastError, useToastSuccess } from '../../components/Toast'; +// import { useUser, useUserUpdate } from '@/spa/admin/users/users.service'; +import { Page, PageBottomBar, PageContent, PageTopBar } from '../Page/Page'; +import { Loader } from '../Router/Router'; + +// import { UserForm } from './UserForm'; + +export const MeetingUpdateView = () => { + const { id } = useParams(); + const navigate = useNavigate(); + // const user = useUser(id, { + // refetchOnWindowFocus: false, + // enabled: !!login, + // }); + + const form = useForm({ subscribe: false }); + + const toastSuccess = useToastSuccess(); + const toastError = useToastError(); + + // const { mutate: editUser, isLoading: editUserIsLoading } = useUserUpdate({ + // onError: (error) => { + // if (error.response) { + // const { title, errorKey } = error.response.data; + // toastError({ + // title: t('users:update.feedbacks.updateError.title'), + // description: title, + // }); + // switch (errorKey) { + // case 'userexists': + // form.invalidateFields({ + // login: t('users:data.login.alreadyUsed'), + // }); + // break; + // case 'emailexists': + // form.invalidateFields({ + // email: t('users:data.email.alreadyUsed'), + // }); + // break; + // } + // } + // }, + // onSuccess: () => { + // toastSuccess({ + // title: t('users:update.feedbacks.updateSuccess.title'), + // }); + // navigate(-1); + // }, + // }); + // const submitEditUser = (values: TODO) => { + // const userToSend = { + // id: user.data?.id, + // ...values, + // }; + // editUser(userToSend); + // }; + + return ( + + navigate(-1)}> + + + {false || false ? ( + + ) : ( + + 000 + + Meeting ID: 000 + + + )} + + + + {/* {user.isFetching && } + {user.isError && !user.isFetching && } + {!user.isError && !user.isFetching && ( */} + +
+ {/* */} + + + + + + +
+
+
+ ); +}; + +export default MeetingUpdateView; diff --git a/src/containers/MeetingsActions/MeetingsActions.tsx b/src/containers/MeetingsActions/MeetingsActions.tsx index 62ca94c..9853dff 100644 --- a/src/containers/MeetingsActions/MeetingsActions.tsx +++ b/src/containers/MeetingsActions/MeetingsActions.tsx @@ -7,6 +7,8 @@ import { BiCalendar, BiFilter, BiSort } from 'react-icons/bi'; import { FiChevronDown, FiEdit, FiPlus } from 'react-icons/fi'; import { Link } from 'react-router-dom'; +import { useToastError, useToastSuccess } from '../../components/Toast'; +import { useMeetingRemove } from '../../services/meetings.service'; import { MeetingFilterType, MeetingSortType } from '../../types/meetings.types'; type MeetingsActionsProps = { @@ -16,6 +18,7 @@ type MeetingsActionsProps = { setFilter: (filter: MeetingFilterType) => void; range: DateRange | undefined; setRange: (range: DateRange | undefined) => void; + selected: string[]; selectedAll: boolean; toggleSelectedAll: () => void; invertSelected: () => void; @@ -34,11 +37,12 @@ const ActionsOptions = ({ selectedAll, toggleSelectedAll, invertSelected, -}: Pick) => ( + removeMeeting, +}: Pick & { removeMeeting: () => void }) => ( {selectedAll ? Unselect All : 'Select All'} Invert Selection - Delete Selected + removeMeeting()}>Delete Selected ); @@ -56,10 +60,25 @@ export const MeetingsActions = ({ setFilter, range, setRange, + selected, selectedAll, toggleSelectedAll, invertSelected, }: MeetingsActionsProps) => { + const toastSuccess = useToastSuccess(); + const toastError = useToastError(); + + const meetingRemove = useMeetingRemove({ + onSuccess: (_, { id }) => { + toastSuccess({ title: 'Meeting deleted', description: `Meeting ${id} has been deleted.` }); + }, + onError: (_, { id }) => { + toastError({ title: 'Meeting delete error', description: `Meeting ${id} could not be deleted.` }); + }, + }); + const removeMeeting = () => meetingRemove.mutate({ id: selected.join(',') }); + const isRemovalLoading = meetingRemove.isLoading; + let period = 'Period'; if (range?.from) { if (!range.to) { @@ -90,20 +109,43 @@ export const MeetingsActions = ({ - } rightIcon={} display={{ base: 'none', md: 'flex' }}> + } + rightIcon={} + display={{ base: 'none', md: 'flex' }} + isLoading={isRemovalLoading} + > Actions - + - } variant="outline" display={{ base: 'flex', md: 'none' }} /> - + } + variant="outline" + display={{ base: 'flex', md: 'none' }} + isLoading={isRemovalLoading} + /> + } rightIcon={} display={{ base: 'none', md: 'flex' }}> - `Sort: {sort.charAt(0) + sort.slice(1).toLowerCase()} + Sort: {sort.charAt(0) + sort.slice(1).toLowerCase()} @@ -129,14 +171,14 @@ export const MeetingsActions = ({ - } diff --git a/src/containers/MeetingsView/MeetingsView.tsx b/src/containers/MeetingsView/MeetingsView.tsx index 7aab9a8..0bd309a 100644 --- a/src/containers/MeetingsView/MeetingsView.tsx +++ b/src/containers/MeetingsView/MeetingsView.tsx @@ -25,7 +25,7 @@ const MeetingsView = () => { const filteredMeetings = filterMeetingList(sortedMeetings, filter); const rangedMeetings = rangeMeetingList(filteredMeetings, range); const pagedMeetings = rangedMeetings.slice(pageSize * (page - 1), pageSize * page); - const selectedAll = selected.length === rangedMeetings.length; + const selectedAll = !!selected.length && selected.length === rangedMeetings.length; const toggleSelectedAll = () => (selectedAll ? setSelected([]) : setSelected(rangedMeetings.map((m: Meeting) => m.id))); const invertSelected = () => setSelected(rangedMeetings.map((m: Meeting) => m.id).filter((id) => !selected.includes(id))); @@ -44,6 +44,7 @@ const MeetingsView = () => { setFilter={setFilter} range={range} setRange={setRange} + selected={selected} selectedAll={selectedAll} toggleSelectedAll={toggleSelectedAll} invertSelected={invertSelected} diff --git a/src/containers/Router/Router.tsx b/src/containers/Router/Router.tsx index c5c3b1e..8943bc8 100644 --- a/src/containers/Router/Router.tsx +++ b/src/containers/Router/Router.tsx @@ -1,9 +1,11 @@ +import React, { Suspense, useCallback } from 'react'; + +import { Center, Spinner } from '@chakra-ui/react'; +import { BrowserRouter, Route, Routes, useNavigate, useSearchParams } from 'react-router-dom'; + import { ErrorBoundary } from '../../components/ErrorBoundary'; import { ErrorPage } from '../../components/ErrorPage'; import { Layout } from '../Layout/Layout'; -import { Center, Spinner } from '@chakra-ui/react'; -import React, { Suspense, useCallback } from 'react'; -import { BrowserRouter, Route, Routes, useSearchParams, useNavigate } from 'react-router-dom'; export const Loader = () => (
@@ -34,13 +36,8 @@ export const useRedirectFromUrl = (defaultTo = '/') => { }; const MeetingsView = React.lazy(() => import('../MeetingsView/MeetingsView')); -// const MeetingCreateView = React.lazy( -// () => import("@/spa/views/MeetingCreateView") -// ); -// const MeetingUpdateView = React.lazy( -// () => import("@/spa/views/MeetingUpdateView") -// ); -// const ApiView = React.lazy(() => import("@/spa/views/ApiView")); +const MeetingCreateView = React.lazy(() => import('../MeetingCreateView/MeetingCreateView')); +const MeetingUpdateView = React.lazy(() => import('../MeetingUpdateView/MeetingUpdateView')); export const Router = () => { return ( @@ -50,6 +47,8 @@ export const Router = () => { }> } /> + } /> + } /> } /> diff --git a/src/services/meetings.service.ts b/src/services/meetings.service.ts index 6d7c39b..70e4e82 100644 --- a/src/services/meetings.service.ts +++ b/src/services/meetings.service.ts @@ -1,71 +1,45 @@ -import { Meeting, MeetingList } from '../types/meetings.types'; import { createQueryKeys, inferQueryKeys } from '@lukemorales/query-key-factory'; -import { - // UseMutationOptions, - UseQueryOptions, // useMutation, - useQuery, // useQueryClient, -} from '@tanstack/react-query'; +import { UseMutationOptions, UseQueryOptions, useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import Axios, { AxiosError } from 'axios'; import { DateRange } from 'react-day-picker'; +// import { useToastError, useToastSuccess } from '../../components/Toast'; +import { Meeting, MeetingList } from '../types/meetings.types'; + +type MeetingWithIdOnly = { id: string }; + // type UserMutateError = { // title: string; // errorKey: "userexists" | "emailexists"; // }; -export const sortMeetingList = (meetings: Meeting[], sort: string) => { - if (sort === 'NEWEST') { - return meetings.sort((a, b) => { - return new Date(b.properties.hs_meeting_start_time).getTime() - new Date(a.properties.hs_meeting_start_time).getTime(); - }); - } else if (sort === 'OLDEST') { - return meetings.sort((a, b) => { - return new Date(a.properties.hs_meeting_start_time).getTime() - new Date(b.properties.hs_meeting_start_time).getTime(); - }); - } else { - return meetings; - } -}; +const MEETINGS_API_BASE_URL = 'https://us-central1-epicbrief-c47c8.cloudfunctions.net/meetings'; +// const MEETINGS_API_BASE_URL = 'http://127.0.0.1:5001/epicbrief-c47c8/us-central1/meetings'; -export const filterMeetingList = (meetings: Meeting[], filter: string) => { - if (filter === 'ALL') { - return meetings; - } else { - return meetings.filter((meeting) => { - return meeting.properties.hs_meeting_outcome === filter; - }); - } -}; - -export const rangeMeetingList = (meetings: Meeting[], range: DateRange | undefined) => { - if (!range || !range.from || !range.to) { - return meetings; - } else { - return meetings.filter((meeting) => { - return ( - range.from && - new Date(meeting.properties.hs_meeting_start_time).getTime() >= range.from.getTime() && - range.to && - new Date(meeting.properties.hs_meeting_start_time).getTime() <= range.to.getTime() - ); - }); - } +export const useMeetingRemove = (config: UseMutationOptions = {}) => { + const queryClient = useQueryClient(); + return useMutation((meeting: MeetingWithIdOnly): Promise => Axios.delete(`${MEETINGS_API_BASE_URL}/${meeting.id}`), { + ...config, + onSuccess: (...args) => { + queryClient.invalidateQueries(meetingsKeys.meetings._def); + config?.onSuccess?.(...args); + }, + }); }; -const usersKeys = createQueryKeys('usersService', { +const meetingsKeys = createQueryKeys('usersService', { meetings: (params: { limit?: number; after?: number }) => [params], - users: (params: { page?: number; size?: number }) => [params], - user: (params: { login?: string }) => [params], }); -type UsersKeys = inferQueryKeys; + +type MeetingsKeys = inferQueryKeys; export const useMeetingList = ( { page = 0, size = 10, limit = 20 } = {}, - config: UseQueryOptions = {} + config: UseQueryOptions = {} ) => { const result = useQuery( - usersKeys.meetings({ limit: 20, after: 0 }).queryKey, - (): Promise => Axios.get('https://us-central1-epicbrief-c47c8.cloudfunctions.net/meetings'), + meetingsKeys.meetings({ limit: 20, after: 0 }).queryKey, + (): Promise => Axios.get(`${MEETINGS_API_BASE_URL}?limit=${limit}&after=${page}`), { keepPreviousData: true, ...config } ); console.log('result', result.data); @@ -166,21 +140,41 @@ export const useMeetingList = ( // ); // }; -// type UserWithLoginOnly = Pick; +export const sortMeetingList = (meetings: Meeting[], sort: string) => { + if (sort === 'NEWEST') { + return meetings.sort((a, b) => { + return new Date(b.properties.hs_meeting_start_time).getTime() - new Date(a.properties.hs_meeting_start_time).getTime(); + }); + } else if (sort === 'OLDEST') { + return meetings.sort((a, b) => { + return new Date(a.properties.hs_meeting_start_time).getTime() - new Date(b.properties.hs_meeting_start_time).getTime(); + }); + } else { + return meetings; + } +}; + +export const filterMeetingList = (meetings: Meeting[], filter: string) => { + if (filter === 'ALL') { + return meetings; + } else { + return meetings.filter((meeting) => { + return meeting.properties.hs_meeting_outcome === filter; + }); + } +}; -// export const useUserRemove = ( -// config: UseMutationOptions = {} -// ) => { -// const queryClient = useQueryClient(); -// return useMutation( -// (user: UserWithLoginOnly): Promise => -// Axios.delete(`/admin/users/${user.login}`), -// { -// ...config, -// onSuccess: (...args) => { -// queryClient.invalidateQueries(usersKeys.users._def); -// config?.onSuccess?.(...args); -// }, -// } -// ); -// }; +export const rangeMeetingList = (meetings: Meeting[], range: DateRange | undefined) => { + if (!range || !range.from || !range.to) { + return meetings; + } else { + return meetings.filter((meeting) => { + return ( + range.from && + new Date(meeting.properties.hs_meeting_start_time).getTime() >= range.from.getTime() && + range.to && + new Date(meeting.properties.hs_meeting_start_time).getTime() <= range.to.getTime() + ); + }); + } +};