yale-user-access/packages/frontend/components/UserCodeList.vue

300 lines
8.9 KiB
Vue
Raw Normal View History

2025-01-10 08:37:18 +11:00
<script setup lang='ts'>
import type { ApiResponse } from '@/types/api-response';
import UserCodeListRow from './UserCodeListRow.vue';
import { onMounted, ref } from 'vue';
import { UserCodeStatus, type Person, type YaleUserCode } from '@/types/yale';
const userCodes = ref([] as YaleUserCode[]);
const userCode = ref({} as YaleUserCode);
const people = ref([] as { label: string, value: string }[]);
const personNumber = ref('');
const loading = ref(true);
const runtimeConfig = useRuntimeConfig();
// Modals
const showModal = ref(false);
const editModal = ref(false);
const clearModal = ref(false);
const sendModal = ref(false);
// Form Fields
const newCode = ref('');
const newCodeError = ref('');
// When the component is mounted, load the user codes
onMounted(async () => {
// Load the user codes and set the loading status when complete
await loadUserCodes();
await loadPeople();
loading.value = false;
});
const loadUserCodes = async () => {
// Send a request to the api to get the user codes
const response = await fetch(`${runtimeConfig.public.apiBaseUrl}/api/Yale/codes`, { credentials: 'include' });
// Parse the response
const apiResponse = await response.json() as ApiResponse<YaleUserCode[]>;
// Set the user codes by id
userCodes.value = apiResponse.data?.sort((a, b) => a.id - b.id) || [];
}
const loadPeople = async () => {
// Send a request to the api to get the people
const response = await fetch(`${runtimeConfig.public.apiBaseUrl}/api/People`, { credentials: 'include' });
// Parse the response
const apiResponse = await response.json() as ApiResponse<Person[]>;
// Set the people for drop down
people.value = apiResponse.data?.map(x => ({ label: x.name, value: x.phoneNumber })) || [];
}
const confirmUpdateCode = async (id: number, code: string) => {
// Reset the error
newCodeError.value = '';
// Validate the new code first
if (!/^\d{4,6}$/.test(code)) {
newCodeError.value = 'Code must be 4, 5 or 6 digits long';
return;
}
// Set the loading status
loading.value = true;
// Send a request to the api, the body will just be the new code
const response = await fetch(`${runtimeConfig.public.apiBaseUrl}/api/Yale/code/${id}`, {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json'
},
body: `"${code}"`
});
// Parse the result
const apiResponse = await response.json() as ApiResponse<boolean>;
if (apiResponse.success) {
// If the response was successful update the code in the list
const index = userCodes.value.findIndex(x => x.id === id);
userCodes.value[index].code = code;
userCodes.value[index].status = UserCodeStatus.ENABLED;
} else {
// Otherwise display an error to the user.
alert(apiResponse.error ?? 'Unknown error');
}
// Reset the new code
newCode.value = '';
// Close the edit modal
editModal.value = false;
// Set the loading status
loading.value = false;
}
const confirmClearCode = async (id: number) => {
// Set the loading status
loading.value = true;
// Send a request to the api
const response = await fetch(`${runtimeConfig.public.apiBaseUrl}/api/Yale/code/${id}/status`, {
method: 'POST',
credentials: 'include'
});
// Parse the response
const apiResponse = await response.json() as ApiResponse<boolean>;
if (apiResponse.success) {
// If the response was successful set the code to available in the list
const index = userCodes.value.findIndex(x => x.id === id);
userCodes.value[index].code = '';
userCodes.value[index].status = UserCodeStatus.AVAILABLE;
} else {
// Otherwise display an error to the user.
alert(apiResponse.error ?? 'Unknown error');
}
// Close the clear modal
clearModal.value = false;
// Set the loading status
loading.value = false;
}
const handleShowCode = (id: number) => {
// Get the user code to show
const code = userCodes.value.find(x => x.id === id);
// If the code is not found then show an error to the user
if (!code) {
alert('Code not found');
return;
}
// Set the user code to show
userCode.value = code;
// Show the show-modal
showModal.value = true;
}
const handleUpdateCode = (id: number) => {
// Get the user code to update
const code = userCodes.value.find(x => x.id === id);
// If the code is not found then show an error to the user
if (!code) {
alert('Code not found');
return;
}
// Set the user code to update
userCode.value = code;
// Show the edit-modal
editModal.value = true;
}
const handleClearCode = (id: number) => {
// Get the user code to clear
const code = userCodes.value.find(x => x.id === id);
// If the code is not found then show an error to the user
if (!code) {
alert('Code not found');
return;
}
// Set the user code to clear
userCode.value = code;
// Show the clear-modal
clearModal.value = true;
}
const handleSendCode = (id: number) => {
// Get the user code to send
const code = userCodes.value.find(x => x.id === id);
// If the code is not found then show an error to the user
if (!code) {
alert('Code not found');
return;
}
// Set the user code
userCode.value = code;
// Show the send modal
sendModal.value = true;
}
const confirmSendCode = async (id: number) => {
// Set the loading status
loading.value = true;
if (!personNumber.value) {
alert('Please select a person to send the code to');
loading.value = false;
return;
}
// Send a request to the api to send the code
const response = await fetch(`${runtimeConfig.public.apiBaseUrl}/api/Yale/code/${id}/send`, {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json'
},
body: `"${personNumber.value}"`
});
// Parse the response
const apiResponse = await response.json() as ApiResponse<boolean>;
if (apiResponse.success) {
alert('Code sent successfully');
} else {
alert(apiResponse.error ?? 'Unknown error');
}
// Close the clear modal
sendModal.value = false;
// Clear the person number and user code
personNumber.value = '';
userCode.value = {} as YaleUserCode;
// Set the loading status
loading.value = false;
}
</script>
<template>
<!-- Handle loading state -->
<div v-if="loading">Loading...</div>
<table v-else class="w-full text-left">
<tr>
<th scope="col">Code ID</th>
<th scope="col">Status</th>
<th scope="col">Actions</th>
</tr>
<UserCodeListRow v-for="userCode in userCodes" :key="userCode.id" :user-code="userCode"
@update-code="handleUpdateCode" @clear-code="handleClearCode" @show-code="handleShowCode"
@send-code="handleSendCode" />
</table>
<!-- Show modal -->
<Modal v-if="showModal" @close="showModal = false">
<template #title>
User Code # {{ userCode.id }}
</template>
<template #default>
Code: {{ userCode.code }}
</template>
</Modal>
<!-- Edit modal -->
<Modal v-if="editModal" @close="editModal = false">
<template #title>
Edit User Code # {{ userCode.id }}
</template>
<template #default>
<YaleFormInput v-model="newCode" type="text" placeholder="New Code" class="block w-full" />
<p class="text-red-600 mt-3" v-if="newCodeError">{{ newCodeError }}</p>
<YaleButton @click="confirmUpdateCode(userCode.id, newCode)" class="w-full mt-3">Update Code</YaleButton>
</template>
<template #footer v-if="userCode.isHome">
<p class="text-red-600 mt-3">You are about to edit the home code, are you sure?</p>
</template>
</Modal>
<!-- Clear modal -->
<Modal v-if="clearModal" @close="clearModal = false">
<template #title>
Delete User Code # {{ userCode.id }}
</template>
<template #default>
<p>Are you sure you want to delete this code?</p>
<YaleButton @click="confirmClearCode(userCode.id)" class="w-full mt-3">Delete Code</YaleButton>
</template>
</Modal>
<!-- Send modal -->
<Modal v-if="sendModal" @close="sendModal = false">
<template #title>
Send User Code # {{ userCode.id }}
</template>
<template #default>
<YaleFormSelect v-model="personNumber" :options="people" class="block w-full"
placeholder="Select a Person" />
<YaleButton @click="confirmSendCode(userCode.id)" class="w-full mt-3">Send Code</YaleButton>
</template>
</Modal>
</template>