Skip to content

Commit dbfffad

Browse files
authored
Merge pull request #284 from HiEventsDev/develop
2 parents 157f205 + 03ea042 commit dbfffad

File tree

8 files changed

+72
-17
lines changed

8 files changed

+72
-17
lines changed
36.9 KB
Binary file not shown.
7.98 KB
Binary file not shown.
17.1 KB
Binary file not shown.

frontend/src/components/common/AttendeeCheckInTable/QrScanner.module.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@
4040
z-index: 2;
4141
}
4242

43+
.soundToggle {
44+
position: absolute;
45+
bottom: 20px;
46+
left: 20px;
47+
z-index: 2;
48+
}
49+
4350
.closeButton {
4451
position: absolute;
4552
top: 20px;

frontend/src/components/common/AttendeeCheckInTable/QrScanner.tsx

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {useEffect, useRef, useState} from 'react';
22
import QrScanner from 'qr-scanner';
33
import {useDebouncedValue} from '@mantine/hooks';
44
import classes from './QrScanner.module.scss';
5-
import {IconBulb, IconBulbOff, IconCameraRotate, IconX} from "@tabler/icons-react";
5+
import {IconBulb, IconBulbOff, IconCameraRotate, IconVolume, IconVolumeOff, IconX} from "@tabler/icons-react";
66
import {Anchor, Button, Menu} from "@mantine/core";
77
import {showError} from "../../../utilites/notifications.tsx";
88
import {t, Trans} from "@lingui/macro";
@@ -29,6 +29,20 @@ export const QRScannerComponent = (props: QRScannerComponentProps) => {
2929
const [isScanFailed, setIsScanFailed] = useState(false);
3030
const [isScanSucceeded, setIsScanSucceeded] = useState(false);
3131

32+
const scanSuccessAudioRef = useRef<HTMLAudioElement | null>(null);
33+
const scanErrorAudioRef = useRef<HTMLAudioElement | null>(null);
34+
const scanInProgressAudioRef = useRef<HTMLAudioElement | null>(null);
35+
36+
const [isSoundOn, setIsSoundOn] = useState(() => {
37+
const storedIsSoundOn = localStorage.getItem("qrScannerSoundOn");
38+
return storedIsSoundOn === null ? true : JSON.parse(storedIsSoundOn);
39+
});
40+
41+
useEffect(() => {
42+
localStorage.setItem("qrScannerSoundOn", JSON.stringify(isSoundOn));
43+
}, [isSoundOn]);
44+
45+
3246
useEffect(() => {
3347
latestProcessedAttendeeIdsRef.current = processedAttendeeIds;
3448
}, [processedAttendeeIds]);
@@ -64,30 +78,44 @@ export const QRScannerComponent = (props: QRScannerComponentProps) => {
6478
showError(t`You already scanned this ticket`);
6579

6680
setIsScanFailed(true);
67-
setInterval(function() {
81+
setInterval(function () {
6882
setIsScanFailed(false);
6983
}, 500);
84+
if (isSoundOn && scanErrorAudioRef.current) {
85+
scanErrorAudioRef.current.play();
86+
}
7087

7188
return;
7289
}
7390

7491
if (!isCheckingIn && !alreadyScanned) {
7592
setIsCheckingIn(true);
93+
94+
if (isSoundOn && scanInProgressAudioRef.current) {
95+
scanInProgressAudioRef.current.play();
96+
}
97+
7698
props.onCheckIn(debouncedAttendeeId, (didSucceed) => {
7799
setIsCheckingIn(false);
78100
setProcessedAttendeeIds(prevIds => [...prevIds, debouncedAttendeeId]);
79101
setCurrentAttendeeId(null);
80102

81103
if (didSucceed) {
82104
setIsScanSucceeded(true);
83-
setInterval(function() {
105+
setInterval(function () {
84106
setIsScanSucceeded(false);
85107
}, 500);
108+
if (isSoundOn && scanSuccessAudioRef.current) {
109+
scanSuccessAudioRef.current.play();
110+
}
86111
} else {
87112
setIsScanFailed(true);
88-
setInterval(function() {
113+
setInterval(function () {
89114
setIsScanFailed(false);
90115
}, 500);
116+
if (isSoundOn && scanErrorAudioRef.current) {
117+
scanErrorAudioRef.current.play();
118+
}
91119
}
92120
}, () => {
93121
setIsCheckingIn(false);
@@ -126,6 +154,10 @@ export const QRScannerComponent = (props: QRScannerComponentProps) => {
126154
}
127155
};
128156

157+
const handleSoundToggle = () => {
158+
setIsSoundOn(!isSoundOn);
159+
};
160+
129161
const requestPermission = async () => {
130162
setPermissionDenied(false);
131163
await startScanner();
@@ -184,6 +216,13 @@ export const QRScannerComponent = (props: QRScannerComponentProps) => {
184216
{!isFlashAvailable && <IconBulbOff color={'#ffffff95'} size={30}/>}
185217
{isFlashAvailable && <IconBulb color={isFlashOn ? 'yellow' : '#ffffff95'} size={30}/>}
186218
</Button>
219+
<Button onClick={handleSoundToggle} variant={'transparent'} className={classes.soundToggle}>
220+
{isSoundOn && <IconVolume color={'#ffffff95'} size={30}/>}
221+
{!isSoundOn && <IconVolumeOff color={'#ffffff95'} size={30}/>}
222+
</Button>
223+
<audio ref={scanSuccessAudioRef} src="/sounds/scan-success.wav"/>
224+
<audio ref={scanErrorAudioRef} src="/sounds/scan-error.wav"/>
225+
<audio ref={scanInProgressAudioRef} src="/sounds/scan-in-progress.wav"/>
187226
<Button onClick={handleClose} variant={'transparent'} className={classes.closeButton}>
188227
<IconX color={'#ffffff95'} size={30}/>
189228
</Button>

frontend/src/components/routes/ticket-widget/SelectTickets/Prices/Tiered/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export const TieredPricing = ({ticket, event, form, ticketIndex}: TieredPricingP
2121
{ticket?.prices?.map((price, index) => {
2222
return (
2323
<div key={index} className={'hi-price-tier-row'}>
24-
<Group justify={'space-between'}>
24+
<Group justify={'space-between'} wrap={'nowrap'}>
2525
<div className={'hi-price-tier'}>
2626
<div className={'hi-price-tier-label'}>{price.label}</div>
2727
<div className={'hi-price-tier-price'}>

frontend/src/components/routes/ticket-widget/SelectTickets/index.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ import {PoweredByFooter} from "../../../common/PoweredByFooter";
3333
import {Event} from "../../../../types.ts";
3434
import {eventsClientPublic} from "../../../../api/event.client.ts";
3535
import {promoCodeClientPublic} from "../../../../api/promo-code.client.ts";
36-
import {IconX} from "@tabler/icons-react"
36+
import {IconX, IconChevronRight} from "@tabler/icons-react"
3737
import {getSessionIdentifier} from "../../../../utilites/sessionIdentifier.ts";
3838
import {Constants} from "../../../../constants.ts";
3939

@@ -297,7 +297,7 @@ const SelectTickets = (props: SelectTicketsProps) => {
297297
.map((n) => n.toString());
298298
quantityRange.unshift("0");
299299

300-
const [ticketIsCollapsed, {toggle: collapseTicket}] = useDisclosure(!ticket.start_collapsed);
300+
const [ticketIsCollapsed, {toggle: collapseTicket}] = useDisclosure(ticket.start_collapsed);
301301

302302
return (
303303
<div key={ticket.id} className={'hi-ticket-row'}>
@@ -328,15 +328,14 @@ const SelectTickets = (props: SelectTicketsProps) => {
328328
{(!ticket.is_available && ticket.type === 'TIERED') && (
329329
<TicketAvailabilityMessage ticket={ticket} event={event}/>
330330
)}
331-
332-
<span className={'hi-ticket-collapse-arrow'}>
333-
{ticketIsCollapsed ? '\u25BC' : '\u25B6'}
334-
</span>
335331
</div>
332+
<span className={`hi-ticket-collapse-arrow`}>
333+
<IconChevronRight className={ticketIsCollapsed ? "" : "open"} />
334+
</span>
336335
</UnstyledButton>
337336
</div>
338337

339-
<Collapse in={ticketIsCollapsed} className={'hi-ticket-content'}>
338+
<Collapse in={!ticketIsCollapsed} className={'hi-ticket-content'}>
340339
<div className={'hi-price-tiers-rows'}>
341340
<TieredPricing
342341
ticketIndex={ticketIndex}

frontend/src/styles/widget/default.scss

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
align-items: center;
4141

4242
h3 {
43+
flex: 1;
4344
margin: 10px 0;
4445

4546
a {
@@ -48,14 +49,23 @@
4849
}
4950

5051
.hi-ticket-title-metadata {
51-
.hi-ticket-collapse-arrow {
52-
color: var(--widget-secondary-color, var(--tk-primary));
53-
margin-left: 10px;
54-
}
55-
5652
margin-left: 5px;
5753
font-weight: normal;
5854
}
55+
56+
.hi-ticket-collapse-arrow {
57+
display: flex;
58+
color: var(--widget-secondary-color, var(--tk-primary));
59+
margin-left: 10px;
60+
61+
svg {
62+
transition: all 0.1s linear;
63+
}
64+
65+
svg.open {
66+
transform: rotate(90deg);
67+
}
68+
}
5969
}
6070
}
6171

0 commit comments

Comments
 (0)