Merge web-v1 into main #299
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user