initial commit
All checks were successful
Build and Publish / Build Yale Access Backend (push) Successful in 28s
Build and Publish / Build Yale Access Frontend (push) Successful in 47s
Build and Publish / Push Yale Access Backend Docker Image (push) Successful in 9s
Build and Publish / Push Yale Access Frontend Docker Image (push) Successful in 10s
All checks were successful
Build and Publish / Build Yale Access Backend (push) Successful in 28s
Build and Publish / Build Yale Access Frontend (push) Successful in 47s
Build and Publish / Push Yale Access Backend Docker Image (push) Successful in 9s
Build and Publish / Push Yale Access Frontend Docker Image (push) Successful in 10s
This commit is contained in:
132
packages/frontend/components/PeopleList.vue
Normal file
132
packages/frontend/components/PeopleList.vue
Normal file
@@ -0,0 +1,132 @@
|
||||
<script setup lang="ts">
|
||||
import { type Person } from '@/types/yale';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import type { ApiResponse } from '~/types/api-response';
|
||||
|
||||
const people = ref([] as Person[]);
|
||||
const person = ref({ id: 0, name: '', phoneNumber: '' } as Person);
|
||||
const loading = ref(true);
|
||||
const runtimeConfig = useRuntimeConfig();
|
||||
|
||||
const addModal = ref(false);
|
||||
|
||||
// When the component is mounted, load the people
|
||||
onMounted(async () => {
|
||||
await loadPeople();
|
||||
loading.value = false;
|
||||
});
|
||||
|
||||
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
|
||||
people.value = apiResponse.data || [];
|
||||
}
|
||||
|
||||
const handleAddPerson = () => {
|
||||
addModal.value = true;
|
||||
}
|
||||
|
||||
const handleSavePerson = async () => {
|
||||
// Validate the person fields
|
||||
if (!person.value.name || !person.value.phoneNumber) {
|
||||
alert('Name and phone number are required');
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the loading status
|
||||
loading.value = true;
|
||||
|
||||
// Send a request to the api to save the person
|
||||
const response = await fetch(`${runtimeConfig.public.apiBaseUrl}/api/People`, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(person.value)
|
||||
});
|
||||
|
||||
// Parse the response
|
||||
const apiResponse = await response.json() as ApiResponse<Person>;
|
||||
|
||||
if (apiResponse.success) {
|
||||
// Add the new person to the list
|
||||
people.value.push(apiResponse.data!);
|
||||
addModal.value = false;
|
||||
} else {
|
||||
alert(apiResponse.error ?? 'An error occurred');
|
||||
}
|
||||
|
||||
// Close the modal and reset the person
|
||||
loading.value = false;
|
||||
person.value = { id: 0, name: '', phoneNumber: '' };
|
||||
|
||||
// Set the loading status
|
||||
loading.value = false;
|
||||
}
|
||||
|
||||
const handleDeletePerson = async (id: number) => {
|
||||
// Set the loading status
|
||||
loading.value = true;
|
||||
|
||||
// Send a request to the api to delete the person
|
||||
const response = await fetch(`${runtimeConfig.public.apiBaseUrl}/api/People/${id}`, {
|
||||
method: 'DELETE',
|
||||
credentials: 'include'
|
||||
});
|
||||
|
||||
// Parse the response
|
||||
const apiResponse = await response.json() as ApiResponse<Person>;
|
||||
|
||||
if (apiResponse.success) {
|
||||
// Remove the person from the list
|
||||
const index = people.value.findIndex(x => x.id === id);
|
||||
people.value.splice(index, 1);
|
||||
} else {
|
||||
alert(apiResponse.error ?? 'An error occurred');
|
||||
}
|
||||
|
||||
// Set the loading status
|
||||
loading.value = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- Handle loading state -->
|
||||
<div v-if="loading">Loading...</div>
|
||||
<template v-else>
|
||||
<div class="text-end my-2">
|
||||
<YaleButton type="button" @click="handleAddPerson">Add Person</YaleButton>
|
||||
</div>
|
||||
<table class="w-full text-left">
|
||||
<tr>
|
||||
<th scope="col">Person ID</th>
|
||||
<th scope="col">Name</th>
|
||||
<th scope="col">Phone Number</th>
|
||||
<th scope="col">Actions</th>
|
||||
</tr>
|
||||
<PeopleListRow v-for="person in people" :key="person.id" :person="person" @delete-person="handleDeletePerson" />
|
||||
</table>
|
||||
</template>
|
||||
|
||||
<!-- Add modal -->
|
||||
<Modal v-if="addModal" @close="addModal = false">
|
||||
<template #title>
|
||||
Add Person
|
||||
</template>
|
||||
<template #default>
|
||||
<div class="flex flex-col space-y-2">
|
||||
<YaleFormInput v-model="person.name" type="text" placeholder="Name" class="block w-full" />
|
||||
<YaleFormInput v-model="person.phoneNumber" type="text" placeholder="Phone" class="block w-full" />
|
||||
<div class="flex justify-end">
|
||||
<YaleButton type="button" @click="handleSavePerson">Save</YaleButton>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
Reference in New Issue
Block a user