Merge web-v1 into main #299

Merged
RecentRunner merged 8 commits from web-v1 into main 2026-04-14 23:29:51 -06:00
4 changed files with 45 additions and 3 deletions
Showing only changes of commit c5448b95c9 - Show all commits

View File

@@ -1,5 +1,7 @@
package com.petshop.backend.dto.pet;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
@@ -16,6 +18,10 @@ public class MyPetRequest {
@Size(max = 50, message = "Breed must not exceed 50 characters")
private String breed;
@Min(value = 0, message = "Age must be 0 or greater")
@Max(value = 100, message = "Age must not exceed 100")
private Integer petAge;
public String getPetName() {
return petName;
}
@@ -39,4 +45,12 @@ public class MyPetRequest {
public void setBreed(String breed) {
this.breed = breed;
}
public Integer getPetAge() {
return petAge;
}
public void setPetAge(Integer petAge) {
this.petAge = petAge;
}
}

View File

@@ -6,17 +6,19 @@ public class MyPetResponse {
private String petName;
private String species;
private String breed;
private Integer petAge;
private String imageUrl;
private String petStatus;
public MyPetResponse() {
}
public MyPetResponse(Long customerPetId, String petName, String species, String breed, String imageUrl, String petStatus) {
public MyPetResponse(Long customerPetId, String petName, String species, String breed, Integer petAge, String imageUrl, String petStatus) {
this.customerPetId = customerPetId;
this.petName = petName;
this.species = species;
this.breed = breed;
this.petAge = petAge;
this.imageUrl = imageUrl;
this.petStatus = petStatus;
}
@@ -53,6 +55,14 @@ public class MyPetResponse {
this.breed = breed;
}
public Integer getPetAge() {
return petAge;
}
public void setPetAge(Integer petAge) {
this.petAge = petAge;
}
public String getImageUrl() {
return imageUrl;
}

View File

@@ -357,6 +357,7 @@ public class PetService {
pet.getPetName(),
pet.getPetSpecies(),
pet.getPetBreed(),
pet.getPetAge(),
pet.getImageUrl() != null && !pet.getImageUrl().isBlank() ? "/api/v1/pets/" + pet.getPetId() + "/image" : null,
pet.getPetStatus()
);
@@ -366,7 +367,7 @@ public class PetService {
pet.setPetName(request.getPetName().trim());
pet.setPetSpecies(request.getSpecies().trim());
pet.setPetBreed(normalizeOptional(request.getBreed()));
pet.setPetAge(null);
pet.setPetAge(request.getPetAge());
pet.setPetPrice(null);
}

View File

@@ -30,6 +30,7 @@ export default function ProfilePage() {
const [petName, setPetName] = useState("");
const [species, setSpecies] = useState("");
const [breed, setBreed] = useState("");
const [petAge, setPetAge] = useState("1");
const [submitting, setSubmitting] = useState(false);
const [petError, setPetError] = useState(null);
const [profileForm, setProfileForm] = useState({ fullName: "", email: "", phone: "" });
@@ -230,6 +231,7 @@ if (user?.role === "CUSTOMER" || user?.role === "ADMIN") {
setPetName("");
setSpecies("");
setBreed("");
setPetAge("1");
setPetError(null);
setShowForm(true);
}
@@ -239,6 +241,7 @@ if (user?.role === "CUSTOMER" || user?.role === "ADMIN") {
setPetName(pet.petName);
setSpecies(pet.species);
setBreed(pet.breed || "");
setPetAge(pet.petAge != null ? String(pet.petAge) : "1");
setPetError(null);
setShowForm(true);
}
@@ -265,7 +268,7 @@ if (user?.role === "CUSTOMER" || user?.role === "ADMIN") {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({ petName, species, breed: breed || null }),
body: JSON.stringify({ petName, species, breed: breed || null, petAge: Number(petAge) }),
});
if (!res.ok) {
@@ -485,6 +488,19 @@ if (user?.role === "CUSTOMER" || user?.role === "ADMIN") {
))}
</select>
</label>
<label className="appt-label">
Age (years)
<select
className="appt-select"
value={petAge}
onChange={(e) => setPetAge(e.target.value)}
required
>
{Array.from({ length: 20 }, (_, i) => i + 1).map((n) => (
<option key={n} value={n}>{n}</option>
))}
</select>
</label>
<div className="profile-pet-form-actions">
<button type="submit" className="appt-submit-btn" disabled={submitting}>
{submitting ? "Saving..." : editingPet ? "Save Changes" : "Add Pet"}
@@ -531,6 +547,7 @@ if (user?.role === "CUSTOMER" || user?.role === "ADMIN") {
<span className="profile-pet-card-name">{pet.petName}</span>
<span className="profile-pet-card-detail">{pet.species}</span>
{pet.breed && <span className="profile-pet-card-detail">{pet.breed}</span>}
{pet.petAge != null && <span className="profile-pet-card-detail">Age: {pet.petAge === 0 ? "< 1 yr" : `${pet.petAge} yr${pet.petAge !== 1 ? "s" : ""}`}</span>}
</div>
<div className="profile-pet-card-actions">
<button type="button" className="profile-pet-edit-btn" onClick={() => openEditForm(pet)}>Edit</button>