From 9e51e20da0aa7ef2c6e25153e3d430ff25bc9e14 Mon Sep 17 00:00:00 2001 From: Lars Mitsem Selbekk Date: Tue, 18 Jun 2024 23:45:10 +0200 Subject: [PATCH] feat(match): ux overhaul (#439) * fix(match): permanent scroll bar in FF * fix(scanner): ignore ISBNs when blids found * fix(scanner): wait for alert-close before countdown * feat(scanner): don't say 'error' * feat(scanner): tell users not to accept ugly books * feat(scanner): tell users not to accept ugly books * feat(scanner): scroll countdown into view * feat(usermatchdetail): scan-button blue on click * feat(manualreg): improve buttons --- src/components/CountdownToRedirect.tsx | 12 +++- src/components/OrderHistory.tsx | 2 +- .../Scanner/ManualRegistrationModal.tsx | 24 ++++---- .../matches/Scanner/ScannerModal.tsx | 56 +++++++++++++------ src/components/matches/UserMatchDetail.tsx | 3 +- 5 files changed, 65 insertions(+), 32 deletions(-) diff --git a/src/components/CountdownToRedirect.tsx b/src/components/CountdownToRedirect.tsx index 91b27897..2fe78a63 100644 --- a/src/components/CountdownToRedirect.tsx +++ b/src/components/CountdownToRedirect.tsx @@ -1,6 +1,6 @@ import { LinearProgress, Box, Typography } from "@mui/material"; import { useRouter } from "next/router"; -import { useEffect, useState } from "react"; +import { useEffect, useRef, useState } from "react"; const CountdownToRedirect = ({ path, @@ -11,6 +11,14 @@ const CountdownToRedirect = ({ }) => { const [progress, setProgress] = useState(100); const router = useRouter(); + const elementRef = useRef(null); + + useEffect(() => { + elementRef.current?.scrollIntoView({ + behavior: "smooth", + block: "center", + }); + }, []); useEffect(() => { const interval = setInterval(() => { @@ -30,7 +38,7 @@ const CountdownToRedirect = ({ }, [path, router, seconds]); return ( - + Du blir videresendt om {Math.ceil((progress / 100) * seconds)}{" "} sekunder... diff --git a/src/components/OrderHistory.tsx b/src/components/OrderHistory.tsx index 1f2b5c32..6afaca52 100644 --- a/src/components/OrderHistory.tsx +++ b/src/components/OrderHistory.tsx @@ -118,7 +118,7 @@ const OrderHistory = ({ orders }: { orders: Order[] }) => { width: "80%", display: "flex", flexDirection: "column", - overflowY: "scroll", + overflowY: "auto", }} > { const [manualInput, setManualInput] = useState(""); return ( - + Manuell registrering @@ -43,19 +43,9 @@ const ManualRegistrationModal = ({ - + ); diff --git a/src/components/matches/Scanner/ScannerModal.tsx b/src/components/matches/Scanner/ScannerModal.tsx index 424c0e20..bc2792b6 100644 --- a/src/components/matches/Scanner/ScannerModal.tsx +++ b/src/components/matches/Scanner/ScannerModal.tsx @@ -1,7 +1,7 @@ import { Close, InputRounded } from "@mui/icons-material"; import { AlertColor, Box, Button, Card, Modal, Stack } from "@mui/material"; import Typography from "@mui/material/Typography"; -import { Scanner } from "@yudiel/react-qr-scanner"; +import { Scanner, IDetectedBarcode } from "@yudiel/react-qr-scanner"; import { AxiosResponse } from "axios"; import React, { useEffect, useState } from "react"; @@ -99,7 +99,7 @@ const ScannerModal = ({ } } catch (error) { setFeedback({ - text: String(error), + text: error instanceof Error ? error.message : String(error), severity: "error", visible: true, }); @@ -107,10 +107,44 @@ const ScannerModal = ({ }; useEffect(() => { - if (open && expectedItems.length === fulfilledItems.length) { + if ( + open && + expectedItems.length === fulfilledItems.length && + !(feedback.visible && feedback.severity === "info") + ) { handleClose(); } - }, [expectedItems.length, fulfilledItems.length, handleClose, open]); + }, [ + expectedItems.length, + fulfilledItems.length, + handleClose, + open, + feedback.visible, + feedback.severity, + ]); + + const handleCodeDetection = async ( + detectedCodes: IDetectedBarcode[], + ): Promise => { + const didFindBlid = detectedCodes.some( + (code) => determineScannedTextType(code.rawValue) === TextType.BLID, + ); + const codesToProcess = didFindBlid + ? detectedCodes.filter( + (code) => determineScannedTextType(code.rawValue) === TextType.BLID, + ) + : detectedCodes; + + for (const code of codesToProcess) { + await handleRegistration(code.rawValue).catch((error) => + console.error("Failed to handle scan", error), + ); + // Arbitrary delay to somewhat avoid races the backend isn't smart enough to handle + await new Promise((resolve) => { + window.setTimeout(resolve, 250); + }); + } + }; return ( { - for (const code of detectedCodes) { - await handleRegistration(code.rawValue).catch((error) => - console.error("Failed to handle scan", error), - ); - // Arbitrary delay to somewhat avoid races the backend isn't smart enough to handle - await new Promise((resolve) => { - window.setTimeout(resolve, 250); - }); - } - }} + onScan={handleCodeDetection} /> @@ -169,7 +193,7 @@ const ScannerModal = ({ Du skal møte @@ -127,7 +128,7 @@ const UserMatchDetail = ({ >