From 69200c0ae56ce784f8a4ef87fdae461f569403a7 Mon Sep 17 00:00:00 2001 From: rizky Date: Thu, 5 Sep 2024 00:50:03 -0700 Subject: [PATCH] QR --- .../Datepicker/components/Calendar/Days.tsx | 775 ++++++++++-------- .../Datepicker/components/Calendar/index.tsx | 17 + comps/custom/Datepicker/types/index.ts | 5 +- comps/custom/QrLabel.tsx | 18 + comps/custom/QrReader.tsx | 78 ++ 5 files changed, 540 insertions(+), 353 deletions(-) create mode 100644 comps/custom/QrLabel.tsx create mode 100644 comps/custom/QrReader.tsx diff --git a/comps/custom/Datepicker/components/Calendar/Days.tsx b/comps/custom/Datepicker/components/Calendar/Days.tsx index 33c8c0d..f4e75ac 100755 --- a/comps/custom/Datepicker/components/Calendar/Days.tsx +++ b/comps/custom/Datepicker/components/Calendar/Days.tsx @@ -4,393 +4,464 @@ import React, { useCallback, useContext } from "react"; import { BG_COLOR, TEXT_COLOR } from "../../constants"; import DatepickerContext from "../../contexts/DatepickerContext"; -import { formatDate, nextMonth, previousMonth, classNames as cn } from "../../helpers"; +import { + formatDate, + nextMonth, + previousMonth, + classNames as cn, +} from "../../helpers"; import { Period } from "../../types"; dayjs.extend(isBetween); interface Props { - calendarData: { - date: dayjs.Dayjs; - days: { - previous: number[]; - current: number[]; - next: number[]; - }; + calendarData: { + date: dayjs.Dayjs; + days: { + previous: number[]; + current: number[]; + next: number[]; }; - onClickPreviousDays: (day: number) => void; - onClickDay: (day: number) => void; - onClickNextDays: (day: number) => void; + }; + onClickPreviousDays: (day: number) => void; + onClickDay: (day: number) => void; + onClickNextDays: (day: number) => void; + onIcon?: (day: number, date: Date) => any; } const Days: React.FC = ({ - calendarData, - onClickPreviousDays, - onClickDay, - onClickNextDays + calendarData, + onClickPreviousDays, + onClickDay, + onClickNextDays, + onIcon, }) => { - // Contexts - const { - primaryColor, - period, - changePeriod, - dayHover, - changeDayHover, - minDate, - maxDate, - disabledDates - } = useContext(DatepickerContext); + // Contexts + const { + primaryColor, + period, + changePeriod, + dayHover, + changeDayHover, + minDate, + maxDate, + disabledDates, + } = useContext(DatepickerContext); - // Functions - const currentDateClass = useCallback( - (item: number) => { - const itemDate = `${calendarData.date.year()}-${calendarData.date.month() + 1}-${ - item >= 10 ? item : "0" + item - }`; - if (formatDate(dayjs()) === formatDate(dayjs(itemDate))) - return TEXT_COLOR["500"][primaryColor as keyof (typeof TEXT_COLOR)["500"]]; - return ""; - }, - [calendarData.date, primaryColor] - ); + // Functions + const currentDateClass = useCallback( + (item: number) => { + const itemDate = `${calendarData.date.year()}-${ + calendarData.date.month() + 1 + }-${item >= 10 ? item : "0" + item}`; + if (formatDate(dayjs()) === formatDate(dayjs(itemDate))) + return TEXT_COLOR["500"][ + primaryColor as keyof (typeof TEXT_COLOR)["500"] + ]; + return ""; + }, + [calendarData.date, primaryColor] + ); - const activeDateData = useCallback( - (day: number) => { - const fullDay = `${calendarData.date.year()}-${calendarData.date.month() + 1}-${day}`; - let className = ""; + const activeDateData = useCallback( + (day: number) => { + const fullDay = `${calendarData.date.year()}-${ + calendarData.date.month() + 1 + }-${day}`; + let className = ""; - if (dayjs(fullDay).isSame(period.start) && dayjs(fullDay).isSame(period.end)) { - className = ` ${BG_COLOR["500"][primaryColor]} c-text-white c-font-medium rounded-full`; - } else if (dayjs(fullDay).isSame(period.start)) { - className = ` ${BG_COLOR["500"][primaryColor]} c-text-white c-font-medium ${ - dayjs(fullDay).isSame(dayHover) && !period.end - ? "c-rounded-full" - : "c-rounded-l-full" - }`; - } else if (dayjs(fullDay).isSame(period.end)) { - className = ` ${BG_COLOR["500"][primaryColor]} c-text-white c-font-medium ${ - dayjs(fullDay).isSame(dayHover) && !period.start - ? "c-rounded-full" - : "c-rounded-r-full" - }`; - } + if ( + dayjs(fullDay).isSame(period.start) && + dayjs(fullDay).isSame(period.end) + ) { + className = ` ${BG_COLOR["500"][primaryColor]} c-text-white c-font-medium rounded-full`; + } else if (dayjs(fullDay).isSame(period.start)) { + className = ` ${ + BG_COLOR["500"][primaryColor] + } c-text-white c-font-medium ${ + dayjs(fullDay).isSame(dayHover) && !period.end + ? "c-rounded-full" + : "c-rounded-l-full" + }`; + } else if (dayjs(fullDay).isSame(period.end)) { + className = ` ${ + BG_COLOR["500"][primaryColor] + } c-text-white c-font-medium ${ + dayjs(fullDay).isSame(dayHover) && !period.start + ? "c-rounded-full" + : "c-rounded-r-full" + }`; + } - return { - active: dayjs(fullDay).isSame(period.start) || dayjs(fullDay).isSame(period.end), - className: className - }; - }, - [calendarData.date, dayHover, period.end, period.start, primaryColor] - ); + return { + active: + dayjs(fullDay).isSame(period.start) || + dayjs(fullDay).isSame(period.end), + className: className, + }; + }, + [calendarData.date, dayHover, period.end, period.start, primaryColor] + ); - const hoverClassByDay = useCallback( - (day: number) => { - let className = currentDateClass(day); - const fullDay = `${calendarData.date.year()}-${calendarData.date.month() + 1}-${ - day >= 10 ? day : "0" + day - }`; + const hoverClassByDay = useCallback( + (day: number) => { + let className = currentDateClass(day); + const fullDay = `${calendarData.date.year()}-${ + calendarData.date.month() + 1 + }-${day >= 10 ? day : "0" + day}`; - if (period.start && period.end) { - if (dayjs(fullDay).isBetween(period.start, period.end, "day", "[)")) { - return ` ${BG_COLOR["100"][primaryColor]} ${currentDateClass( - day - )} dark:bg-white/10`; - } - } + if (period.start && period.end) { + if (dayjs(fullDay).isBetween(period.start, period.end, "day", "[)")) { + return ` ${BG_COLOR["100"][primaryColor]} ${currentDateClass( + day + )} dark:bg-white/10`; + } + } - if (!dayHover) { - return className; - } + if (!dayHover) { + return className; + } - if (period.start && dayjs(fullDay).isBetween(period.start, dayHover, "day", "[)")) { - className = ` ${BG_COLOR["100"][primaryColor]} ${currentDateClass( - day - )} dark:bg-white/10`; - } + if ( + period.start && + dayjs(fullDay).isBetween(period.start, dayHover, "day", "[)") + ) { + className = ` ${BG_COLOR["100"][primaryColor]} ${currentDateClass( + day + )} dark:bg-white/10`; + } - if (period.end && dayjs(fullDay).isBetween(dayHover, period.end, "day", "[)")) { - className = ` ${BG_COLOR["100"][primaryColor]} ${currentDateClass( - day - )} dark:bg-white/10`; - } + if ( + period.end && + dayjs(fullDay).isBetween(dayHover, period.end, "day", "[)") + ) { + className = ` ${BG_COLOR["100"][primaryColor]} ${currentDateClass( + day + )} dark:bg-white/10`; + } - if (dayHover === fullDay) { - const bgColor = BG_COLOR["500"][primaryColor]; - className = ` transition-all duration-500 text-white font-medium ${bgColor} ${ - period.start ? "rounded-r-full" : "rounded-l-full" - }`; - } + if (dayHover === fullDay) { + const bgColor = BG_COLOR["500"][primaryColor]; + className = ` transition-all duration-500 text-white font-medium ${bgColor} ${ + period.start ? "rounded-r-full" : "rounded-l-full" + }`; + } - return className; - }, - [calendarData.date, currentDateClass, dayHover, period.end, period.start, primaryColor] - ); + return className; + }, + [ + calendarData.date, + currentDateClass, + dayHover, + period.end, + period.start, + primaryColor, + ] + ); - const isDateTooEarly = useCallback( - (day: number, type: "current" | "previous" | "next") => { - if (!minDate) { - return false; - } - const object = { - previous: previousMonth(calendarData.date), - current: calendarData.date, - next: nextMonth(calendarData.date) - }; - const newDate = object[type as keyof typeof object]; - const formattedDate = newDate.set("date", day); - return dayjs(formattedDate).isSame(dayjs(minDate), "day") - ? false - : dayjs(formattedDate).isBefore(dayjs(minDate)); - }, - [calendarData.date, minDate] - ); + const isDateTooEarly = useCallback( + (day: number, type: "current" | "previous" | "next") => { + if (!minDate) { + return false; + } + const object = { + previous: previousMonth(calendarData.date), + current: calendarData.date, + next: nextMonth(calendarData.date), + }; + const newDate = object[type as keyof typeof object]; + const formattedDate = newDate.set("date", day); + return dayjs(formattedDate).isSame(dayjs(minDate), "day") + ? false + : dayjs(formattedDate).isBefore(dayjs(minDate)); + }, + [calendarData.date, minDate] + ); - const isDateTooLate = useCallback( - (day: number, type: "current" | "previous" | "next") => { - if (!maxDate) { - return false; - } - const object = { - previous: previousMonth(calendarData.date), - current: calendarData.date, - next: nextMonth(calendarData.date) - }; - const newDate = object[type as keyof typeof object]; - const formattedDate = newDate.set("date", day); - return dayjs(formattedDate).isSame(dayjs(maxDate), "day") - ? false - : dayjs(formattedDate).isAfter(dayjs(maxDate)); - }, - [calendarData.date, maxDate] - ); + const isDateTooLate = useCallback( + (day: number, type: "current" | "previous" | "next") => { + if (!maxDate) { + return false; + } + const object = { + previous: previousMonth(calendarData.date), + current: calendarData.date, + next: nextMonth(calendarData.date), + }; + const newDate = object[type as keyof typeof object]; + const formattedDate = newDate.set("date", day); + return dayjs(formattedDate).isSame(dayjs(maxDate), "day") + ? false + : dayjs(formattedDate).isAfter(dayjs(maxDate)); + }, + [calendarData.date, maxDate] + ); - const isDateDisabled = useCallback( - (day: number, type: "current" | "previous" | "next") => { - if (isDateTooEarly(day, type) || isDateTooLate(day, type)) { - return true; - } - const object = { - previous: previousMonth(calendarData.date), - current: calendarData.date, - next: nextMonth(calendarData.date) - }; - const newDate = object[type as keyof typeof object]; - const formattedDate = `${newDate.year()}-${newDate.month() + 1}-${ - day >= 10 ? day : "0" + day - }`; + const isDateDisabled = useCallback( + (day: number, type: "current" | "previous" | "next") => { + if (isDateTooEarly(day, type) || isDateTooLate(day, type)) { + return true; + } + const object = { + previous: previousMonth(calendarData.date), + current: calendarData.date, + next: nextMonth(calendarData.date), + }; + const newDate = object[type as keyof typeof object]; + const formattedDate = `${newDate.year()}-${newDate.month() + 1}-${ + day >= 10 ? day : "0" + day + }`; - if (!disabledDates || (Array.isArray(disabledDates) && !disabledDates.length)) { - return false; - } + if ( + !disabledDates || + (Array.isArray(disabledDates) && !disabledDates.length) + ) { + return false; + } - let matchingCount = 0; - disabledDates?.forEach(dateRange => { - if ( - dayjs(formattedDate).isAfter(dateRange.startDate) && - dayjs(formattedDate).isBefore(dateRange.endDate) - ) { - matchingCount++; - } - if ( - dayjs(formattedDate).isSame(dateRange.startDate) || - dayjs(formattedDate).isSame(dateRange.endDate) - ) { - matchingCount++; - } + let matchingCount = 0; + disabledDates?.forEach((dateRange) => { + if ( + dayjs(formattedDate).isAfter(dateRange.startDate) && + dayjs(formattedDate).isBefore(dateRange.endDate) + ) { + matchingCount++; + } + if ( + dayjs(formattedDate).isSame(dateRange.startDate) || + dayjs(formattedDate).isSame(dateRange.endDate) + ) { + matchingCount++; + } + }); + return matchingCount > 0; + }, + [calendarData.date, isDateTooEarly, isDateTooLate, disabledDates] + ); + + const buttonClass = useCallback( + (day: number, type: "current" | "next" | "previous") => { + const baseClass = + "c-flex c-items-center c-justify-center c-w-12 c-h-12 lg:c-w-10 lg:c-h-10 c-relative"; + if (type === "current") { + return cn( + baseClass, + !activeDateData(day).active + ? hoverClassByDay(day) + : activeDateData(day).className, + isDateDisabled(day, type) && "c-text-gray-400 c-cursor-not-allowed" + ); + } + return cn( + baseClass, + isDateDisabled(day, type) && "c-cursor-not-allowed", + "c-text-gray-400" + ); + }, + [activeDateData, hoverClassByDay, isDateDisabled] + ); + + const checkIfHoverPeriodContainsDisabledPeriod = useCallback( + (hoverPeriod: Period) => { + if (!Array.isArray(disabledDates)) { + return false; + } + for (let i = 0; i < disabledDates.length; i++) { + if ( + dayjs(hoverPeriod.start).isBefore(disabledDates[i].startDate) && + dayjs(hoverPeriod.end).isAfter(disabledDates[i].endDate) + ) { + return true; + } + } + return false; + }, + [disabledDates] + ); + + const getMetaData = useCallback(() => { + return { + previous: previousMonth(calendarData.date), + current: calendarData.date, + next: nextMonth(calendarData.date), + }; + }, [calendarData.date]); + + const hoverDay = useCallback( + (day: number, type: string) => { + const object = getMetaData(); + const newDate = object[type as keyof typeof object]; + const newHover = `${newDate.year()}-${newDate.month() + 1}-${ + day >= 10 ? day : "0" + day + }`; + + if (period.start && !period.end) { + const hoverPeriod = { ...period, end: newHover }; + if (dayjs(newHover).isBefore(dayjs(period.start))) { + hoverPeriod.start = newHover; + hoverPeriod.end = period.start; + if (!checkIfHoverPeriodContainsDisabledPeriod(hoverPeriod)) { + changePeriod({ + start: null, + end: period.start, }); - return matchingCount > 0; - }, - [calendarData.date, isDateTooEarly, isDateTooLate, disabledDates] - ); + } + } + if (!checkIfHoverPeriodContainsDisabledPeriod(hoverPeriod)) { + changeDayHover(newHover); + } + } - const buttonClass = useCallback( - (day: number, type: "current" | "next" | "previous") => { - const baseClass = "c-flex c-items-center c-justify-center c-w-12 c-h-12 lg:c-w-10 lg:c-h-10"; - if (type === "current") { - return cn( - baseClass, - !activeDateData(day).active - ? hoverClassByDay(day) - : activeDateData(day).className, - isDateDisabled(day, type) && "c-text-gray-400 c-cursor-not-allowed" - ); - } - return cn(baseClass, isDateDisabled(day, type) && "c-cursor-not-allowed", "c-text-gray-400"); - }, - [activeDateData, hoverClassByDay, isDateDisabled] - ); + if (!period.start && period.end) { + const hoverPeriod = { ...period, start: newHover }; + if (dayjs(newHover).isAfter(dayjs(period.end))) { + hoverPeriod.start = period.end; + hoverPeriod.end = newHover; + if (!checkIfHoverPeriodContainsDisabledPeriod(hoverPeriod)) { + changePeriod({ + start: period.end, + end: null, + }); + } + } + if (!checkIfHoverPeriodContainsDisabledPeriod(hoverPeriod)) { + changeDayHover(newHover); + } + } + }, + [ + changeDayHover, + changePeriod, + checkIfHoverPeriodContainsDisabledPeriod, + getMetaData, + period, + ] + ); - const checkIfHoverPeriodContainsDisabledPeriod = useCallback( - (hoverPeriod: Period) => { - if (!Array.isArray(disabledDates)) { - return false; - } - for (let i = 0; i < disabledDates.length; i++) { - if ( - dayjs(hoverPeriod.start).isBefore(disabledDates[i].startDate) && - dayjs(hoverPeriod.end).isAfter(disabledDates[i].endDate) - ) { - return true; - } - } - return false; - }, - [disabledDates] - ); + const handleClickDay = useCallback( + (day: number, type: "previous" | "current" | "next") => { + function continueClick() { + if (type === "previous") { + onClickPreviousDays(day); + } - const getMetaData = useCallback(() => { - return { - previous: previousMonth(calendarData.date), - current: calendarData.date, - next: nextMonth(calendarData.date) - }; - }, [calendarData.date]); + if (type === "current") { + onClickDay(day); + } - const hoverDay = useCallback( - (day: number, type: string) => { - const object = getMetaData(); - const newDate = object[type as keyof typeof object]; - const newHover = `${newDate.year()}-${newDate.month() + 1}-${ - day >= 10 ? day : "0" + day - }`; + if (type === "next") { + onClickNextDays(day); + } + } - if (period.start && !period.end) { - const hoverPeriod = { ...period, end: newHover }; - if (dayjs(newHover).isBefore(dayjs(period.start))) { - hoverPeriod.start = newHover; - hoverPeriod.end = period.start; - if (!checkIfHoverPeriodContainsDisabledPeriod(hoverPeriod)) { - changePeriod({ - start: null, - end: period.start - }); - } - } - if (!checkIfHoverPeriodContainsDisabledPeriod(hoverPeriod)) { - changeDayHover(newHover); - } - } + if (disabledDates?.length) { + const object = getMetaData(); + const newDate = object[type as keyof typeof object]; + const clickDay = `${newDate.year()}-${newDate.month() + 1}-${ + day >= 10 ? day : "0" + day + }`; - if (!period.start && period.end) { - const hoverPeriod = { ...period, start: newHover }; - if (dayjs(newHover).isAfter(dayjs(period.end))) { - hoverPeriod.start = period.end; - hoverPeriod.end = newHover; - if (!checkIfHoverPeriodContainsDisabledPeriod(hoverPeriod)) { - changePeriod({ - start: period.end, - end: null - }); - } - } - if (!checkIfHoverPeriodContainsDisabledPeriod(hoverPeriod)) { - changeDayHover(newHover); - } - } - }, - [ - changeDayHover, - changePeriod, - checkIfHoverPeriodContainsDisabledPeriod, - getMetaData, - period - ] - ); + if (period.start && !period.end) { + dayjs(clickDay).isSame(dayHover) && continueClick(); + } else if (!period.start && period.end) { + dayjs(clickDay).isSame(dayHover) && continueClick(); + } else { + continueClick(); + } + } else { + continueClick(); + } + }, + [ + dayHover, + disabledDates?.length, + getMetaData, + onClickDay, + onClickNextDays, + onClickPreviousDays, + period.end, + period.start, + ] + ); + const load_marker = (day: number, type: string) => { + let fullDay = `${calendarData.date.year()}-${ + calendarData.date.month() + 1 + }-${day >= 10 ? day : "0" + day}`; + if (type === "previous") { + const newDate = previousMonth(calendarData.date); + fullDay = `${newDate.year()}-${newDate.month() + 1}-${ + day >= 10 ? day : "0" + day + }`; + } + if (type === "next") { + const newDate = nextMonth(calendarData.date); + fullDay = `${newDate.year()}-${newDate.month() + 1}-${ + day >= 10 ? day : "0" + day + }`; + } + const res = new Date(fullDay); + return typeof onIcon === "function" ? onIcon(day, res) : null; + }; + return ( +
+ {calendarData.days.previous.map((item, index) => ( + + ))} - const handleClickDay = useCallback( - (day: number, type: "previous" | "current" | "next") => { - function continueClick() { - if (type === "previous") { - onClickPreviousDays(day); - } + {calendarData.days.current.map((item, index) => ( + + ))} - if (type === "current") { - onClickDay(day); - } - - if (type === "next") { - onClickNextDays(day); - } - } - - if (disabledDates?.length) { - const object = getMetaData(); - const newDate = object[type as keyof typeof object]; - const clickDay = `${newDate.year()}-${newDate.month() + 1}-${ - day >= 10 ? day : "0" + day - }`; - - if (period.start && !period.end) { - dayjs(clickDay).isSame(dayHover) && continueClick(); - } else if (!period.start && period.end) { - dayjs(clickDay).isSame(dayHover) && continueClick(); - } else { - continueClick(); - } - } else { - continueClick(); - } - }, - [ - dayHover, - disabledDates?.length, - getMetaData, - onClickDay, - onClickNextDays, - onClickPreviousDays, - period.end, - period.start - ] - ); - - return ( -
- {calendarData.days.previous.map((item, index) => ( - - ))} - - {calendarData.days.current.map((item, index) => ( - - ))} - - {calendarData.days.next.map((item, index) => ( - - ))} -
- ); + {calendarData.days.next.map((item, index) => ( + + ))} +
+ ); }; export default Days; diff --git a/comps/custom/Datepicker/components/Calendar/index.tsx b/comps/custom/Datepicker/components/Calendar/index.tsx index de6086c..ad506a9 100755 --- a/comps/custom/Datepicker/components/Calendar/index.tsx +++ b/comps/custom/Datepicker/components/Calendar/index.tsx @@ -44,6 +44,7 @@ interface Props { changeMonth: (month: number) => void; changeYear: (year: number) => void; mode?: "monthly" | "daily"; + onMark?: (day: number, date: Date) => any; } const Calendar: React.FC = ({ @@ -54,6 +55,7 @@ const Calendar: React.FC = ({ onClickNext, changeMonth, changeYear, + onMark, mode = "daily", }) => { // Contexts @@ -366,6 +368,21 @@ const Calendar: React.FC = ({ onClickPreviousDays={clickPreviousDays} onClickDay={clickDay} onClickNextDays={clickNextDays} + onIcon={(day, date) => { + if(typeof onMark === "function"){ + return onMark(day, date) + } + return <> + if (new Date().getDate() === day) + return ( +
+
+ ! +
+
+ ); + return <> + }} /> )} diff --git a/comps/custom/Datepicker/types/index.ts b/comps/custom/Datepicker/types/index.ts index 9f5487a..c8c3b4b 100755 --- a/comps/custom/Datepicker/types/index.ts +++ b/comps/custom/Datepicker/types/index.ts @@ -82,7 +82,10 @@ export interface DatepickerType { disabledDates?: DateRangeType[] | null; startWeekOn?: string | null; popoverDirection?: PopoverDirectionType; - mode?: "daily" | "monthly" + mode?: "daily" | "monthly"; + onMark?: (day: number, date: Date) => any; + onLoad?: () => Promise + } export type ColorKeys = (typeof COLORS)[number]; // "blue" | "orange" diff --git a/comps/custom/QrLabel.tsx b/comps/custom/QrLabel.tsx new file mode 100644 index 0000000..a40c11a --- /dev/null +++ b/comps/custom/QrLabel.tsx @@ -0,0 +1,18 @@ +import { FC } from "react"; +import QRCode from 'react-qr-code'; + +export const QrLabel: FC<{ + value: string, + bgcolor: string, + fgcolor: string, + size: number +}> = ({ value, bgcolor, fgcolor, size }) => { + return ( +
+ +
+ ) +} \ No newline at end of file diff --git a/comps/custom/QrReader.tsx b/comps/custom/QrReader.tsx new file mode 100644 index 0000000..677f197 --- /dev/null +++ b/comps/custom/QrReader.tsx @@ -0,0 +1,78 @@ +import { useEffect, useRef, useState } from "react"; +import QrScanner from "qr-scanner"; + +export const QrReader = () => { + const scanner = useRef(); + const videoEl = useRef(null); + const qrBoxEl = useRef(null); + const [qrOn, setQrOn] = useState(true); + const [scannedResult, setScannedResult] = useState(""); + + // Success + const onScanSuccess = (result: QrScanner.ScanResult) => { + console.log(result); + setScannedResult(result?.data); + }; + + // Fail + const onScanFail = (err: string | Error) => { + console.log(err); + }; + + useEffect(() => { + if (videoEl?.current && !scanner.current) { + scanner.current = new QrScanner(videoEl?.current, onScanSuccess, { + onDecodeError: onScanFail, + preferredCamera: "environment", + highlightScanRegion: true, + highlightCodeOutline: true, + overlay: qrBoxEl?.current || undefined, + }); + + scanner?.current + ?.start() + .then(() => setQrOn(true)) + .catch((err) => { + if (err) setQrOn(false); + }); + } + + return () => { + if (!videoEl?.current) { + scanner?.current?.stop(); + } + }; + }, []); + + useEffect(() => { + if (!qrOn) + alert( + "Camera is blocked or not accessible. Please allow camera in your browser permissions and Reload." + ); + }, [qrOn]); + + return ( +
+ {/* QR */} + +
+ +
+ + {/* Show Data Result if scan is success */} + {scannedResult && ( +

+ Scanned Result: {scannedResult} +

+ )} +
+ ); +};