diff --git a/src/frontend/src/components/barcodes/BarcodeScanDialog.tsx b/src/frontend/src/components/barcodes/BarcodeScanDialog.tsx
index 1bec3d0298..6aaf0ad2ea 100644
--- a/src/frontend/src/components/barcodes/BarcodeScanDialog.tsx
+++ b/src/frontend/src/components/barcodes/BarcodeScanDialog.tsx
@@ -1,7 +1,7 @@
import { t } from '@lingui/macro';
import { Box, Divider, Modal } from '@mantine/core';
import { useCallback, useState } from 'react';
-import { useNavigate } from 'react-router-dom';
+import { type NavigateFunction, useNavigate } from 'react-router-dom';
import { api } from '../../App';
import { ApiEndpoints } from '../../enums/ApiEndpoints';
import type { ModelType } from '../../enums/ModelType';
@@ -17,17 +17,34 @@ export default function BarcodeScanDialog({
title,
opened,
onClose
-}: {
+}: Readonly<{
title?: string;
opened: boolean;
onClose: () => void;
-}) {
+}>) {
const navigate = useNavigate();
- const user = useUserState();
+ return (
+ {title ?? t`Scan Barcode`}}
+ >
+
+
+
+
+
+ );
+}
+export function ScanInputHandler({
+ onClose,
+ navigate
+}: Readonly<{ onClose: () => void; navigate: NavigateFunction }>) {
const [error, setError] = useState('');
-
const [processing, setProcessing] = useState(false);
+ const user = useUserState();
const onScan = useCallback((barcode: string) => {
if (!barcode || barcode.length === 0) {
@@ -80,19 +97,5 @@ export default function BarcodeScanDialog({
});
}, []);
- return (
- <>
- {title ?? t`Scan Barcode`}}
- >
-
-
-
-
-
- >
- );
+ return ;
}
diff --git a/src/frontend/src/components/modals/QrModal.tsx b/src/frontend/src/components/modals/QrModal.tsx
new file mode 100644
index 0000000000..14d5ef2ee7
--- /dev/null
+++ b/src/frontend/src/components/modals/QrModal.tsx
@@ -0,0 +1,21 @@
+import {} from '@mantine/core';
+import type { ContextModalProps } from '@mantine/modals';
+import type { NavigateFunction } from 'react-router-dom';
+import { ScanInputHandler } from '../barcodes/BarcodeScanDialog';
+
+export function QrModal({
+ context,
+ id,
+ innerProps
+}: Readonly<
+ ContextModalProps<{ modalBody: string; navigate: NavigateFunction }>
+>) {
+ function close() {
+ context.closeModal(id);
+ }
+ function navigate() {
+ context.closeModal(id);
+ }
+
+ return ;
+}
diff --git a/src/frontend/src/contexts/ThemeContext.tsx b/src/frontend/src/contexts/ThemeContext.tsx
index 61c326a287..023ca0eb6a 100644
--- a/src/frontend/src/contexts/ThemeContext.tsx
+++ b/src/frontend/src/contexts/ThemeContext.tsx
@@ -6,6 +6,7 @@ import { ContextMenuProvider } from 'mantine-contextmenu';
import { AboutInvenTreeModal } from '../components/modals/AboutInvenTreeModal';
import { LicenseModal } from '../components/modals/LicenseModal';
+import { QrModal } from '../components/modals/QrModal';
import { ServerInfoModal } from '../components/modals/ServerInfoModal';
import { useLocalState } from '../states/LocalState';
import { LanguageContext } from './LanguageContext';
@@ -47,7 +48,8 @@ export function ThemeContext({
modals={{
info: ServerInfoModal,
about: AboutInvenTreeModal,
- license: LicenseModal
+ license: LicenseModal,
+ qr: QrModal
}}
>
diff --git a/src/frontend/src/defaults/actions.tsx b/src/frontend/src/defaults/actions.tsx
index b15d469222..0bda2be938 100644
--- a/src/frontend/src/defaults/actions.tsx
+++ b/src/frontend/src/defaults/actions.tsx
@@ -1,12 +1,20 @@
import { t } from '@lingui/macro';
import type { SpotlightActionData } from '@mantine/spotlight';
-import { IconLink, IconPointer } from '@tabler/icons-react';
+import { IconBarcode, IconLink, IconPointer } from '@tabler/icons-react';
import type { NavigateFunction } from 'react-router-dom';
+import { openContextModal } from '@mantine/modals';
import { useLocalState } from '../states/LocalState';
import { useUserState } from '../states/UserState';
import { aboutInvenTree, docLinks, licenseInfo, serverInfo } from './links';
+export function openQrModal(navigate: NavigateFunction) {
+ return openContextModal({
+ modal: 'qr',
+ innerProps: { navigate: navigate }
+ });
+}
+
export function getActions(navigate: NavigateFunction) {
const setNavigationOpen = useLocalState((state) => state.setNavigationOpen);
const { user } = useUserState();
@@ -55,6 +63,13 @@ export function getActions(navigate: NavigateFunction) {
description: t`Open the main navigation menu`,
onClick: () => setNavigationOpen(true),
leftSection:
+ },
+ {
+ id: 'scan',
+ label: t`Scan`,
+ description: t`Scan a barcode or QR code`,
+ onClick: () => openQrModal(navigate),
+ leftSection:
}
];