Skip to content

Commit

Permalink
wip: qr scan page
Browse files Browse the repository at this point in the history
  • Loading branch information
MuhammedKpln committed Feb 28, 2024
1 parent 998e72f commit c1f7279
Show file tree
Hide file tree
Showing 10 changed files with 159 additions and 76 deletions.
2 changes: 1 addition & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export default function App() {
useEffect(() => {
const listener = listenToAuthClient();

if (!isNative) {
if (!isNative.current) {
showLoading("Värmer upp...");
}

Expand Down
3 changes: 1 addition & 2 deletions src/components/App/AppInfoCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ export default function AppInfoCard(props: IProps) {
case InfoCardStatus.Error:
return "danger";
case InfoCardStatus.Information:
return "warning";

return "secondary";
default:
return "warning";
}
Expand Down
36 changes: 34 additions & 2 deletions src/hooks/useBarcodeScanner.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
Barcode,
BarcodeFormat,
BarcodeScannedEvent,
BarcodeScanner,
Expand All @@ -7,15 +8,17 @@ import {
import { Capacitor } from "@capacitor/core";
import { useIonAlert } from "@ionic/react";
import { useCallback, useRef } from "react";
import { ToastStatus, useAppToast } from "./useAppToast";

interface IProps {
onBarcodeScanned: (e: BarcodeScannedEvent) => void;
onBarcodeScanned?: (e: BarcodeScannedEvent) => void;
onBarcodeError: () => void;
}

export function useBarcodeScanner(props: IProps) {
const [showAlert] = useIonAlert();
const googleModulesInstalled = useRef<boolean>(false);
const { showToast } = useAppToast();

const initialize = useCallback(async () => {
const supported = await isSupported();
Expand Down Expand Up @@ -61,8 +64,31 @@ export function useBarcodeScanner(props: IProps) {
return supported;
}, []);

const scanSingleBarcode = useCallback((): Promise<Barcode> => {
return new Promise(async (resolve) => {
document.querySelector("body")?.classList.add("barcode-scanner-active");

const listener = await BarcodeScanner.addListener(
"barcodeScanned",
async (result) => {
await listener.remove();
document
.querySelector("body")
?.classList.remove("barcode-scanner-active");
await BarcodeScanner.stopScan();
resolve(result.barcode);
}
);

await BarcodeScanner.startScan();
});
}, []);

const initializeListeners = useCallback(() => {
BarcodeScanner.addListener("barcodeScanned", props.onBarcodeScanned);
if (props.onBarcodeScanned) {
BarcodeScanner.addListener("barcodeScanned", props.onBarcodeScanned);
}

BarcodeScanner.addListener("scanError", props.onBarcodeError);

BarcodeScanner.addListener(
Expand Down Expand Up @@ -116,13 +142,19 @@ export function useBarcodeScanner(props: IProps) {
await BarcodeScanner.isGoogleBarcodeScannerModuleAvailable();

if (!hasModule) {
showToast({
message: "Installing required modules..",
status: ToastStatus.Info,
});
await BarcodeScanner.installGoogleBarcodeScannerModule();
googleModulesInstalled.current = true;
}
}, []);

return {
initialize,
startScan,
stopScan,
scanSingleBarcode,
};
}
11 changes: 5 additions & 6 deletions src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { SplashScreen } from "@capacitor/splash-screen";
import { defineCustomElements } from "@ionic/pwa-elements/loader";
import React from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
import Providers from "./Providers";
Expand All @@ -12,10 +11,10 @@ SplashScreen.show().then(() => {
defineCustomElements(window);

root.render(
<React.StrictMode>
<Providers>
<App />
</Providers>
</React.StrictMode>
// <React.StrictMode>
<Providers>
<App />
</Providers>
// </React.StrictMode>
);
});
3 changes: 3 additions & 0 deletions src/modules/newtag/newtag.module.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function NewTagModule() {
return <>selam</>;
}
103 changes: 65 additions & 38 deletions src/modules/scan/Scan.module.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,72 @@
import AppInfoCard, { InfoCardStatus } from "@/components/App/AppInfoCard";
import { useBarcodeScanner } from "@/hooks/useBarcodeScanner";
import {
BarcodeScannedEvent,
BarcodeScanner,
} from "@capacitor-mlkit/barcode-scanning";
import {
IonButton,
IonButtons,
IonContent,
IonPage,
useIonAlert,
useIonRouter,
} from "@ionic/react";
import { useCallback, useLayoutEffect } from "react";
import { QueryKeys } from "@/models/query_keys.model";
import { Routes } from "@/routes/routes";
import { tagService } from "@/services/tag.service";
import { Barcode, BarcodeScanner } from "@capacitor-mlkit/barcode-scanning";
import { IonButton, useIonAlert } from "@ionic/react";
import { useQueryClient } from "@tanstack/react-query";
import { useCallback, useEffect } from "react";

interface IProps {
onCancel: () => void;
onCancel: (route: string) => void;
}
export default function ScanModule(props: IProps) {
const [showAlert] = useIonAlert();
const router = useIonRouter();
const queryClient = useQueryClient();

const onBarcodeScanned = useCallback(async (e: BarcodeScannedEvent) => {
showAlert(e.barcode.displayValue);
const onBarcodeScanned = useCallback(async (e: Barcode) => {
await stopScan();
const url = e.displayValue;
const tagSplitted = url.split("tag/");
const tag = tagSplitted[1];

if (tag) {
const response = await queryClient.fetchQuery({
queryKey: [QueryKeys.Tag, tag],
queryFn: () => tagService.fetchTag(tag),
});

if (response && response.isAvailable) {
showAlert({
message: "Registrera ditt nya etikett.",
subHeader: "Grattis!",
buttons: [
{
text: "Registrera",
handler() {
props.onCancel(Routes.NewTag.replace(":tagUid", response.id));
},
},
{
text: "Gå tillbaka",
role: "cancel",
handler() {
props.onCancel(Routes.AppRoot);
},
},
],
});
} else {
console.log("yok");
}
}
}, []);

const onBarcodeError = useCallback(() => {}, []);

const { initialize, startScan, stopScan } = useBarcodeScanner({
onBarcodeScanned,
const { initialize, stopScan, scanSingleBarcode } = useBarcodeScanner({
onBarcodeError,
});

const stopScanAndNavigate = useCallback(async () => {
await stopScan();
props.onCancel();
props.onCancel(Routes.AppRoot);
}, []);

useLayoutEffect(() => {
initialize().then(async (s) => {
startScan();
useEffect(() => {
initialize().then(async () => {
scanSingleBarcode().then((value) => onBarcodeScanned(value));
});

return () => {
Expand All @@ -50,21 +77,21 @@ export default function ScanModule(props: IProps) {
}, []);

return (
<IonPage>
<IonContent className="h-full barcode-scanner-modal overflow-hidden">
<IonButtons style={{ paddingTop: "var(--ion-safe-area-top)" }}>
<IonButton fill="clear" slot="start" onClick={stopScanAndNavigate}>
Cancel
</IonButton>
</IonButtons>
<div className="h-screen barcode-scanner-modal overflow-hidden">
<IonButton fill="clear" color="light" onClick={stopScanAndNavigate}>
Cancel
</IonButton>

<div className="flex items-center justify-center h-full">
<div
id="qrView"
className="border border-white block border-solid w-56 h-56"
></div>
</div>
</IonContent>
</IonPage>
<div className="flex flex-col gap-5 items-center justify-around h-full ">
<div
id="qrView"
className="border-4 border-white block border-solid w-56 h-56 rounded-xl"
></div>
<AppInfoCard
message="Scanna ett QR-kod"
status={InfoCardStatus.Information}
/>
</div>
</div>
);
}
17 changes: 17 additions & 0 deletions src/pages/NewTag/NewTag.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import AppHeader from "@/components/App/AppHeader";
import NewTagModule from "@/modules/newtag/newtag.module";
import { IonContent, IonPage, IonTitle } from "@ionic/react";

export default function NewTagPage() {
return (
<IonPage>
<AppHeader withBackButton>
<IonTitle>Nytt ettikett</IonTitle>
</AppHeader>

<IonContent>
<NewTagModule />
</IonContent>
</IonPage>
);
}
55 changes: 28 additions & 27 deletions src/pages/Scan.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,41 @@
import { useIsNative } from "@/hooks/app/useIsNative";
import AppHeader from "@/components/App/AppHeader";
import ScanModule from "@/modules/scan/Scan.module";
import { Routes } from "@/routes/routes";
import {
IonButton,
IonContent,
IonPage,
useIonModal,
IonTitle,
useIonRouter,
useIonViewDidEnter,
useIonViewWillLeave,
} from "@ionic/react";
import { useCallback } from "react";

export default function ScanPage() {
const router = useIonRouter();
const { isNative } = useIsNative(true);
const [showModal, hideModal] = useIonModal(ScanModule, {
onCancel: () => hideModal(undefined, "cancel"),
});
// useEffect(() => {
// if (isNative.current) {
// showModal();
// }

const onExit = useCallback(() => {
if (router.canGoBack()) {
router.goBack();
} else {
router.push("/app");
}
}, []);
// return () => {
// hideModal(undefined, "cancel");
// };
// }, [isNative]);

useIonViewWillLeave(() => {
hideModal(undefined, "cancel");
});
function selam() {
router.push(Routes.Settings);
}

useIonViewDidEnter(() => {
if (isNative.current) {
showModal({
onWillDismiss: onExit,
});
}
});
return (
<IonPage>
<AppHeader>
<IonTitle>selam</IonTitle>
</AppHeader>

return <IonPage></IonPage>;
<IonContent>
<IonButton id="ss">selam</IonButton>

<ScanModule onCancel={selam} />
</IonContent>
</IonPage>
);
}
2 changes: 2 additions & 0 deletions src/pages/Tags/EditTag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ export default function EditTagPage(props: EditTagPageProps) {
return <AppLoading />;
}

console.log(tag);

return (
<IonPage>
<AppHeader withBackButton>
Expand Down
3 changes: 3 additions & 0 deletions src/routes/routes.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import AppOrLogin from "@/components/AppOrLogin";
import ChatPage from "@/pages/Chats/Chat";
import EditNotePage from "@/pages/EditNote/EditNote";
import NewTagPage from "@/pages/NewTag/NewTag";
import NoteDetailsPage from "@/pages/NoteDetails/NoteDetails";
import SettingsPage from "@/pages/Settings/Settings";
import TagPage from "@/pages/Tag/Tag";
Expand Down Expand Up @@ -30,6 +31,7 @@ export enum Routes {
Tag = "/tag/:tagUid",
EditNote = "/edit-note/:noteUid",
Verification = "/auth/verification",
NewTag = "/new-tag/:tagUid",
}

export default function AppRoutes() {
Expand All @@ -50,6 +52,7 @@ export default function AppRoutes() {
<PublicRoute path={Routes.Login} component={LoginPage} exact />
<PublicRoute path={Routes.Register} component={RegisterPage} exact />
<Route path="/" exact component={AppOrLogin} />
<PrivateRoute path={Routes.NewTag} exact component={NewTagPage} />
</>
);
}

0 comments on commit c1f7279

Please sign in to comment.