fix six app bugs

This commit is contained in:
2026-04-16 07:55:13 -06:00
parent 77793071ce
commit a1ec3e728b
7 changed files with 21 additions and 13 deletions

View File

@@ -56,7 +56,8 @@ public class AiChatController {
List<Pet> userPets; List<Pet> userPets;
try { try {
userPets = petRepository.findAllByOwner_IdOrderByPetNameAsc(user.getId()); userPets = petRepository.findAllByOwner_IdAndPetStatusInOrderByPetNameAsc(
user.getId(), List.of("Adopted", "Owned"));
} }
catch (Exception e) { catch (Exception e) {

View File

@@ -53,5 +53,8 @@ public interface AppointmentRepository extends JpaRepository<Appointment, Long>
List<Appointment> findByPet_Id(Long petId); List<Appointment> findByPet_Id(Long petId);
@Query("SELECT a FROM Appointment a JOIN FETCH a.service WHERE a.pet.petId = :petId AND a.appointmentDate = :date AND LOWER(a.appointmentStatus) NOT IN ('cancelled', 'missed')")
List<Appointment> findByPetIdAndAppointmentDate(@Param("petId") Long petId, @Param("date") LocalDate date);
List<Appointment> findByAppointmentDateAndAppointmentStatusIgnoreCase(LocalDate date, String status); List<Appointment> findByAppointmentDateAndAppointmentStatusIgnoreCase(LocalDate date, String status);
} }

View File

@@ -37,6 +37,7 @@ public interface PetRepository extends JpaRepository<Pet, Long> {
List<Pet> findAdoptablePetsByStore(@Param("storeId") Long storeId); List<Pet> findAdoptablePetsByStore(@Param("storeId") Long storeId);
List<Pet> findAllByOwner_IdOrderByPetNameAsc(Long ownerId); List<Pet> findAllByOwner_IdOrderByPetNameAsc(Long ownerId);
List<Pet> findAllByOwner_IdAndPetStatusInOrderByPetNameAsc(Long ownerId, List<String> statuses);
Optional<Pet> findByIdAndOwner_Id(Long id, Long ownerId); Optional<Pet> findByIdAndOwner_Id(Long id, Long ownerId);
@Lock(LockModeType.PESSIMISTIC_WRITE) @Lock(LockModeType.PESSIMISTIC_WRITE)

View File

@@ -132,6 +132,7 @@ public class AppointmentService {
validateStoreAccess(store.getStoreId(), authenticatedUser); validateStoreAccess(store.getStoreId(), authenticatedUser);
validatePetServiceCompatibility(pet, service); validatePetServiceCompatibility(pet, service);
validateAvailability(employee, service, request.getAppointmentDate(), request.getAppointmentTime(), null); validateAvailability(employee, service, request.getAppointmentDate(), request.getAppointmentTime(), null);
validatePetAvailability(pet, service, request.getAppointmentDate(), request.getAppointmentTime(), null);
Appointment appointment = new Appointment(); Appointment appointment = new Appointment();
appointment.setCustomer(customer); appointment.setCustomer(customer);
@@ -172,6 +173,7 @@ public class AppointmentService {
validateStoreAccess(store.getStoreId(), authenticatedUser); validateStoreAccess(store.getStoreId(), authenticatedUser);
validatePetServiceCompatibility(pet, service); validatePetServiceCompatibility(pet, service);
validateAvailability(employee, service, request.getAppointmentDate(), request.getAppointmentTime(), id); validateAvailability(employee, service, request.getAppointmentDate(), request.getAppointmentTime(), id);
validatePetAvailability(pet, service, request.getAppointmentDate(), request.getAppointmentTime(), id);
appointment.setCustomer(customer); appointment.setCustomer(customer);
appointment.setStore(store); appointment.setStore(store);
@@ -387,6 +389,15 @@ public class AppointmentService {
return true; return true;
} }
private void validatePetAvailability(Pet pet, com.petshop.backend.entity.Service service, LocalDate date, LocalTime time, Long appointmentIdToIgnore) {
if (pet == null) return;
List<Appointment> existingAppointments = appointmentRepository
.findByPetIdAndAppointmentDate(pet.getPetId(), date);
if (!isSlotAvailable(existingAppointments, service, time, appointmentIdToIgnore)) {
throw new IllegalArgumentException("This pet already has an appointment during this time slot");
}
}
private void validateSpeciesServiceCompatibility(Pet pet, com.petshop.backend.entity.Service service) { private void validateSpeciesServiceCompatibility(Pet pet, com.petshop.backend.entity.Service service) {
if (pet == null || service == null) return; if (pet == null || service == null) return;
String species = pet.getPetSpecies(); String species = pet.getPetSpecies();

View File

@@ -45,9 +45,9 @@ function AiChatPage() {
lastScrolledIdRef.current = lastMsg.id; lastScrolledIdRef.current = lastMsg.id;
const area = messagesAreaRef.current; const area = messagesAreaRef.current;
if (!area) return; if (!area) return;
const nearBottom = area.scrollHeight - area.scrollTop - area.clientHeight < 150; const nearBottom = area.scrollHeight - area.scrollTop - area.clientHeight < 80;
if (nearBottom) { if (nearBottom) {
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); area.scrollTop = area.scrollHeight;
} }
}, [messages]); }, [messages]);
@@ -347,11 +347,6 @@ function AiChatPage() {
if (pollRef.current) clearInterval(pollRef.current); if (pollRef.current) clearInterval(pollRef.current);
setMessages([]); setMessages([]);
setError(null); setError(null);
setLoadingConv(true);
await fetchConversation(convId);
await fetchMessages(convId);
setLoadingConv(false);
startPolling(convId);
router.replace(`/ai-chat?id=${convId}`, { scroll: false }); router.replace(`/ai-chat?id=${convId}`, { scroll: false });
} }

View File

@@ -352,11 +352,6 @@ function ChatPage() {
if (pollRef.current) clearInterval(pollRef.current); if (pollRef.current) clearInterval(pollRef.current);
setMessages([]); setMessages([]);
setError(null); setError(null);
setLoadingConv(true);
await fetchConversation(convId);
await fetchMessages(convId);
setLoadingConv(false);
startPolling(convId);
router.replace(`/chat?id=${convId}`, { scroll: false }); router.replace(`/chat?id=${convId}`, { scroll: false });
} }

View File

@@ -58,6 +58,8 @@ body {
align-items: center; align-items: center;
gap: 1.25rem; gap: 1.25rem;
justify-content: center; justify-content: center;
min-width: 0;
overflow: hidden;
} }
/* Indivdual Link Styles */ /* Indivdual Link Styles */