132 lines
3.7 KiB
Vue
132 lines
3.7 KiB
Vue
|
<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>
|