diff --git a/.env.sample b/.env.sample index c2d4e1fb79..0465863d09 100644 --- a/.env.sample +++ b/.env.sample @@ -1,4 +1,4 @@ -REACT_APP_API_URL=http://localhost:4000 +REACT_APP_API_URL=http://localhost:4000/ NODE_ENV=development MONGO_URL=mongodb://localhost:27017/erxes NODE_OPTIONS=--max-old-space-size=1536 diff --git a/frontend/core-ui/src/modules/app/hooks/usePluginsRouter.tsx b/frontend/core-ui/src/modules/app/hooks/usePluginsRouter.tsx index 345b1ad14f..07a6e066a7 100644 --- a/frontend/core-ui/src/modules/app/hooks/usePluginsRouter.tsx +++ b/frontend/core-ui/src/modules/app/hooks/usePluginsRouter.tsx @@ -16,7 +16,6 @@ export const getPluginsRoutes = () => { pluginName: plugin.name, })), ); - return allModules.map((module) => ( { } /> } /> } /> - } /> }> } /> diff --git a/frontend/plugins/pos_ui/src/modules/states/PosCount.tsx b/frontend/plugins/pos_ui/src/modules/states/PosCount.tsx new file mode 100644 index 0000000000..80afd30f3d --- /dev/null +++ b/frontend/plugins/pos_ui/src/modules/states/PosCount.tsx @@ -0,0 +1,3 @@ +import { atom } from 'jotai'; + +export const posTotalCountAtom = atom(null); diff --git a/frontend/plugins/sales_ui/module-federation.config.ts b/frontend/plugins/sales_ui/module-federation.config.ts index 1154350a44..ecd3faaf06 100644 --- a/frontend/plugins/sales_ui/module-federation.config.ts +++ b/frontend/plugins/sales_ui/module-federation.config.ts @@ -16,10 +16,9 @@ const config: ModuleFederationConfig = { name: 'sales_ui', exposes: { './config': './src/config.tsx', - './deals': './src/modules/deals/Main.tsx', + './sales': './src/modules/main/Main.tsx', './dealsSettings': './src/pages/SettingsPage.tsx', './Widgets': './src/widgets/Widgets.tsx', - './pos': './src/modules/pos/pos/Main.tsx', './posSettings': './src/modules/pos/pos/Settings.tsx', }, diff --git a/frontend/plugins/sales_ui/src/config.tsx b/frontend/plugins/sales_ui/src/config.tsx index 92c6d4352c..8d08a0f65d 100644 --- a/frontend/plugins/sales_ui/src/config.tsx +++ b/frontend/plugins/sales_ui/src/config.tsx @@ -6,11 +6,17 @@ import { import { lazy, Suspense } from 'react'; const SalesNavigation = lazy(() => - import('./modules/SalesNavigation').then((module) => ({ + import('./modules/navigation/SalesNavigation').then((module) => ({ default: module.SalesNavigation, })), ); +const PosOrderNavigation = lazy(() => + import('./modules/navigation/PosOrderNavigation').then((module) => ({ + default: module.PosOrderNavigation, + })), +); + export const CONFIG = { name: 'sales', icon: IconBriefcase, @@ -24,20 +30,28 @@ export const CONFIG = { ), + subGroups: () => ( + }> + + + ), }, modules: [ { - name: 'deals', - icon: IconSandbox, - path: 'deals', - hasSettings: true, + name: 'sales', + icon: IconBriefcase, + path: 'sales', + hasSettings: false, + hasRelationWidget: true, + hasFloatingWidget: false, }, { name: 'pos', icon: IconCashRegister, path: 'pos', - hasSettings: true, + hasSettings: false, hasRelationWidget: true, + hasFloatingWidget: false, }, ], }; diff --git a/frontend/plugins/sales_ui/src/modules/SalesNavigation.tsx b/frontend/plugins/sales_ui/src/modules/SalesNavigation.tsx deleted file mode 100644 index b0a1440381..0000000000 --- a/frontend/plugins/sales_ui/src/modules/SalesNavigation.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { NavigationMenuLinkItem } from 'erxes-ui'; - -export const SalesNavigation = () => { - return ( - <> - - - - ); -}; diff --git a/frontend/plugins/sales_ui/src/modules/deals/Main.tsx b/frontend/plugins/sales_ui/src/modules/deals/Main.tsx deleted file mode 100644 index 5a5c9f1f60..0000000000 --- a/frontend/plugins/sales_ui/src/modules/deals/Main.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { Route, Routes } from 'react-router'; -import { Suspense, lazy } from 'react'; - -import { Spinner } from 'erxes-ui/components'; - -const DealsMain = lazy(() => - import('~/pages/SalesIndexPage').then((module) => ({ - default: module.SalesIndexPage, - })), -); - -const App = () => { - return ( - }> - - } /> - - - ); -}; - -export default App; diff --git a/frontend/plugins/sales_ui/src/modules/main/Main.tsx b/frontend/plugins/sales_ui/src/modules/main/Main.tsx new file mode 100644 index 0000000000..17af95845b --- /dev/null +++ b/frontend/plugins/sales_ui/src/modules/main/Main.tsx @@ -0,0 +1,37 @@ +import { Navigate, Route, Routes } from 'react-router'; +import { Suspense, lazy } from 'react'; +import { Spinner } from 'erxes-ui/components'; + +const DealsMain = lazy(() => + import('~/pages/SalesIndexPage').then((module) => ({ + default: module.SalesIndexPage, + })), +); + +const OrdersMain = lazy(() => + import('~/pages/OrdersPage').then((module) => ({ + default: module.OrdersPage, + })), +); + +const PosMain = lazy(() => + import('~/pages/PosIndexPage').then((module) => ({ + default: module.PosIndexPage, + })), +); + +const App = () => { + return ( + }> + + } /> + } /> + } /> + } /> + } /> + + + ); +}; + +export default App; diff --git a/frontend/plugins/sales_ui/src/modules/navigation/PosOrderNavigation.tsx b/frontend/plugins/sales_ui/src/modules/navigation/PosOrderNavigation.tsx new file mode 100644 index 0000000000..b6e146dfe6 --- /dev/null +++ b/frontend/plugins/sales_ui/src/modules/navigation/PosOrderNavigation.tsx @@ -0,0 +1,237 @@ +import { useAtomValue } from 'jotai'; +import { currentUserState } from 'ui-modules'; +import { useNavigate } from 'react-router-dom'; +import { + Button, + Collapsible, + DropdownMenu, + IconComponent, + NavigationMenuGroup, + NavigationMenuLinkItem, + Sidebar, + Skeleton, + TextOverflowTooltip, + useToast, +} from 'erxes-ui'; +import { + IconRestore, + IconCaretRightFilled, + IconChecklist, + IconClipboard, + IconDotsVertical, + IconLink, + IconSettings, +} from '@tabler/icons-react'; +import { useGetPos } from '~/modules/pos/hooks/useGetPos'; + +type Pos = { + _id: string; + name: string; + icon?: string; +}; + +function LoadingSkeleton() { + return ( +
+ {[1, 2, 3].map((i) => ( + + ))} +
+ ); +} + +interface posItemProps { + pos: Pos; +} + +function PosItem({ pos }: posItemProps) { + return ( + + +
+ +
+ +
+
+
+ +
+ + + + + + + + + + + + + +
+
+ ); +} + +export function PosOrderNavigation() { + const currentUser = useAtomValue(currentUserState); + const { pos, loading } = useGetPos({ + variables: { userId: currentUser?._id }, + }); + + return ( + + {loading ? ( + + ) : ( + pos?.map((pos) => ) + )} + + ); +} + +const PosActionsMenu = ({ pos }: { pos: Pos }) => { + const navigate = useNavigate(); + const { toast } = useToast(); + + const handleCopyLink = async () => { + const posLink = `${window.location.origin}/operation/pos/${pos._id}/orders`; + try { + await navigator.clipboard.writeText(posLink); + toast({ + variant: 'default', + title: 'Link copied to clipboard', + }); + } catch (e) { + toast({ + variant: 'destructive', + title: 'Failed to copy link', + description: e as string, + }); + } + }; + + return ( + + + + + + { + navigate(`/settings/operation/pos/details/${pos._id}`); + }} + > + + Go to pos settings + + { + handleCopyLink(); + }} + className="cursor-pointer" + > + + Copy link + + + {/* + + Archive team + + + + + + Subscribe + + + + + e.preventDefault()}> + + An issue is added to the team + + e.preventDefault()}> + + An issue is marked completed or cancelled + + e.preventDefault()}> + + An issue is added to the triage queue + + + */} + + + ); +}; diff --git a/frontend/plugins/sales_ui/src/modules/navigation/SalesNavigation.tsx b/frontend/plugins/sales_ui/src/modules/navigation/SalesNavigation.tsx new file mode 100644 index 0000000000..4827990d16 --- /dev/null +++ b/frontend/plugins/sales_ui/src/modules/navigation/SalesNavigation.tsx @@ -0,0 +1,10 @@ +import { NavigationMenuLinkItem } from 'erxes-ui'; + +export const SalesNavigation = () => { + return ( + <> + + + + ); +}; diff --git a/frontend/plugins/sales_ui/src/modules/orders/components/OrderRecordTable.tsx b/frontend/plugins/sales_ui/src/modules/orders/components/OrderRecordTable.tsx new file mode 100644 index 0000000000..b10c612fe2 --- /dev/null +++ b/frontend/plugins/sales_ui/src/modules/orders/components/OrderRecordTable.tsx @@ -0,0 +1,39 @@ +import { RecordTable } from 'erxes-ui'; +import { useOrdersList } from '../hooks/useOrdersList'; +import { OrderCommandBar } from '~/modules/orders/components/order-command-bar/OrderCommandBar'; +import { orderColumns } from '~/modules/orders/components/columns'; + +export const OrderRecordTable = () => { + const { ordersList, handleFetchMore, loading, pageInfo } = useOrdersList(); + + return ( + + + + + + + {loading && } + + + + + + + + ); +}; diff --git a/frontend/plugins/sales_ui/src/modules/orders/components/columns.tsx b/frontend/plugins/sales_ui/src/modules/orders/components/columns.tsx new file mode 100644 index 0000000000..c3dee061ec --- /dev/null +++ b/frontend/plugins/sales_ui/src/modules/orders/components/columns.tsx @@ -0,0 +1,123 @@ +import { + IconBuilding, + IconChartBar, + IconLabel, + IconMobiledata, + IconPhone, + IconClock, + IconUser, +} from '@tabler/icons-react'; +import { ColumnDef } from '@tanstack/table-core'; +import { + RecordTable, + TextOverflowTooltip, + RecordTableInlineCell, + Badge, +} from 'erxes-ui'; +import { ordersMoreColumn } from '~/modules/orders/components/ordersMoreColumn'; + +import { IOrder } from '~/modules/pos/types/order'; + +export const orderColumns: ColumnDef[] = [ + ordersMoreColumn, + RecordTable.checkboxColumn as ColumnDef, + { + id: 'name', + accessorKey: 'name', + header: () => , + cell: ({ cell }) => { + return ( + + + + ); + }, + }, + { + id: 'isOnline', + accessorKey: 'isOnline', + header: () => ( + + ), + cell: ({ cell }) => { + const value = cell.getValue() as boolean; + return ( + + + {value ? 'Online' : 'Offline'} + + + ); + }, + }, + { + id: 'onServer', + accessorKey: 'onServer', + header: () => ( + + ), + cell: ({ cell }) => { + const value = cell.getValue() as boolean; + return ( + + {value ? 'On Server' : 'Local Only'} + + ); + }, + }, + { + id: 'branchTitle', + accessorKey: 'branchTitle', + header: () => , + cell: ({ cell }) => { + return ( + + + + ); + }, + }, + { + id: 'departmentTitle', + accessorKey: 'departmentTitle', + header: () => ( + + ), + cell: ({ cell }) => { + return ( + + + + ); + }, + }, + { + id: 'createdAt', + accessorKey: 'createdAt', + header: () => ( + + ), + cell: ({ cell }) => { + const rawDate = cell.getValue() as string; + const formattedDate = new Date(rawDate).toLocaleString(); + + return ( + + + + ); + }, + }, + { + id: 'createdBy', + accessorKey: 'createdBy', + header: () => , + cell: ({ cell }) => { + return ( + + + + ); + }, + }, +]; diff --git a/frontend/plugins/sales_ui/src/modules/orders/components/order-command-bar/OrderCommandBar.tsx b/frontend/plugins/sales_ui/src/modules/orders/components/order-command-bar/OrderCommandBar.tsx new file mode 100644 index 0000000000..c1376d5110 --- /dev/null +++ b/frontend/plugins/sales_ui/src/modules/orders/components/order-command-bar/OrderCommandBar.tsx @@ -0,0 +1,30 @@ +import { IconPlus } from '@tabler/icons-react'; + +import { Button, CommandBar, RecordTable, Separator } from 'erxes-ui'; +import { OrderDelete } from '~/modules/orders/components/order-command-bar/delete/delete'; + +export const OrderCommandBar = () => { + const { table } = RecordTable.useRecordTable(); + + return ( + 0}> + + + {table.getFilteredSelectedRowModel().rows.length} selected + + + row.original._id) + .join(',')} + /> + + + + + ); +}; diff --git a/frontend/plugins/sales_ui/src/modules/orders/components/order-command-bar/delete/delete.tsx b/frontend/plugins/sales_ui/src/modules/orders/components/order-command-bar/delete/delete.tsx new file mode 100644 index 0000000000..bd4620999b --- /dev/null +++ b/frontend/plugins/sales_ui/src/modules/orders/components/order-command-bar/delete/delete.tsx @@ -0,0 +1,57 @@ +import { Button } from 'erxes-ui/components'; +import { IconTrash } from '@tabler/icons-react'; +import { useConfirm } from 'erxes-ui/hooks'; +import { useToast } from 'erxes-ui'; +import { ApolloError } from '@apollo/client'; +import { useRemovePos } from '@/pos/hooks/usePosRemove'; + +interface OrderDeleteProps { + orderIds: string; + onDeleteSuccess?: () => void; +} + +export const OrderDelete = ({ + orderIds, + onDeleteSuccess, +}: OrderDeleteProps) => { + const { confirm } = useConfirm(); + const { removePos } = useRemovePos(); + const { toast } = useToast(); + + const orderCount = orderIds.includes(',') ? orderIds.split(',').length : 1; + + return ( + + ); +}; diff --git a/frontend/plugins/sales_ui/src/modules/orders/components/ordersMoreColumn.tsx b/frontend/plugins/sales_ui/src/modules/orders/components/ordersMoreColumn.tsx new file mode 100644 index 0000000000..a0ab4deda7 --- /dev/null +++ b/frontend/plugins/sales_ui/src/modules/orders/components/ordersMoreColumn.tsx @@ -0,0 +1,39 @@ +import { Cell } from '@tanstack/react-table'; +import { useSetAtom } from 'jotai'; +import { useSearchParams } from 'react-router-dom'; +import { RecordTable } from 'erxes-ui'; + +import { IOrder } from '~/modules/pos/types/order'; +import { renderingOrderDetailAtom } from '~/modules/pos/states/orderDetail'; + +export const ordersMoreColumnCell = ({ + cell, +}: { + cell: Cell; +}) => { + const [searchParams, setSearchParams] = useSearchParams(); + const setRenderingOrderDetail = useSetAtom(renderingOrderDetailAtom); + const { _id } = cell.row.original; + + const setOpen = (orderId: string) => { + const newSearchParams = new URLSearchParams(searchParams); + newSearchParams.set('order_id', orderId); + setSearchParams(newSearchParams); + }; + + return ( + { + setOpen(_id); + setRenderingOrderDetail(false); + }} + /> + ); +}; + +export const ordersMoreColumn = { + id: 'more', + cell: ordersMoreColumnCell, + size: 33, +}; diff --git a/frontend/plugins/sales_ui/src/modules/orders/hooks/useOrdersList.tsx b/frontend/plugins/sales_ui/src/modules/orders/hooks/useOrdersList.tsx new file mode 100644 index 0000000000..4577b7c875 --- /dev/null +++ b/frontend/plugins/sales_ui/src/modules/orders/hooks/useOrdersList.tsx @@ -0,0 +1,64 @@ +import { useQuery } from '@apollo/client'; +import { queries } from '~/modules/pos/graphql'; + +import { IOrder } from '~/modules/pos/types/order'; + +const POS_PER_PAGE = 30; + +export const useOrdersList = (options = {}) => { + const { data, loading, fetchMore } = useQuery(queries.posList, { + variables: { + perPage: POS_PER_PAGE, + ...options, + }, + }); + + const transformedPosList = + data?.posList?.map((order: IOrder) => ({ + _id: order._id, + name: order.name, + isOnline: order.isOnline || false, + onServer: order.onServer || false, + branchTitle: order.branchTitle || '', + departmentTitle: order.departmentTitle || '', + createdAt: order.createdAt, + createdBy: order?.user?.details?.fullName || 'Admin', + })) || []; + + const handleFetchMore = () => { + if (!data?.ordersList) { + return; + } + + fetchMore({ + variables: { + page: Math.ceil(transformedPosList.length / POS_PER_PAGE) + 1, + perPage: POS_PER_PAGE, + }, + updateQuery: (prev, { fetchMoreResult }) => { + if (!fetchMoreResult) { + return prev; + } + return Object.assign({}, prev, { + ordersList: [ + ...(prev.ordersList || []), + ...fetchMoreResult.ordersList, + ], + }); + }, + }); + }; + + return { + loading, + ordersList: transformedPosList, + totalCount: data?.ordersList?.length || 0, + handleFetchMore, + pageInfo: { + hasNextPage: transformedPosList.length < (data?.ordersList?.length || 0), + hasPreviousPage: false, + startCursor: null, + endCursor: null, + }, + }; +}; diff --git a/frontend/plugins/sales_ui/src/modules/pos/PosNavigation.tsx b/frontend/plugins/sales_ui/src/modules/pos/PosNavigation.tsx deleted file mode 100644 index 3a3b9148c7..0000000000 --- a/frontend/plugins/sales_ui/src/modules/pos/PosNavigation.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { NavigationMenuLinkItem } from 'erxes-ui'; - -export const PosNavigation = () => { - return ; -}; diff --git a/frontend/plugins/sales_ui/src/modules/pos/constants/PosCursorSessionKey.tsx b/frontend/plugins/sales_ui/src/modules/pos/constants/PosCursorSessionKey.tsx new file mode 100644 index 0000000000..0d35f71859 --- /dev/null +++ b/frontend/plugins/sales_ui/src/modules/pos/constants/PosCursorSessionKey.tsx @@ -0,0 +1,2 @@ +export const POS_CURSOR_SESSION_KEY = 'pos-cursor'; +export const LEADS_CURSOR_SESSION_KEY = 'leads-cursor'; diff --git a/frontend/plugins/sales_ui/src/modules/pos/graphql/queries.ts b/frontend/plugins/sales_ui/src/modules/pos/graphql/queries.ts index b28f148b3d..a1b8a1f6b5 100644 --- a/frontend/plugins/sales_ui/src/modules/pos/graphql/queries.ts +++ b/frontend/plugins/sales_ui/src/modules/pos/graphql/queries.ts @@ -84,6 +84,21 @@ const posList = gql` } } `; +const posOrdersList = gql` + query posOrdersList( + ${commonParamDefs} + $sortField: String + $sortDirection: Int + ) { + posList( + ${commonParams} + sortField: $sortField + sortDirection: $sortDirection + ) { + ${posCommonFields} + } + } +`; const productGroups = gql` query productGroups($posId: String!) { @@ -149,4 +164,4 @@ export default { getDbSchemaLabels, posSlots, posOrdersSummary, -}; \ No newline at end of file +}; diff --git a/frontend/plugins/sales_ui/src/modules/pos/graphql/queries/getPos.tsx b/frontend/plugins/sales_ui/src/modules/pos/graphql/queries/getPos.tsx new file mode 100644 index 0000000000..0e4024bd91 --- /dev/null +++ b/frontend/plugins/sales_ui/src/modules/pos/graphql/queries/getPos.tsx @@ -0,0 +1,114 @@ +import gql from 'graphql-tag'; +export const posCommonFields = ` + _id + name + description + orderPassword + scopeBrandIds + pdomain + createdAt + token + erxesAppToken + adminIds + cashierIds + paymentIds + paymentTypes + user { + _id + details { + avatar + fullName + } + } + + isOnline + onServer + branchId + departmentId + allowBranchIds + beginNumber + maxSkipNumber + waitingScreen + kitchenScreen + kioskMachine + uiOptions + ebarimtConfig + erkhetConfig + cardsConfig + catProdMappings { + _id + categoryId + code + name + productId + } + + initialCategoryIds + kioskExcludeCategoryIds + kioskExcludeProductIds + deliveryConfig + checkRemainder + permissionConfig + allowTypes + isCheckRemainder + checkExcludeCategoryIds + banFractions + + branchTitle + departmentTitle +`; +// export const GET_POS = gql` +// query getPos( +// $name: String +// $userId: String +// $teamIds: [String] +// $projectId: String +// ) { +// getPos( +// name: $name +// userId: $userId +// teamIds: $teamIds +// projectId: $projectId +// ) { +// _id +// name +// isOnline +// onServer +// branchTitle +// departmentTitle +// createdAt +// updatedAt +// user { +// _id +// details { +// avatar +// fullName +// } +// } +// } +// } + +// `; +const commonParamDefs = ` + $page: Int, + $perPage: Int +`; +const commonParams = ` + page: $page, + perPage: $perPage +`; +export const POS_LIST = gql` +query posList( + ${commonParamDefs} + $sortField: String + $sortDirection: Int +) { + posList( + ${commonParams} + sortField: $sortField + sortDirection: $sortDirection + ) { + ${posCommonFields} + } +} +`; diff --git a/frontend/plugins/sales_ui/src/modules/pos/hooks/useGetCurrentUsersPos.tsx b/frontend/plugins/sales_ui/src/modules/pos/hooks/useGetCurrentUsersPos.tsx new file mode 100644 index 0000000000..f50f3b73a1 --- /dev/null +++ b/frontend/plugins/sales_ui/src/modules/pos/hooks/useGetCurrentUsersPos.tsx @@ -0,0 +1,27 @@ +import { useQuery, QueryHookOptions } from '@apollo/client'; +import { POS_LIST } from '@/pos/graphql/queries/getPos'; +import { IPos } from '@/pos/types/pos'; +import { currentUserState } from 'ui-modules'; +import { useAtomValue } from 'jotai'; + +interface IGetPosQueryResponse { + getPosList: IPos[]; +} + +export const useGetCurrentUsersPos = ( + options?: QueryHookOptions, +) => { + const currentUser = useAtomValue(currentUserState); + const userId = currentUser?._id; + const { data, loading } = useQuery(POS_LIST, { + ...options, + variables: { + userId, + ...options?.variables, + }, + }); + + const pos = data?.getPosList; + + return { pos, loading }; +}; diff --git a/frontend/plugins/sales_ui/src/modules/pos/hooks/useGetPos.tsx b/frontend/plugins/sales_ui/src/modules/pos/hooks/useGetPos.tsx new file mode 100644 index 0000000000..e344481fbf --- /dev/null +++ b/frontend/plugins/sales_ui/src/modules/pos/hooks/useGetPos.tsx @@ -0,0 +1,16 @@ +import { useQuery, QueryHookOptions } from '@apollo/client'; +import { POS_LIST } from '~/modules/pos/graphql/queries/getPos'; + +import { IPos } from '~/modules/pos/types/pos'; + +interface IGetPosQueryResponse { + posList: IPos[]; +} + +export const useGetPos = (options?: QueryHookOptions) => { + const { data, loading } = useQuery(POS_LIST, options); + + const pos = data?.posList; + + return { pos, loading }; +}; diff --git a/frontend/plugins/sales_ui/src/modules/pos/pos-detail/hooks/UsePosLeadSessionKey.tsx b/frontend/plugins/sales_ui/src/modules/pos/pos-detail/hooks/UsePosLeadSessionKey.tsx new file mode 100644 index 0000000000..52f14fe423 --- /dev/null +++ b/frontend/plugins/sales_ui/src/modules/pos/pos-detail/hooks/UsePosLeadSessionKey.tsx @@ -0,0 +1,16 @@ +import { useLocation } from 'react-router'; +import { LEADS_CURSOR_SESSION_KEY, POS_CURSOR_SESSION_KEY } from '~/modules/pos/constants/PosCursorSessionKey'; + +import { PosPath } from '~/modules/pos/types/path/PosPath'; + + +export const useIsPosLeadSessionKey = () => { + const { pathname } = useLocation(); + const isLead = new RegExp(`(^|/)${PosPath.Leads}(/|$)`).test(pathname); + return { + isLead, + sessionKey: isLead + ? LEADS_CURSOR_SESSION_KEY + : POS_CURSOR_SESSION_KEY, + }; +}; diff --git a/frontend/plugins/sales_ui/src/modules/pos/pos/PosFilter.tsx b/frontend/plugins/sales_ui/src/modules/pos/pos/PosFilter.tsx new file mode 100644 index 0000000000..240b5b524e --- /dev/null +++ b/frontend/plugins/sales_ui/src/modules/pos/pos/PosFilter.tsx @@ -0,0 +1,169 @@ +import { + IconCalendar, + IconCalendarPlus, + IconCalendarTime, + IconCalendarUp, + IconLabel, + IconSearch, +} from '@tabler/icons-react'; +import { + Combobox, + Command, + Filter, + useFilterQueryState, + useMultiQueryState, +} from 'erxes-ui'; +import { SelectMember, TagsFilter, SelectBrand } from 'ui-modules'; + +import { PosHotKeyScope } from '../types/posHotkeyScope'; + +import { PosTotalCount } from '~/modules/pos/pos/PosTotalCount'; +import { useIsPosLeadSessionKey } from '~/modules/pos/pos-detail/hooks/UsePosLeadSessionKey'; +const PosFilterPopover = () => { + const [queries] = useMultiQueryState<{ + tags: string[]; + searchValue: string; + created: string; + updated: string; + lastSeen: string; + brand: string; + }>(['tags', 'searchValue', 'created', 'updated', 'lastSeen', 'brand']); + + const hasFilters = Object.values(queries || {}).some( + (value) => value !== null, + ); + + return ( + <> + + + + + + + + + + Search + + + + + Brand + + + + + + Created At + + + + Updated At + + + + Last Seen At + + + + Birthday + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export const PosFilter = () => { + const [searchValue] = useFilterQueryState('searchValue'); + const { sessionKey } = useIsPosLeadSessionKey(); + + return ( + + + + + + Search + + + {searchValue} + + + + + + + Created At + + + + + + + Updated At + + + + + + + Last Seen At + + + + + + + Birthday + + + + + + + + + + ); +}; diff --git a/frontend/plugins/sales_ui/src/modules/pos/pos/PosTotalCount.tsx b/frontend/plugins/sales_ui/src/modules/pos/pos/PosTotalCount.tsx new file mode 100644 index 0000000000..854a03ea01 --- /dev/null +++ b/frontend/plugins/sales_ui/src/modules/pos/pos/PosTotalCount.tsx @@ -0,0 +1,16 @@ +import { isUndefinedOrNull, Skeleton } from 'erxes-ui'; +import { useAtomValue } from 'jotai'; +import { posTotalCountAtom } from '~/modules/pos/states/PosCount'; + +export const PosTotalCount = () => { + const totalCount = useAtomValue(posTotalCountAtom); + return ( +
+ {isUndefinedOrNull(totalCount) ? ( + + ) : ( + `${totalCount} records found` + )} +
+ ); +}; diff --git a/frontend/plugins/sales_ui/src/modules/pos/pos/breadcumb/PosBreadCumb.tsx b/frontend/plugins/sales_ui/src/modules/pos/pos/breadcumb/PosBreadCumb.tsx new file mode 100644 index 0000000000..bef3742dd0 --- /dev/null +++ b/frontend/plugins/sales_ui/src/modules/pos/pos/breadcumb/PosBreadCumb.tsx @@ -0,0 +1,26 @@ +import { Breadcrumb, Button, IconComponent, Skeleton } from 'erxes-ui'; +import { Link, useParams } from 'react-router-dom'; +import { useGetCurrentUsersPos } from '@/pos/hooks/useGetCurrentUsersPos'; + +export const PosBreadCrumb = () => { + const { posId } = useParams(); + + const { pos, loading } = useGetCurrentUsersPos(); + + const posItem = pos?.find((pos) => pos._id === posId); + + if (loading) { + return ; + } + + return ( + + + + ); +}; diff --git a/frontend/plugins/sales_ui/src/modules/pos/states/PosCount.tsx b/frontend/plugins/sales_ui/src/modules/pos/states/PosCount.tsx new file mode 100644 index 0000000000..80afd30f3d --- /dev/null +++ b/frontend/plugins/sales_ui/src/modules/pos/states/PosCount.tsx @@ -0,0 +1,3 @@ +import { atom } from 'jotai'; + +export const posTotalCountAtom = atom(null); diff --git a/frontend/plugins/sales_ui/src/modules/pos/states/orderDetail.tsx b/frontend/plugins/sales_ui/src/modules/pos/states/orderDetail.tsx new file mode 100644 index 0000000000..ffcc0d747a --- /dev/null +++ b/frontend/plugins/sales_ui/src/modules/pos/states/orderDetail.tsx @@ -0,0 +1,3 @@ +import { atom } from 'jotai'; + +export const renderingOrderDetailAtom = atom(false); diff --git a/frontend/plugins/sales_ui/src/modules/pos/types/order.ts b/frontend/plugins/sales_ui/src/modules/pos/types/order.ts new file mode 100644 index 0000000000..0f945e7903 --- /dev/null +++ b/frontend/plugins/sales_ui/src/modules/pos/types/order.ts @@ -0,0 +1,22 @@ +export interface IUser { + _id: string; + details: { + avatar: string; + fullName: string; + __typename: string; + }; + __typename: string; +} + +export interface IOrder { + _id: string; + name: string; + icon: string; + isOnline: boolean; + onServer: boolean; + branchTitle: string; + departmentTitle: string; + createdAt: string; + createdBy: string; + user: IUser; +} diff --git a/frontend/plugins/sales_ui/src/modules/pos/types/path/PosPath.tsx b/frontend/plugins/sales_ui/src/modules/pos/types/path/PosPath.tsx new file mode 100644 index 0000000000..e8212c6b49 --- /dev/null +++ b/frontend/plugins/sales_ui/src/modules/pos/types/path/PosPath.tsx @@ -0,0 +1,9 @@ +export const PosPath = { + Index: '/contacts', + Customers: '/customers', + Leads: '/leads', + Companies: '/companies', + Vendors: '/vendors', + Clients: '/clients', +} as const; +export type PosPath = typeof PosPath[keyof typeof PosPath]; \ No newline at end of file diff --git a/frontend/plugins/sales_ui/src/modules/pos/types/pos.ts b/frontend/plugins/sales_ui/src/modules/pos/types/pos.ts index efba053ec4..333329af80 100644 --- a/frontend/plugins/sales_ui/src/modules/pos/types/pos.ts +++ b/frontend/plugins/sales_ui/src/modules/pos/types/pos.ts @@ -11,6 +11,7 @@ export interface IUser { export interface IPos { _id: string; name: string; + icon: string; isOnline: boolean; onServer: boolean; branchTitle: string; diff --git a/frontend/plugins/sales_ui/src/pages/OrdersPage.tsx b/frontend/plugins/sales_ui/src/pages/OrdersPage.tsx new file mode 100644 index 0000000000..f7f8a93b60 --- /dev/null +++ b/frontend/plugins/sales_ui/src/pages/OrdersPage.tsx @@ -0,0 +1,34 @@ +import { PageHeader } from 'ui-modules'; +import { Breadcrumb, Separator } from 'erxes-ui'; + +import { useParams } from 'react-router-dom'; +import { PosBreadCrumb } from '../modules/pos/pos/breadcumb/PosBreadCumb'; +import { OrderRecordTable } from '~/modules/orders/components/OrderRecordTable'; +import { PosFilter } from '../modules/pos/pos/PosFilter'; + +export const OrdersPage = () => { + const { posId } = useParams(); + + return ( + <> + + + + + {posId && ( + <> + + + + )} + + + + + + + + + + ); +}; diff --git a/frontend/plugins/sales_ui/src/pages/PosIndexPage.tsx b/frontend/plugins/sales_ui/src/pages/PosIndexPage.tsx index 641ed3b993..6b513ae53d 100644 --- a/frontend/plugins/sales_ui/src/pages/PosIndexPage.tsx +++ b/frontend/plugins/sales_ui/src/pages/PosIndexPage.tsx @@ -7,6 +7,8 @@ import { useAtom } from 'jotai'; import { PosCreate } from '@/pos/create-pos/components/index/pos-create'; import { PosEdit } from '@/pos/pos-detail/components/posDetail'; import { renderingPosCreateAtom } from '@/pos/create-pos/states/renderingPosCreateAtom'; +import { PosFilter } from '~/modules/pos/pos/PosFilter'; +import { OrderRecordTable } from '~/modules/orders/components/OrderRecordTable'; export const PosIndexPage = () => { const [, setSearchParams] = useSearchParams(); @@ -49,7 +51,10 @@ export const PosIndexPage = () => { - + + + + ); diff --git a/frontend/plugins/sales_ui/src/pages/SalesIndexPage.tsx b/frontend/plugins/sales_ui/src/pages/SalesIndexPage.tsx index b3f49759fe..b9620667c2 100644 --- a/frontend/plugins/sales_ui/src/pages/SalesIndexPage.tsx +++ b/frontend/plugins/sales_ui/src/pages/SalesIndexPage.tsx @@ -49,7 +49,6 @@ export const SalesIndexPage = () => { - diff --git a/package.json b/package.json index 92913cc821..f3a5bdde09 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "dev:apis": "dotenv -e .env -- node scripts/start-api-dev.js", "dev:uis": "dotenv -e .env -- node scripts/start-ui-dev.js", "create-plugin": "node scripts/create-plugin.js" + }, "engines": { "pnpm": ">=8", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d29622de0d..631b570b5b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -969,11 +969,107 @@ importers: specifier: workspace:^ version: link:../../erxes-api-shared - backend/plugins/tourism_api: + backend/plugins/tourism_api/dist: dependencies: + '@apollo/server': + specifier: 4.11.3 + version: 4.11.3(encoding@0.1.13)(graphql@16.10.0) + '@apollo/subgraph': + specifier: 2.10.0 + version: 2.10.0(graphql@16.10.0) + '@babel/preset-env': + specifier: 7.26.9 + version: 7.26.9(@babel/core@7.26.10) + '@elastic/elasticsearch': + specifier: 7.17.14 + version: 7.17.14 + '@preconstruct/cli': + specifier: 2.8.12 + version: 2.8.12 + '@prettier/sync': + specifier: 0.5.5 + version: 0.5.5(prettier@2.8.8) + '@sniptt/guards': + specifier: 0.2.0 + version: 0.2.0 + '@trpc/client': + specifier: 11.0.4 + version: 11.0.4(@trpc/server@11.0.4(typescript@5.8.3))(typescript@5.8.3) + '@trpc/server': + specifier: 11.0.4 + version: 11.0.4(typescript@5.8.3) + '@types/babel__preset-env': + specifier: 7.10.0 + version: 7.10.0 + '@types/graphql': + specifier: 14.5.0 + version: 14.5.0 + '@types/ioredis': + specifier: 5.0.0 + version: 5.0.0 + babel-plugin-module-resolver: + specifier: 5.0.2 + version: 5.0.2 + bullmq: + specifier: 5.40.4 + version: 5.40.4 + cookie-parser: + specifier: 1.4.7 + version: 1.4.7 + cors: + specifier: 2.8.5 + version: 2.8.5 + dayjs: + specifier: 1.11.13 + version: 1.11.13 + dotenv: + specifier: 16.4.7 + version: 16.4.7 erxes-api-shared: specifier: workspace:^ - version: link:../../erxes-api-shared + version: link:../../../erxes-api-shared + express: + specifier: 4.21.2 + version: 4.21.2 + express-rate-limit: + specifier: 6.11.2 + version: 6.11.2(express@4.21.2) + glob: + specifier: 11.0.1 + version: 11.0.1 + graphql: + specifier: 16.10.0 + version: 16.10.0 + graphql-redis-subscriptions: + specifier: 2.7.0 + version: 2.7.0(graphql-subscriptions@3.0.0(graphql@16.10.0)) + graphql-subscriptions: + specifier: 3.0.0 + version: 3.0.0(graphql@16.10.0) + graphql-tag: + specifier: 2.12.6 + version: 2.12.6(graphql@16.10.0) + ioredis: + specifier: 5.6.1 + version: 5.6.1 + moment: + specifier: 2.30.1 + version: 2.30.1 + mongoose: + specifier: 8.13.2 + version: 8.13.2 + nanoid: + specifier: 3.3.11 + version: 3.3.11 + node-fetch: + specifier: 2.7.0 + version: 2.7.0(encoding@0.1.13) + strip-ansi: + specifier: 6.0.1 + version: 6.0.1 + zod: + specifier: 3.24.2 + version: 3.24.2 backend/services/automations: dependencies: @@ -1058,8 +1154,11 @@ packages: graphql: 14.x || 15.x || 16.x '@apollo/server@4.11.3': - resolution: {integrity: sha512-mW8idE2q0/BN14mimfJU5DAnoPHZRrAWgwsVLBEdACds+mxapIYxIbI6AH4AsOpxfrpvHts3PCYDbopy1XPW1g==} - engines: {node: '>=14.16.0'} + resolution: + { + integrity: sha512-mW8idE2q0/BN14mimfJU5DAnoPHZRrAWgwsVLBEdACds+mxapIYxIbI6AH4AsOpxfrpvHts3PCYDbopy1XPW1g==, + } + engines: { node: '>=14.16.0' } peerDependencies: graphql: ^16.6.0 @@ -5373,108 +5472,171 @@ packages: peerDependencies: rollup: ^1.20.0||^2.0.0 - '@rollup/rollup-android-arm-eabi@4.50.2': - resolution: {integrity: sha512-uLN8NAiFVIRKX9ZQha8wy6UUs06UNSZ32xj6giK/rmMXAgKahwExvK6SsmgU5/brh4w/nSgj8e0k3c1HBQpa0A==} + '@rollup/rollup-android-arm-eabi@4.50.1': + resolution: + { + integrity: sha512-HJXwzoZN4eYTdD8bVV22DN8gsPCAj3V20NHKOs8ezfXanGpmVPR7kalUHd+Y31IJp9stdB87VKPFbsGY3H/2ag==, + } cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.50.2': - resolution: {integrity: sha512-oEouqQk2/zxxj22PNcGSskya+3kV0ZKH+nQxuCCOGJ4oTXBdNTbv+f/E3c74cNLeMO1S5wVWacSws10TTSB77g==} + '@rollup/rollup-android-arm64@4.50.1': + resolution: + { + integrity: sha512-PZlsJVcjHfcH53mOImyt3bc97Ep3FJDXRpk9sMdGX0qgLmY0EIWxCag6EigerGhLVuL8lDVYNnSo8qnTElO4xw==, + } cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.50.2': - resolution: {integrity: sha512-OZuTVTpj3CDSIxmPgGH8en/XtirV5nfljHZ3wrNwvgkT5DQLhIKAeuFSiwtbMto6oVexV0k1F1zqURPKf5rI1Q==} + '@rollup/rollup-darwin-arm64@4.50.1': + resolution: + { + integrity: sha512-xc6i2AuWh++oGi4ylOFPmzJOEeAa2lJeGUGb4MudOtgfyyjr4UPNK+eEWTPLvmPJIY/pgw6ssFIox23SyrkkJw==, + } cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.50.2': - resolution: {integrity: sha512-Wa/Wn8RFkIkr1vy1k1PB//VYhLnlnn5eaJkfTQKivirOvzu5uVd2It01ukeQstMursuz7S1bU+8WW+1UPXpa8A==} + '@rollup/rollup-darwin-x64@4.50.1': + resolution: + { + integrity: sha512-2ofU89lEpDYhdLAbRdeyz/kX3Y2lpYc6ShRnDjY35bZhd2ipuDMDi6ZTQ9NIag94K28nFMofdnKeHR7BT0CATw==, + } cpu: [x64] os: [darwin] - '@rollup/rollup-freebsd-arm64@4.50.2': - resolution: {integrity: sha512-QkzxvH3kYN9J1w7D1A+yIMdI1pPekD+pWx7G5rXgnIlQ1TVYVC6hLl7SOV9pi5q9uIDF9AuIGkuzcbF7+fAhow==} + '@rollup/rollup-freebsd-arm64@4.50.1': + resolution: + { + integrity: sha512-wOsE6H2u6PxsHY/BeFHA4VGQN3KUJFZp7QJBmDYI983fgxq5Th8FDkVuERb2l9vDMs1D5XhOrhBrnqcEY6l8ZA==, + } cpu: [arm64] os: [freebsd] - '@rollup/rollup-freebsd-x64@4.50.2': - resolution: {integrity: sha512-dkYXB0c2XAS3a3jmyDkX4Jk0m7gWLFzq1C3qUnJJ38AyxIF5G/dyS4N9B30nvFseCfgtCEdbYFhk0ChoCGxPog==} + '@rollup/rollup-freebsd-x64@4.50.1': + resolution: + { + integrity: sha512-A/xeqaHTlKbQggxCqispFAcNjycpUEHP52mwMQZUNqDUJFFYtPHCXS1VAG29uMlDzIVr+i00tSFWFLivMcoIBQ==, + } cpu: [x64] os: [freebsd] - '@rollup/rollup-linux-arm-gnueabihf@4.50.2': - resolution: {integrity: sha512-9VlPY/BN3AgbukfVHAB8zNFWB/lKEuvzRo1NKev0Po8sYFKx0i+AQlCYftgEjcL43F2h9Ui1ZSdVBc4En/sP2w==} + '@rollup/rollup-linux-arm-gnueabihf@4.50.1': + resolution: + { + integrity: sha512-54v4okehwl5TaSIkpp97rAHGp7t3ghinRd/vyC1iXqXMfjYUTm7TfYmCzXDoHUPTTf36L8pr0E7YsD3CfB3ZDg==, + } cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.50.2': - resolution: {integrity: sha512-+GdKWOvsifaYNlIVf07QYan1J5F141+vGm5/Y8b9uCZnG/nxoGqgCmR24mv0koIWWuqvFYnbURRqw1lv7IBINw==} + '@rollup/rollup-linux-arm-musleabihf@4.50.1': + resolution: + { + integrity: sha512-p/LaFyajPN/0PUHjv8TNyxLiA7RwmDoVY3flXHPSzqrGcIp/c2FjwPPP5++u87DGHtw+5kSH5bCJz0mvXngYxw==, + } cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.50.2': - resolution: {integrity: sha512-df0Eou14ojtUdLQdPFnymEQteENwSJAdLf5KCDrmZNsy1c3YaCNaJvYsEUHnrg+/DLBH612/R0xd3dD03uz2dg==} + '@rollup/rollup-linux-arm64-gnu@4.50.1': + resolution: + { + integrity: sha512-2AbMhFFkTo6Ptna1zO7kAXXDLi7H9fGTbVaIq2AAYO7yzcAsuTNWPHhb2aTA6GPiP+JXh85Y8CiS54iZoj4opw==, + } cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.50.2': - resolution: {integrity: sha512-iPeouV0UIDtz8j1YFR4OJ/zf7evjauqv7jQ/EFs0ClIyL+by++hiaDAfFipjOgyz6y6xbDvJuiU4HwpVMpRFDQ==} + '@rollup/rollup-linux-arm64-musl@4.50.1': + resolution: + { + integrity: sha512-Cgef+5aZwuvesQNw9eX7g19FfKX5/pQRIyhoXLCiBOrWopjo7ycfB292TX9MDcDijiuIJlx1IzJz3IoCPfqs9w==, + } cpu: [arm64] os: [linux] - '@rollup/rollup-linux-loong64-gnu@4.50.2': - resolution: {integrity: sha512-OL6KaNvBopLlj5fTa5D5bau4W82f+1TyTZRr2BdnfsrnQnmdxh4okMxR2DcDkJuh4KeoQZVuvHvzuD/lyLn2Kw==} + '@rollup/rollup-linux-loongarch64-gnu@4.50.1': + resolution: + { + integrity: sha512-RPhTwWMzpYYrHrJAS7CmpdtHNKtt2Ueo+BlLBjfZEhYBhK00OsEqM08/7f+eohiF6poe0YRDDd8nAvwtE/Y62Q==, + } cpu: [loong64] os: [linux] - '@rollup/rollup-linux-ppc64-gnu@4.50.2': - resolution: {integrity: sha512-I21VJl1w6z/K5OTRl6aS9DDsqezEZ/yKpbqlvfHbW0CEF5IL8ATBMuUx6/mp683rKTK8thjs/0BaNrZLXetLag==} + '@rollup/rollup-linux-ppc64-gnu@4.50.1': + resolution: + { + integrity: sha512-eSGMVQw9iekut62O7eBdbiccRguuDgiPMsw++BVUg+1K7WjZXHOg/YOT9SWMzPZA+w98G+Fa1VqJgHZOHHnY0Q==, + } cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.50.2': - resolution: {integrity: sha512-Hq6aQJT/qFFHrYMjS20nV+9SKrXL2lvFBENZoKfoTH2kKDOJqff5OSJr4x72ZaG/uUn+XmBnGhfr4lwMRrmqCQ==} + '@rollup/rollup-linux-riscv64-gnu@4.50.1': + resolution: + { + integrity: sha512-S208ojx8a4ciIPrLgazF6AgdcNJzQE4+S9rsmOmDJkusvctii+ZvEuIC4v/xFqzbuP8yDjn73oBlNDgF6YGSXQ==, + } cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-riscv64-musl@4.50.2': - resolution: {integrity: sha512-82rBSEXRv5qtKyr0xZ/YMF531oj2AIpLZkeNYxmKNN6I2sVE9PGegN99tYDLK2fYHJITL1P2Lgb4ZXnv0PjQvw==} + '@rollup/rollup-linux-riscv64-musl@4.50.1': + resolution: + { + integrity: sha512-3Ag8Ls1ggqkGUvSZWYcdgFwriy2lWo+0QlYgEFra/5JGtAd6C5Hw59oojx1DeqcA2Wds2ayRgvJ4qxVTzCHgzg==, + } cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.50.2': - resolution: {integrity: sha512-4Q3S3Hy7pC6uaRo9gtXUTJ+EKo9AKs3BXKc2jYypEcMQ49gDPFU2P1ariX9SEtBzE5egIX6fSUmbmGazwBVF9w==} + '@rollup/rollup-linux-s390x-gnu@4.50.1': + resolution: + { + integrity: sha512-t9YrKfaxCYe7l7ldFERE1BRg/4TATxIg+YieHQ966jwvo7ddHJxPj9cNFWLAzhkVsbBvNA4qTbPVNsZKBO4NSg==, + } cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.50.2': - resolution: {integrity: sha512-9Jie/At6qk70dNIcopcL4p+1UirusEtznpNtcq/u/C5cC4HBX7qSGsYIcG6bdxj15EYWhHiu02YvmdPzylIZlA==} + '@rollup/rollup-linux-x64-gnu@4.50.1': + resolution: + { + integrity: sha512-MCgtFB2+SVNuQmmjHf+wfI4CMxy3Tk8XjA5Z//A0AKD7QXUYFMQcns91K6dEHBvZPCnhJSyDWLApk40Iq/H3tA==, + } cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.50.2': - resolution: {integrity: sha512-HPNJwxPL3EmhzeAnsWQCM3DcoqOz3/IC6de9rWfGR8ZCuEHETi9km66bH/wG3YH0V3nyzyFEGUZeL5PKyy4xvw==} + '@rollup/rollup-linux-x64-musl@4.50.1': + resolution: + { + integrity: sha512-nEvqG+0jeRmqaUMuwzlfMKwcIVffy/9KGbAGyoa26iu6eSngAYQ512bMXuqqPrlTyfqdlB9FVINs93j534UJrg==, + } cpu: [x64] os: [linux] - '@rollup/rollup-openharmony-arm64@4.50.2': - resolution: {integrity: sha512-nMKvq6FRHSzYfKLHZ+cChowlEkR2lj/V0jYj9JnGUVPL2/mIeFGmVM2mLaFeNa5Jev7W7TovXqXIG2d39y1KYA==} + '@rollup/rollup-openharmony-arm64@4.50.1': + resolution: + { + integrity: sha512-RDsLm+phmT3MJd9SNxA9MNuEAO/J2fhW8GXk62G/B4G7sLVumNFbRwDL6v5NrESb48k+QMqdGbHgEtfU0LCpbA==, + } cpu: [arm64] os: [openharmony] - '@rollup/rollup-win32-arm64-msvc@4.50.2': - resolution: {integrity: sha512-eFUvvnTYEKeTyHEijQKz81bLrUQOXKZqECeiWH6tb8eXXbZk+CXSG2aFrig2BQ/pjiVRj36zysjgILkqarS2YA==} + '@rollup/rollup-win32-arm64-msvc@4.50.1': + resolution: + { + integrity: sha512-hpZB/TImk2FlAFAIsoElM3tLzq57uxnGYwplg6WDyAxbYczSi8O2eQ+H2Lx74504rwKtZ3N2g4bCUkiamzS6TQ==, + } cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.50.2': - resolution: {integrity: sha512-cBaWmXqyfRhH8zmUxK3d3sAhEWLrtMjWBRwdMMHJIXSjvjLKvv49adxiEz+FJ8AP90apSDDBx2Tyd/WylV6ikA==} + '@rollup/rollup-win32-ia32-msvc@4.50.1': + resolution: + { + integrity: sha512-SXjv8JlbzKM0fTJidX4eVsH+Wmnp0/WcD8gJxIZyR6Gay5Qcsmdbi9zVtnbkGPG8v2vMR1AD06lGWy5FLMcG7A==, + } cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.50.2': - resolution: {integrity: sha512-APwKy6YUhvZaEoHyM+9xqmTpviEI+9eL7LoCH+aLcvWYHJ663qG5zx7WzWZY+a9qkg5JtzcMyJ9z0WtQBMDmgA==} + '@rollup/rollup-win32-x64-msvc@4.50.1': + resolution: + { + integrity: sha512-StxAO/8ts62KZVRAm4JZYq9+NqNsV7RvimNK+YM7ry//zebEH6meuugqW/P5OFUCjyQgui+9fUxT6d5NShvMvA==, + } cpu: [x64] os: [win32] @@ -6634,8 +6796,11 @@ packages: '@types/react@18.3.1': resolution: {integrity: sha512-V0kuGBX3+prX+DQ/7r2qsv1NsdfnCLnTgnRJ1pYnxykBhGMz+qj+box5lq7XsO5mtZsBqpjwwTu/7wszPfMBcw==} - '@types/react@19.1.13': - resolution: {integrity: sha512-hHkbU/eoO3EG5/MZkuFSKmYqPbSVk5byPFa3e7y/8TybHiLMACgI8seVYlicwk7H5K/rI2px9xrQp/C+AUDTiQ==} + '@types/react@19.1.12': + resolution: + { + integrity: sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w==, + } '@types/reactcss@1.2.13': resolution: {integrity: sha512-gi3S+aUi6kpkF5vdhUsnkwbiSEIU/BEJyD7kBy2SudWBUuKmJk8AQKE0OVcQQeEy40Azh0lV6uynxlikYIJuwg==} @@ -6734,9 +6899,12 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/eslint-plugin@8.44.0': - resolution: {integrity: sha512-EGDAOGX+uwwekcS0iyxVDmRV9HX6FLSM5kzrAToLTsr9OWCIKG/y3lQheCq18yZ5Xh78rRKJiEpP0ZaCs4ryOQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/eslint-plugin@8.43.0': + resolution: + { + integrity: sha512-8tg+gt7ENL7KewsKMKDHXR1vm8tt9eMxjJBYINf6swonlWgkYn5NwyIgXpbbDxTNU5DgpDFfj95prcTq2clIQQ==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: '@typescript-eslint/parser': ^8.44.0 eslint: ^8.57.0 || ^9.0.0 @@ -6749,16 +6917,22 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/parser@8.44.0': - resolution: {integrity: sha512-VGMpFQGUQWYT9LfnPcX8ouFojyrZ/2w3K5BucvxL/spdNehccKhB4jUyB1yBCXpr2XFm0jkECxgrpXBW2ipoAw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/parser@8.43.0': + resolution: + { + integrity: sha512-B7RIQiTsCBBmY+yW4+ILd6mF5h1FUwJsVvpqkrgpszYifetQ2Ke+Z4u6aZh0CblkUGIdR59iYVyXqqZGkZ3aBw==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/project-service@8.44.0': - resolution: {integrity: sha512-ZeaGNraRsq10GuEohKTo4295Z/SuGcSq2LzfGlqiuEvfArzo/VRrT0ZaJsVPuKZ55lVbNk8U6FcL+ZMH8CoyVA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/project-service@8.43.0': + resolution: + { + integrity: sha512-htB/+D/BIGoNTQYffZw4uM4NzzuolCoaA/BusuSIcC8YjmBYQioew5VUZAYdAETPjeed0hqCaW7EHg+Robq8uw==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: typescript: '>=4.8.4 <6.0.0' @@ -6766,13 +6940,19 @@ packages: resolution: {integrity: sha512-2nggXGX5F3YrsGN08pw4XpMLO1Rgtnn4AzTegC2MDesv6q3QaTU5yU7IbS1tf1IwCR0Hv/1EFygLn9ms6LIpDA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/scope-manager@8.44.0': - resolution: {integrity: sha512-87Jv3E+al8wpD+rIdVJm/ItDBe/Im09zXIjFoipOjr5gHUhJmTzfFLuTJ/nPTMc2Srsroy4IBXwcTCHyRR7KzA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/scope-manager@8.43.0': + resolution: + { + integrity: sha512-daSWlQ87ZhsjrbMLvpuuMAt3y4ba57AuvadcR7f3nl8eS3BjRc8L9VLxFLk92RL5xdXOg6IQ+qKjjqNEimGuAg==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } - '@typescript-eslint/tsconfig-utils@8.44.0': - resolution: {integrity: sha512-x5Y0+AuEPqAInc6yd0n5DAcvtoQ/vyaGwuX5HE9n6qAefk1GaedqrLQF8kQGylLUb9pnZyLf+iEiL9fr8APDtQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/tsconfig-utils@8.43.0': + resolution: + { + integrity: sha512-ALC2prjZcj2YqqL5X/bwWQmHA2em6/94GcbB/KKu5SX3EBDOsqztmmX1kMkvAJHzxk7TazKzJfFiEIagNV3qEA==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: typescript: '>=4.8.4 <6.0.0' @@ -6783,9 +6963,12 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/type-utils@8.44.0': - resolution: {integrity: sha512-9cwsoSxJ8Sak67Be/hD2RNt/fsqmWnNE1iHohG8lxqLSNY8xNfyY7wloo5zpW3Nu9hxVgURevqfcH6vvKCt6yg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/type-utils@8.43.0': + resolution: + { + integrity: sha512-qaH1uLBpBuBBuRf8c1mLJ6swOfzCXryhKND04Igr4pckzSEW9JX5Aw9AgW00kwfjWJF0kk0ps9ExKTfvXfw4Qg==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' @@ -6794,9 +6977,12 @@ packages: resolution: {integrity: sha512-VT7T1PuJF1hpYC3AGm2rCgJBjHL3nc+A/bhOp9sGMKfi5v0WufsX/sHCFBfNTx2F+zA6qBc/PD0/kLRLjdt8mQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/types@8.44.0': - resolution: {integrity: sha512-ZSl2efn44VsYM0MfDQe68RKzBz75NPgLQXuGypmym6QVOWL5kegTZuZ02xRAT9T+onqvM6T8CdQk0OwYMB6ZvA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.43.0': + resolution: + { + integrity: sha512-vQ2FZaxJpydjSZJKiSW/LJsabFFvV7KgLC5DiLhkBcykhQj8iK9BOaDmQt74nnKdLvceM5xmhaTF+pLekrxEkw==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } '@typescript-eslint/typescript-estree@8.29.1': resolution: {integrity: sha512-l1enRoSaUkQxOQnbi0KPUtqeZkSiFlqrx9/3ns2rEDhGKfTa+88RmXqedC1zmVTOWrLc2e6DEJrTA51C9iLH5g==} @@ -6804,9 +6990,12 @@ packages: peerDependencies: typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/typescript-estree@8.44.0': - resolution: {integrity: sha512-lqNj6SgnGcQZwL4/SBJ3xdPEfcBuhCG8zdcwCPgYcmiPLgokiNDKlbPzCwEwu7m279J/lBYWtDYL+87OEfn8Jw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@8.43.0': + resolution: + { + integrity: sha512-7Vv6zlAhPb+cvEpP06WXXy/ZByph9iL6BQRBDj4kmBsW98AqEeQHlj/13X+sZOrKSo9/rNKH4Ul4f6EICREFdw==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: typescript: '>=4.8.4 <6.0.0' @@ -6817,9 +7006,12 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/utils@8.44.0': - resolution: {integrity: sha512-nktOlVcg3ALo0mYlV+L7sWUD58KG4CMj1rb2HUVOO4aL3K/6wcD+NERqd0rrA5Vg06b42YhF6cFxeixsp9Riqg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/utils@8.43.0': + resolution: + { + integrity: sha512-S1/tEmkUeeswxd0GGcnwuVQPFWo8NzZTOMxCvw8BX7OMxnNae+i8Tm7REQen/SwUIPoPqfKn7EaZ+YLpiB3k9g==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' @@ -6828,9 +7020,12 @@ packages: resolution: {integrity: sha512-RGLh5CRaUEf02viP5c1Vh1cMGffQscyHe7HPAzGpfmfflFg1wUz2rYxd+OZqwpeypYvZ8UxSxuIpF++fmOzEcg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/visitor-keys@8.44.0': - resolution: {integrity: sha512-zaz9u8EJ4GBmnehlrpoKvj/E3dNbuQ7q0ucyZImm3cLqJ8INTc970B1qEqDX/Rzq65r3TvVTN7kHWPBoyW7DWw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.43.0': + resolution: + { + integrity: sha512-T+S1KqRD4sg/bHfLwrpF/K3gQLBM1n7Rp7OjjikjTEssI2YJzQpi5WXoynOaQ93ERIuq3O8RBTOUYDKszUCEHw==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} @@ -13275,9 +13470,12 @@ packages: engines: {node: '>=10.0.0'} hasBin: true - rollup@4.50.2: - resolution: {integrity: sha512-BgLRGy7tNS9H66aIMASq1qSYbAAJV6Z6WR4QYTvj5FgF15rZ/ympT1uixHXwzbZUBDbkvqUI1KR0fH1FhMaQ9w==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} + rollup@4.50.1: + resolution: + { + integrity: sha512-78E9voJHwnXQMiQdiqswVLZwJIzdBKJ1GdI5Zx6XwoFKUIk09/sSrr+05QFzvYb8q6Y9pPV45zzDuYa3907TZA==, + } + engines: { node: '>=18.0.0', npm: '>=8.0.0' } hasBin: true rope-sequence@1.3.4: @@ -14306,9 +14504,12 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' - typescript-eslint@8.44.0: - resolution: {integrity: sha512-ib7mCkYuIzYonCq9XWF5XNw+fkj2zg629PSa9KNIQ47RXFF763S5BIX4wqz1+FLPogTZoiw8KmCiRPRa8bL3qw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + typescript-eslint@8.43.0: + resolution: + { + integrity: sha512-FyRGJKUGvcFekRRcBKFBlAhnp4Ng8rhe8tuvvkR9OiU0gfd4vyvTRQHEckO6VDlH57jbeUQem2IpqPq9kLJH+w==, + } + engines: { node: ^18.18.0 || ^20.9.0 || >=21.1.0 } peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' @@ -15145,7 +15346,30 @@ snapshots: transitivePeerDependencies: - '@types/react' - '@apollo/client@3.13.6(@types/react@19.1.13)(graphql-ws@5.16.2(graphql@16.10.0))(graphql@16.10.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + '@apollo/client@3.13.6(@types/react@19.1.12)(graphql-ws@5.16.2(graphql@16.10.0))(graphql@16.10.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.10.0) + '@wry/caches': 1.0.1 + '@wry/equality': 0.5.7 + '@wry/trie': 0.5.0 + graphql: 16.10.0 + graphql-tag: 2.12.6(graphql@16.10.0) + hoist-non-react-statics: 3.3.2 + optimism: 0.18.1 + prop-types: 15.8.1 + rehackt: 0.1.0(@types/react@19.1.12)(react@18.3.1) + symbol-observable: 4.0.0 + ts-invariant: 0.10.3 + tslib: 2.8.1 + zen-observable-ts: 1.2.5 + optionalDependencies: + graphql-ws: 5.16.2(graphql@16.10.0) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + transitivePeerDependencies: + - '@types/react' + + '@apollo/client@3.13.6(@types/react@19.1.12)(graphql-ws@5.16.2(graphql@16.10.0))(graphql@16.10.0)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': dependencies: '@graphql-typed-document-node/core': 3.2.0(graphql@16.10.0) '@wry/caches': 1.0.1 @@ -15156,7 +15380,7 @@ snapshots: hoist-non-react-statics: 3.3.2 optimism: 0.18.1 prop-types: 15.8.1 - rehackt: 0.1.0(@types/react@19.1.13)(react@19.1.1) + rehackt: 0.1.0(@types/react@19.1.12)(react@19.1.1) symbol-observable: 4.0.0 ts-invariant: 0.10.3 tslib: 2.8.1 @@ -30823,9 +31047,14 @@ snapshots: '@types/react': 18.3.1 react: 18.3.1 - rehackt@0.1.0(@types/react@19.1.13)(react@19.1.1): + rehackt@0.1.0(@types/react@19.1.12)(react@18.3.1): optionalDependencies: - '@types/react': 19.1.13 + '@types/react': 19.1.12 + react: 18.3.1 + + rehackt@0.1.0(@types/react@19.1.12)(react@19.1.1): + optionalDependencies: + '@types/react': 19.1.12 react: 19.1.1 rehype-format@5.0.1: