Skip to content

Commit 5213638

Browse files
authored
Hi/logging fixes (#59)
* fixing non logging issue when on same page!! * api
1 parent 52a00ff commit 5213638

File tree

5 files changed

+300
-3
lines changed

5 files changed

+300
-3
lines changed

src/App.tsx

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, { useEffect } from 'react';
22
import { HashRouter, Routes, Route } from 'react-router-dom';
33
import { ToastContainer } from 'react-toastify';
44
import 'react-toastify/dist/ReactToastify.css';
@@ -11,6 +11,30 @@ import NavbarLayout from './layouts/NavbarLayout';
1111
import SuccessPage from './pages/LoadingScreen/success';
1212

1313
const App = (): React.ReactElement => {
14+
useEffect(() => {
15+
// Check URL parameters on page load
16+
const urlParams = new URLSearchParams(window.location.search);
17+
const action = urlParams.get('action');
18+
const eventKey = urlParams.get('eventKey');
19+
20+
// If this is a check-in action, redirect to the loading route
21+
if (action === 'checkin' && eventKey) {
22+
// Clear the URL parameters
23+
window.history.replaceState(
24+
{},
25+
'',
26+
`${window.location.origin}${window.location.pathname}`
27+
);
28+
29+
// Force navigation to the loading route
30+
const newUrl = `${window.location.origin}${window.location.pathname}`;
31+
window.location.href = `${newUrl}#/loading/${eventKey}`;
32+
33+
// Force a reload to ensure the component loads fresh
34+
setTimeout(() => { window.location.reload(); }, 100);
35+
}
36+
}, []);
37+
1438
return (
1539
<HashRouter>
1640
<ToastContainer />

src/api.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import axios from 'axios';
33
const instance = axios.create({
44
baseURL: import.meta.env.VITE_BASE_URL
55
? import.meta.env.VITE_BASE_URL
6-
: // : 'http://127.0.0.1:3000',
6+
: // 'http://127.0.0.1:3000',
77
'https://points-api.illinoiswcs.org',
88
withCredentials: true
99
});

src/pages/Events/EventQRCode.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ const EventQRCode: React.FC<EventQRCodeProps> = ({
2525
? 'http://127.0.0.1:8080' // development frontend URL
2626
: 'https://points.illinoiswcs.org'; // production frontend URL
2727

28-
const loadingUrl = `${baseUrl}/#/loading/${eventKey}`;
28+
// const loadingUrl = `${baseUrl}/#/loading/${eventKey}`;
29+
const loadingUrl =
30+
`${baseUrl}?action=checkin&eventKey=${eventKey}` + `&t=${Date.now()}`;
2931

3032
// download as svg
3133
const downloadSVG = (): void => {
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
import React, { useEffect, useState } from 'react';
2+
import { useParams, useLocation, useNavigate } from 'react-router-dom';
3+
import axiosInstance from '../../api';
4+
import { useQuery } from 'react-query';
5+
import { toastError, toastSuccess } from '../../utils/toast';
6+
import { Profile } from '../../types/profile';
7+
import { Heading, Box, VStack, Progress, Link } from '@chakra-ui/react';
8+
9+
const LoadingScreen = (): JSX.Element => {
10+
const [state, setState] = useState('auth');
11+
12+
const [isError, setIsError] = useState(false);
13+
const { eventKey } = useParams();
14+
const location = useLocation();
15+
const navigate = useNavigate();
16+
17+
const [isProcessing, setIsProcessing] = useState(false);
18+
const [hasAttemptedLogging, setHasAttemptedLogging] = useState(false);
19+
20+
useEffect(() => {
21+
// Store the current event key and visit ID
22+
const currentEventKey = eventKey ?? '';
23+
24+
// Check if we've processed this event recently
25+
const lastProcessedEvent = localStorage.getItem('last_processed_event');
26+
const lastProcessedTime = localStorage.getItem('last_processed_time');
27+
28+
// If we processed this exact event in the last minute, force a hard reload
29+
if (
30+
lastProcessedEvent === currentEventKey &&
31+
lastProcessedTime &&
32+
Date.now() - parseInt(lastProcessedTime) < 60000
33+
) {
34+
console.log('Forcing reload for repeated event access');
35+
return;
36+
}
37+
38+
// Otherwise, mark this as a new visit
39+
localStorage.setItem('last_processed_event', currentEventKey);
40+
localStorage.setItem('last_processed_time', Date.now().toString());
41+
42+
// Continue with normal component flow
43+
}, [eventKey]);
44+
45+
useEffect(() => {
46+
const authDelay = setTimeout(() => {
47+
setState('logging');
48+
49+
const loggingDelay = setTimeout(() => {
50+
setState('done');
51+
52+
const doneDelay = setTimeout(() => {
53+
navigate('/points', { replace: true });
54+
}, 900);
55+
return () => {
56+
clearTimeout(doneDelay);
57+
};
58+
}, 800);
59+
60+
return () => {
61+
clearTimeout(loggingDelay);
62+
};
63+
}, 400);
64+
65+
return () => {
66+
clearTimeout(authDelay);
67+
};
68+
}, []);
69+
70+
const { data, isLoading } = useQuery<Profile>(['get-profile'], async () => {
71+
const res = await axiosInstance.get('/profile');
72+
return res.data;
73+
});
74+
75+
const logPointsAndRedirect = async (): Promise<void> => {
76+
if (!eventKey) {
77+
console.error('Event Key is missing.');
78+
toastError('Event key is missing. Unable to log points.');
79+
return;
80+
}
81+
82+
try {
83+
console.log('Starting points logging process for event:', eventKey);
84+
setIsProcessing(true);
85+
86+
const response = await axiosInstance.patch('/profile', { eventKey });
87+
toastSuccess(response.data.message);
88+
} catch (error: any) {
89+
setIsError(true);
90+
console.error('Error logging points:', error);
91+
const errorMessage =
92+
error.response?.data?.message ??
93+
'An error occurred while logging points.';
94+
toastError(errorMessage);
95+
} finally {
96+
setIsProcessing(false);
97+
setHasAttemptedLogging(true);
98+
}
99+
};
100+
101+
useEffect(() => {
102+
if (!isLoading && !isProcessing && !hasAttemptedLogging) {
103+
if (!data) {
104+
console.log('Redirecting to login - no data');
105+
const loginUrl = new URL(
106+
`${String(axiosInstance.defaults.baseURL)}/auth/login`
107+
);
108+
109+
loginUrl.searchParams.set('fromQR', 'true');
110+
loginUrl.searchParams.set('eventKey', String(eventKey ?? ''));
111+
loginUrl.searchParams.set('returnTo', `/#/loading/${eventKey ?? ''}`);
112+
113+
window.location.href = loginUrl.toString();
114+
return;
115+
}
116+
117+
// If we have data and eventKey, proceed with logging points
118+
// regardless of isPostAuth (since user might already be authenticated)
119+
if (data && eventKey) {
120+
void logPointsAndRedirect();
121+
} else {
122+
console.log('Missing required conditions:', {
123+
hasData: !!data,
124+
hasEventKey: !!eventKey
125+
});
126+
}
127+
}
128+
}, [
129+
data,
130+
eventKey,
131+
location,
132+
isLoading,
133+
isProcessing,
134+
hasAttemptedLogging,
135+
navigate
136+
]);
137+
138+
const Content = (): React.ReactElement => {
139+
if (isError) {
140+
return (
141+
<Box>
142+
<Heading mb="10px">Sorry, something went wrong</Heading>
143+
<Box className="text-sm text-gray-500" fontSize="2xl" mb="10px">
144+
Please try manually logging your points here:
145+
</Box>
146+
{/* <Link href='http://127.0.0.1:8080'
147+
fontSize="2xl"
148+
color="pink"
149+
>
150+
http://127.0.0.1:8080
151+
</Link> */}
152+
<Link
153+
href="https://points.illinoiswcs.org"
154+
fontSize="2xl"
155+
color="pink"
156+
>
157+
https://points.illinoiswcs.org
158+
</Link>
159+
</Box>
160+
);
161+
}
162+
163+
if (isLoading ?? state === 'auth') {
164+
return (
165+
<Box>
166+
<Heading mb="10px">Authenticating...</Heading>
167+
<Box className="text-sm text-gray-500" fontSize="2xl" mb="25px">
168+
Please wait while we verify your profile
169+
</Box>
170+
</Box>
171+
);
172+
}
173+
174+
if (isProcessing ?? state === 'logging') {
175+
return (
176+
<Box>
177+
<Heading mb="10px">Hang tight...</Heading>
178+
<Box className="text-sm text-gray-500" fontSize="2xl" mb="25px">
179+
We&apos;re logging your points
180+
</Box>
181+
</Box>
182+
);
183+
}
184+
185+
return (
186+
<Box>
187+
<Heading mb="10px">You&apos;re checked in 🎉</Heading>
188+
<Box className="text-sm text-gray-500" fontSize="2xl" mb="25px">
189+
Thanks for joining us!
190+
</Box>
191+
</Box>
192+
);
193+
};
194+
195+
return (
196+
<Box
197+
display="flex"
198+
justifyContent="center"
199+
alignItems="center"
200+
height="70vh"
201+
minW="300px"
202+
>
203+
<VStack alignItems="left">
204+
<Content />
205+
{isError ? (
206+
<div></div>
207+
) : (
208+
<Progress
209+
size="sm"
210+
minW="300px"
211+
maxW="40vw"
212+
width="30vw"
213+
isIndeterminate
214+
/>
215+
)}
216+
</VStack>
217+
</Box>
218+
);
219+
};
220+
221+
export default LoadingScreen;
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import React, { useState, useEffect } from 'react';
2+
import { Box, Heading, Text, Button, VStack } from '@chakra-ui/react';
3+
import { useNavigate } from 'react-router-dom';
4+
import Confetti from 'react-confetti';
5+
import { useWindowSize } from 'react-use';
6+
7+
const SuccessPage: React.FC = (): React.ReactElement => {
8+
const navigate = useNavigate();
9+
const { width, height } = useWindowSize();
10+
const [showConfetti, setShowConfetti] = useState(true);
11+
12+
useEffect(() => {
13+
const timer = setTimeout(() => {
14+
setShowConfetti(false);
15+
}, 5000);
16+
17+
return () => {
18+
clearTimeout(timer);
19+
};
20+
}, []);
21+
22+
const handleGoHome = (): void => {
23+
navigate('/');
24+
};
25+
26+
return (
27+
<Box
28+
p={5}
29+
display="flex"
30+
justifyContent="center"
31+
alignItems="center"
32+
h="100vh"
33+
>
34+
{showConfetti && <Confetti width={width} height={height} />}
35+
<VStack spacing={5} textAlign="center">
36+
<Heading size="2xl" color="pink.500">
37+
Success!
38+
</Heading>
39+
<Text fontSize="lg" color="gray.600">
40+
You have successfully checked in.
41+
</Text>
42+
<Button colorScheme="pink" onClick={handleGoHome}>
43+
Go to Home
44+
</Button>
45+
</VStack>
46+
</Box>
47+
);
48+
};
49+
50+
export default SuccessPage;

0 commit comments

Comments
 (0)