-
Notifications
You must be signed in to change notification settings - Fork 11
Add functionality to use check-in app for QR code scanning with eventyay #115
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: development
Are you sure you want to change the base?
Changes from 7 commits
0771e62
077215b
4c8f4da
57f721b
cbc8b39
3405c89
4f382e0
67ee3dd
b505113
67e1679
e168a42
d016d4c
049a99e
da28507
e188f12
426cf90
fa04c51
1e76141
42f2a92
91a9325
c95c222
f3e6f71
d2ff327
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
sak:3670 | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<script setup> | ||
import QRCamera from '@/components/Common/QRCamera.vue' | ||
import { useLoadingStore } from '@/stores/loading' | ||
const loadingStore = useLoadingStore() | ||
loadingStore.contentLoaded() | ||
</script> | ||
|
||
<template> | ||
<div | ||
class="-mt-16 grid h-screen w-full grid-cols-1 place-items-center items-center justify-center align-middle" | ||
> | ||
<QRCamera :qr-type="'eventyaycheckin'" :scan-type="'Check-In'" /> | ||
</div> | ||
</template> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
<script setup> | ||
import { useLoadingStore } from '@/stores/loading' | ||
import { ref, onMounted, watchEffect } from 'vue' | ||
import { useEventyayEventStore } from '@/stores/eventyayEvent' | ||
import StandardButton from '@/components/Common/StandardButton.vue' | ||
import { useRouter } from 'vue-router' | ||
const loadingStore = useLoadingStore() | ||
|
||
const apiToken = ref('') | ||
const organiser = ref('') | ||
const url = ref('') | ||
const eventyayEventStore = useEventyayEventStore() | ||
const selectedEvent = ref(null) | ||
const router = useRouter() | ||
const { events, loading, error, fetchEvents } = eventyayEventStore | ||
|
||
watchEffect(() => { | ||
apiToken.value = localStorage.getItem('api_token') | ||
organiser.value = localStorage.getItem('organizer') | ||
url.value = localStorage.getItem('url') | ||
|
||
if (apiToken.value && organiser.value && url.value) { | ||
fetchEvents(url.value, apiToken.value, organiser.value) | ||
loadingStore.contentLoaded() | ||
} | ||
}) | ||
|
||
const submitForm = () => { | ||
if (selectedEvent.value) { | ||
localStorage.setItem('selectedEvent', selectedEvent.value) | ||
router.push({ name: 'eventyaycheckin' }) | ||
console.log('Selected event:', selectedEvent.value) | ||
} else { | ||
console.error('Please select an event.') | ||
Sak1012 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
</script> | ||
<template> | ||
<div class="-mt-16 flex h-screen flex-col justify-center"> | ||
<div v-if="loading">Loading events...</div> | ||
<div v-if="error" class="text-danger">{{ error }}</div> | ||
<form v-if="events.length" @submit.prevent="submitForm"> | ||
Sak1012 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
<div v-for="event in events" :key="event.slug" class="mb-2"> | ||
<label> | ||
<input type="radio" :value="event.slug" v-model="selectedEvent" /> | ||
{{ event.name.en }} | ||
</label> | ||
</div> | ||
<div> | ||
<StandardButton | ||
:type="'submit'" | ||
:text="'Select Event'" | ||
class="btn-primary mt-6 w-full justify-center" | ||
/> | ||
</div> | ||
</form> | ||
<div v-if="!loading && !events.length && !error"> | ||
No events available | ||
<StandardButton | ||
:text="'Refresh'" | ||
class="btn-primary mt-6 w-full justify-center" | ||
@click="fetchEvents(url.value, apiToken.value, organiser.value)" | ||
/> | ||
</div> | ||
</div> | ||
</template> |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -13,12 +13,25 @@ const userStore = useUserStore() | |||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
const email = ref('') | ||||||||||||||||||||||||||||||||
const password = ref('') | ||||||||||||||||||||||||||||||||
const server = ref('') | ||||||||||||||||||||||||||||||||
const showError = ref(false) | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
const showServerError = ref(false) | ||||||||||||||||||||||||||||||||
const errmessage = ref('') | ||||||||||||||||||||||||||||||||
// router | ||||||||||||||||||||||||||||||||
const router = useRouter() | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
async function submitLogin() { | ||||||||||||||||||||||||||||||||
console.log(server.value) | ||||||||||||||||||||||||||||||||
Sak1012 marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: Remove console.log statements Consider removing the console.log statements used for debugging purposes before merging the code to the main branch.
Suggested change
|
||||||||||||||||||||||||||||||||
if (server.value === '' || server.value === 'Select a Server') { | ||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: Consider using a constant for the default server value Using a constant for the default server value ('Select a Server') can help avoid potential typos and make the code easier to maintain.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: Use a constant for 'Select a Server' Consider defining 'Select a Server' as a constant to avoid potential typos and make the code more maintainable.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please define constants to compare There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Absolutely, defining constants for strings like 'Select a Server' is a great practice. It helps prevent typos and makes the code more readable and maintainable. You can define the constant at the top of your script or in a separate configuration file if it's used across multiple components. Here's how you can implement it: const SELECT_A_SERVER = 'Select a Server';
if (server.value === '' || server.value === SELECT_A_SERVER) {
// Handle the error case
} This way, if you ever need to change the placeholder text, you only have to update it in one place. Let me know if you need further assistance! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done, I have fixed it in the recent commit. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great to hear that you've implemented the change! Using constants for strings is definitely a good practice for maintaining clean and error-free code. If you have any more questions or need further assistance with anything else in the PR, feel free to ask. Keep up the good work! |
||||||||||||||||||||||||||||||||
showServerError.value = true | ||||||||||||||||||||||||||||||||
return | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
if (server.value === 'Eventyay') { | ||||||||||||||||||||||||||||||||
errmessage.value = 'Please Register a Device for Eventyay' | ||||||||||||||||||||||||||||||||
showServerError.value = true | ||||||||||||||||||||||||||||||||
return | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
showServerError.value = false | ||||||||||||||||||||||||||||||||
loadingStore.contentLoading() | ||||||||||||||||||||||||||||||||
showError.value = false | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
|
@@ -42,6 +55,24 @@ async function submitLogin() { | |||||||||||||||||||||||||||||||
loadingStore.contentLoaded() | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
function registerDevice() { | ||||||||||||||||||||||||||||||||
console.log(server.value) | ||||||||||||||||||||||||||||||||
if (server.value === '' || server.value === 'Select a Server') { | ||||||||||||||||||||||||||||||||
errmessage.value = 'Please select a server first' | ||||||||||||||||||||||||||||||||
showServerError.value = true | ||||||||||||||||||||||||||||||||
return | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
if (server.value === 'Open-Event') { | ||||||||||||||||||||||||||||||||
errmessage.value = 'Please Login with credentials for Open-Event' | ||||||||||||||||||||||||||||||||
showServerError.value = true | ||||||||||||||||||||||||||||||||
return | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
showServerError.value = false | ||||||||||||||||||||||||||||||||
router.push({ | ||||||||||||||||||||||||||||||||
name: 'device' | ||||||||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
onMounted(() => { | ||||||||||||||||||||||||||||||||
if (authStore.isAuthenticated) { | ||||||||||||||||||||||||||||||||
router.push({ | ||||||||||||||||||||||||||||||||
|
@@ -88,6 +119,15 @@ onMounted(() => { | |||||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
<div> | ||||||||||||||||||||||||||||||||
<label for="select">Select a Server</label> | ||||||||||||||||||||||||||||||||
<select id="select" v-model="server" class="mt-2 block w-full"> | ||||||||||||||||||||||||||||||||
<option>Open-Event</option> | ||||||||||||||||||||||||||||||||
<option>Eventyay</option> | ||||||||||||||||||||||||||||||||
<option>Testing</option> | ||||||||||||||||||||||||||||||||
</select> | ||||||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
<div> | ||||||||||||||||||||||||||||||||
<StandardButton | ||||||||||||||||||||||||||||||||
:type="'submit'" | ||||||||||||||||||||||||||||||||
|
@@ -101,13 +141,24 @@ onMounted(() => { | |||||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||||||
</form> | ||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||
<p class="mt-10 text-center text-sm"> | ||||||||||||||||||||||||||||||||
<p class="mt-5 text-center text-sm"> | ||||||||||||||||||||||||||||||||
<span>Forgot password?</span> | ||||||||||||||||||||||||||||||||
{{ ' ' }} | ||||||||||||||||||||||||||||||||
<a href="https://eventyay.com/reset-password" class="font-medium leading-6 text-primary" | ||||||||||||||||||||||||||||||||
>Click here to reset password</a | ||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||
</p> | ||||||||||||||||||||||||||||||||
<StandardButton | ||||||||||||||||||||||||||||||||
:type="'button'" | ||||||||||||||||||||||||||||||||
Sak1012 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||
:text="'Register-Device'" | ||||||||||||||||||||||||||||||||
:disabled="false" | ||||||||||||||||||||||||||||||||
class="btn-primary mt-6 w-full justify-center" | ||||||||||||||||||||||||||||||||
@click="registerDevice" | ||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||
</StandardButton> | ||||||||||||||||||||||||||||||||
Sak1012 marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: Button text should be a prop Consider passing the button text as a prop to the StandardButton component for better reusability and consistency.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you are passing a static string ( Just pass as normal HTML attribute like this: <StandardButton text='Register-Device' ... /> There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great point, @hongquan! If the button text is static and won't change, using a regular HTML attribute is indeed more straightforward and cleaner. However, if there's a possibility that the button text might need to be dynamic or localized in the future, passing it as a prop could be beneficial for flexibility. It really depends on the expected use case. If you foresee any changes or need for localization, consider using a prop; otherwise, your suggestion is perfectly valid for a static text. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As this was the convention followed everywhere else where There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the convention in your codebase is to use the binding syntax for the However, if you and your team decide that using a regular HTML attribute for static text is more appropriate and aligns with your coding standards, you can certainly make that change. Consistency is key, so whichever approach you choose, it would be beneficial to apply it uniformly across your project. If you're unsure, it might be worth discussing with your team to see if there's a preference or if there's a plan to make the button text dynamic in the future. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is not convention, previous people simply don't understand VueJS well enough. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It sounds like there's a bit of a misunderstanding about the use of VueJS syntax in your codebase. If the current practice is to use the binding syntax for static strings, it might be due to a lack of understanding rather than a deliberate convention. Given this, it could be a good opportunity to align on best practices with your team. Using a regular HTML attribute for static text is more straightforward and should be preferred unless there's a specific reason to use the binding syntax, such as future plans for dynamic content or localization. If you decide to switch to using regular HTML attributes for static text, it might be helpful to update the existing code for consistency. This could also be a chance to document this as a coding standard for your team to follow moving forward. If you need further guidance, consider discussing this with your team or a lead developer to ensure everyone is on the same page. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is how the button is defined <script setup>
const props = defineProps({
type: {
type: String,
default: 'button'
},
text: {
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
},
icon: {
type: Function,
default: () => null
},
iconAfter: {
type: Function,
default: () => null
}
})
</script>
<template>
<button :type="type" :disabled="disabled" class="inline-flex items-center">
<component :is="icon" v-if="icon" :class="[text !== '' ? 'mr-1 h-5' : 'h-5']" />
<span>{{ text }}</span>
<component :is="iconAfter" v-if="iconAfter" :class="[text !== '' ? 'ml-1 h-5' : 'h-5']" />
</button>
</template> Hence I'm passing it as a prop There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know that it is a prop, see my previous comment:
Being a "prop", it doesn't mean that you always have to use Vue syntax when passing a value to it. |
||||||||||||||||||||||||||||||||
<div v-if="showServerError" class="mt-5"> | ||||||||||||||||||||||||||||||||
<p class="text-center text-sm text-danger">{{ errmessage }}</p> | ||||||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||||||
</template> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<script setup> | ||
import QRCamera from '@/components/Common/QRCamera.vue' | ||
import { useLoadingStore } from '@/stores/loading' | ||
import StandardButton from '@/components/Common/StandardButton.vue' | ||
import { useProcessDeviceStore } from '@/stores/processDevice' | ||
const loadingStore = useLoadingStore() | ||
loadingStore.contentLoaded() | ||
|
||
const processDeviceStore = useProcessDeviceStore() | ||
|
||
async function registerDevice() { | ||
const auth_token = document.getElementById('auth_token').value | ||
const payload = { handshake_version: 1, url: 'http://localhost', token: auth_token } | ||
await processDeviceStore.authDevice(JSON.stringify(payload)) | ||
} | ||
</script> | ||
|
||
<template> | ||
<div | ||
class="-mt-16 grid h-screen w-full grid-cols-1 place-items-center items-center justify-center align-middle" | ||
> | ||
<QRCamera :qr-type="'device'" :scan-type="'Device Registration'" /> | ||
<div> | ||
<input type="text" id="auth_token" placeholder="Device Key" class="input" /> | ||
<StandardButton | ||
:text="'Register Device'" | ||
class="btn-primary mt-6 w-full justify-center" | ||
@click="registerDevice()" | ||
/> | ||
</div> | ||
</div> | ||
</template> |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,34 @@ | ||||||
import { mande } from 'mande' | ||||||
import { defineStore } from 'pinia' | ||||||
import { ref } from 'vue' | ||||||
|
||||||
export const useEventyayEventStore = defineStore('eventyayEvent', () => { | ||||||
const events = ref([]) | ||||||
const loading = ref(false) | ||||||
const error = ref(null) | ||||||
|
||||||
async function fetchEvents(url, apiToken, organizer) { | ||||||
loading.value = false | ||||||
error.value = null | ||||||
|
||||||
try { | ||||||
const api = mande(url, { headers: { Authorization: `Device ${apiToken}` } }) | ||||||
console.log(`/api/v1/organizers/${organizer}/events/`) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (performance): Remove console.log statements Leaving console.log statements in production code can lead to performance issues and potential information leakage. Consider removing or replacing them with proper logging mechanisms. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: Remove console.log statements Consider removing the console.log statements used for debugging purposes before merging the code to the main branch.
Suggested change
|
||||||
const response = await api.get(`/api/v1/organizers/${organizer}/events/`) | ||||||
console.log('Hello', response) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (performance): Remove console.log statements Leaving console.log statements in production code can lead to performance issues and potential information leakage. Consider removing or replacing them with proper logging mechanisms. |
||||||
events.value = response.results | ||||||
loading.value = true | ||||||
} catch (err) { | ||||||
error.value = err.message | ||||||
} finally { | ||||||
loading.value = false | ||||||
} | ||||||
} | ||||||
|
||||||
return { | ||||||
events, | ||||||
loading, | ||||||
error, | ||||||
fetchEvents | ||||||
} | ||||||
}) |
Uh oh!
There was an error while loading. Please reload this page.