Profile image works, editing profile works, now uses first/last name
This commit is contained in:
@@ -70,7 +70,8 @@ public class AuthController {
|
|||||||
public ResponseEntity<?> register(@Valid @RequestBody RegisterRequest request) {
|
public ResponseEntity<?> register(@Valid @RequestBody RegisterRequest request) {
|
||||||
String username = trimToNull(request.getUsername());
|
String username = trimToNull(request.getUsername());
|
||||||
String email = trimToNull(request.getEmail());
|
String email = trimToNull(request.getEmail());
|
||||||
NameParts nameParts = splitFullName(request.getFullName());
|
String firstName = trimToNull(request.getFirstName());
|
||||||
|
String lastName = trimToNull(request.getLastName());
|
||||||
String phone = normalizePhone(request.getPhone());
|
String phone = normalizePhone(request.getPhone());
|
||||||
|
|
||||||
if (userRepository.findByUsername(username).isPresent()) {
|
if (userRepository.findByUsername(username).isPresent()) {
|
||||||
@@ -98,9 +99,9 @@ public class AuthController {
|
|||||||
user.setUsername(username);
|
user.setUsername(username);
|
||||||
user.setPassword(passwordEncoder.encode(request.getPassword()));
|
user.setPassword(passwordEncoder.encode(request.getPassword()));
|
||||||
user.setEmail(email);
|
user.setEmail(email);
|
||||||
user.setFirstName(nameParts.firstName());
|
user.setFirstName(firstName);
|
||||||
user.setLastName(nameParts.lastName());
|
user.setLastName(lastName);
|
||||||
user.setFullName(nameParts.fullName());
|
user.setFullName(joinFullName(firstName, lastName));
|
||||||
user.setPhone(phone);
|
user.setPhone(phone);
|
||||||
user.setRole(User.Role.CUSTOMER);
|
user.setRole(User.Role.CUSTOMER);
|
||||||
user.setActive(true);
|
user.setActive(true);
|
||||||
@@ -203,11 +204,16 @@ public class AuthController {
|
|||||||
user.setEmail(email);
|
user.setEmail(email);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.getFullName() != null) {
|
String firstName = trimToNull(request.getFirstName());
|
||||||
NameParts nameParts = splitFullName(request.getFullName());
|
if (firstName != null) {
|
||||||
user.setFirstName(nameParts.firstName());
|
user.setFirstName(firstName);
|
||||||
user.setLastName(nameParts.lastName());
|
}
|
||||||
user.setFullName(nameParts.fullName());
|
String lastName = trimToNull(request.getLastName());
|
||||||
|
if (lastName != null) {
|
||||||
|
user.setLastName(lastName);
|
||||||
|
}
|
||||||
|
if (firstName != null || lastName != null) {
|
||||||
|
user.setFullName(joinFullName(user.getFirstName(), user.getLastName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.getPhone() != null) {
|
if (request.getPhone() != null) {
|
||||||
@@ -247,6 +253,8 @@ public class AuthController {
|
|||||||
return new UserInfoResponse(
|
return new UserInfoResponse(
|
||||||
user.getId(),
|
user.getId(),
|
||||||
user.getUsername(),
|
user.getUsername(),
|
||||||
|
user.getFirstName(),
|
||||||
|
user.getLastName(),
|
||||||
user.getEmail(),
|
user.getEmail(),
|
||||||
fullName,
|
fullName,
|
||||||
user.getPhone(),
|
user.getPhone(),
|
||||||
|
|||||||
@@ -11,8 +11,11 @@ public class ProfileUpdateRequest {
|
|||||||
@Email(message = "Email must be valid")
|
@Email(message = "Email must be valid")
|
||||||
private String email;
|
private String email;
|
||||||
|
|
||||||
@Size(max = 100, message = "Full name must not exceed 100 characters")
|
@Size(max = 50, message = "First name must not exceed 50 characters")
|
||||||
private String fullName;
|
private String firstName;
|
||||||
|
|
||||||
|
@Size(max = 50, message = "Last name must not exceed 50 characters")
|
||||||
|
private String lastName;
|
||||||
|
|
||||||
@Size(max = 20, message = "Phone must not exceed 20 characters")
|
@Size(max = 20, message = "Phone must not exceed 20 characters")
|
||||||
private String phone;
|
private String phone;
|
||||||
@@ -36,12 +39,20 @@ public class ProfileUpdateRequest {
|
|||||||
this.email = email;
|
this.email = email;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getFullName() {
|
public String getFirstName() {
|
||||||
return fullName;
|
return firstName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFullName(String fullName) {
|
public void setFirstName(String firstName) {
|
||||||
this.fullName = fullName;
|
this.firstName = firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastName() {
|
||||||
|
return lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastName(String lastName) {
|
||||||
|
this.lastName = lastName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPhone() {
|
public String getPhone() {
|
||||||
@@ -67,14 +78,15 @@ public class ProfileUpdateRequest {
|
|||||||
ProfileUpdateRequest that = (ProfileUpdateRequest) o;
|
ProfileUpdateRequest that = (ProfileUpdateRequest) o;
|
||||||
return Objects.equals(username, that.username) &&
|
return Objects.equals(username, that.username) &&
|
||||||
Objects.equals(email, that.email) &&
|
Objects.equals(email, that.email) &&
|
||||||
Objects.equals(fullName, that.fullName) &&
|
Objects.equals(firstName, that.firstName) &&
|
||||||
|
Objects.equals(lastName, that.lastName) &&
|
||||||
Objects.equals(phone, that.phone) &&
|
Objects.equals(phone, that.phone) &&
|
||||||
Objects.equals(password, that.password);
|
Objects.equals(password, that.password);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(username, email, fullName, phone, password);
|
return Objects.hash(username, email, firstName, lastName, phone, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -82,7 +94,8 @@ public class ProfileUpdateRequest {
|
|||||||
return "ProfileUpdateRequest{" +
|
return "ProfileUpdateRequest{" +
|
||||||
"username='" + username + '\'' +
|
"username='" + username + '\'' +
|
||||||
", email='" + email + '\'' +
|
", email='" + email + '\'' +
|
||||||
", fullName='" + fullName + '\'' +
|
", firstName='" + firstName + '\'' +
|
||||||
|
", lastName='" + lastName + '\'' +
|
||||||
", phone='" + phone + '\'' +
|
", phone='" + phone + '\'' +
|
||||||
", password='" + password + '\'' +
|
", password='" + password + '\'' +
|
||||||
'}';
|
'}';
|
||||||
|
|||||||
@@ -18,9 +18,13 @@ public class RegisterRequest {
|
|||||||
@Email(message = "Email must be valid")
|
@Email(message = "Email must be valid")
|
||||||
private String email;
|
private String email;
|
||||||
|
|
||||||
@NotBlank(message = "Full name is required")
|
@NotBlank(message = "First name is required")
|
||||||
@Size(max = 100, message = "Full name must not exceed 100 characters")
|
@Size(max = 50, message = "First name must not exceed 50 characters")
|
||||||
private String fullName;
|
private String firstName;
|
||||||
|
|
||||||
|
@NotBlank(message = "Last name is required")
|
||||||
|
@Size(max = 50, message = "Last name must not exceed 50 characters")
|
||||||
|
private String lastName;
|
||||||
|
|
||||||
@NotBlank(message = "Phone is required")
|
@NotBlank(message = "Phone is required")
|
||||||
@Size(max = 20, message = "Phone must not exceed 20 characters")
|
@Size(max = 20, message = "Phone must not exceed 20 characters")
|
||||||
@@ -50,12 +54,20 @@ public class RegisterRequest {
|
|||||||
this.email = email;
|
this.email = email;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getFullName() {
|
public String getFirstName() {
|
||||||
return fullName;
|
return firstName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFullName(String fullName) {
|
public void setFirstName(String firstName) {
|
||||||
this.fullName = fullName;
|
this.firstName = firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastName() {
|
||||||
|
return lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastName(String lastName) {
|
||||||
|
this.lastName = lastName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPhone() {
|
public String getPhone() {
|
||||||
@@ -74,13 +86,14 @@ public class RegisterRequest {
|
|||||||
return Objects.equals(username, that.username) &&
|
return Objects.equals(username, that.username) &&
|
||||||
Objects.equals(password, that.password) &&
|
Objects.equals(password, that.password) &&
|
||||||
Objects.equals(email, that.email) &&
|
Objects.equals(email, that.email) &&
|
||||||
Objects.equals(fullName, that.fullName) &&
|
Objects.equals(firstName, that.firstName) &&
|
||||||
|
Objects.equals(lastName, that.lastName) &&
|
||||||
Objects.equals(phone, that.phone);
|
Objects.equals(phone, that.phone);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return Objects.hash(username, password, email, fullName, phone);
|
return Objects.hash(username, password, email, firstName, lastName, phone);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -89,7 +102,8 @@ public class RegisterRequest {
|
|||||||
"username='" + username + '\'' +
|
"username='" + username + '\'' +
|
||||||
", password='" + password + '\'' +
|
", password='" + password + '\'' +
|
||||||
", email='" + email + '\'' +
|
", email='" + email + '\'' +
|
||||||
", fullName='" + fullName + '\'' +
|
", firstName='" + firstName + '\'' +
|
||||||
|
", lastName='" + lastName + '\'' +
|
||||||
", phone='" + phone + '\'' +
|
", phone='" + phone + '\'' +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import java.util.Objects;
|
|||||||
public class UserInfoResponse {
|
public class UserInfoResponse {
|
||||||
private Long id;
|
private Long id;
|
||||||
private String username;
|
private String username;
|
||||||
|
private String firstName;
|
||||||
|
private String lastName;
|
||||||
private String email;
|
private String email;
|
||||||
private String fullName;
|
private String fullName;
|
||||||
private String phone;
|
private String phone;
|
||||||
@@ -17,9 +19,11 @@ public class UserInfoResponse {
|
|||||||
public UserInfoResponse() {
|
public UserInfoResponse() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserInfoResponse(Long id, String username, String email, String fullName, String phone, String avatarUrl, String role, Long customerId, Long storeId, String storeName) {
|
public UserInfoResponse(Long id, String username, String firstName, String lastName, String email, String fullName, String phone, String avatarUrl, String role, Long customerId, Long storeId, String storeName) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.username = username;
|
this.username = username;
|
||||||
|
this.firstName = firstName;
|
||||||
|
this.lastName = lastName;
|
||||||
this.email = email;
|
this.email = email;
|
||||||
this.fullName = fullName;
|
this.fullName = fullName;
|
||||||
this.phone = phone;
|
this.phone = phone;
|
||||||
@@ -46,6 +50,22 @@ public class UserInfoResponse {
|
|||||||
this.username = username;
|
this.username = username;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getFirstName() {
|
||||||
|
return firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstName(String firstName) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastName() {
|
||||||
|
return lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastName(String lastName) {
|
||||||
|
this.lastName = lastName;
|
||||||
|
}
|
||||||
|
|
||||||
public String getEmail() {
|
public String getEmail() {
|
||||||
return email;
|
return email;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ export default function ProfilePage() {
|
|||||||
const [petAge, setPetAge] = useState("1");
|
const [petAge, setPetAge] = useState("1");
|
||||||
const [submitting, setSubmitting] = useState(false);
|
const [submitting, setSubmitting] = useState(false);
|
||||||
const [petError, setPetError] = useState(null);
|
const [petError, setPetError] = useState(null);
|
||||||
const [profileForm, setProfileForm] = useState({ fullName: "", email: "", phone: "" });
|
const [avatarObjectUrl, setAvatarObjectUrl] = useState(null);
|
||||||
|
const [profileForm, setProfileForm] = useState({ firstName: "", lastName: "", email: "", phone: "", password: "", confirmPassword: "" });
|
||||||
const [profileSubmitting, setProfileSubmitting] = useState(false);
|
const [profileSubmitting, setProfileSubmitting] = useState(false);
|
||||||
const [profileError, setProfileError] = useState(null);
|
const [profileError, setProfileError] = useState(null);
|
||||||
const [profileSuccess, setProfileSuccess] = useState(null);
|
const [profileSuccess, setProfileSuccess] = useState(null);
|
||||||
@@ -55,9 +56,12 @@ export default function ProfilePage() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setProfileForm({
|
setProfileForm({
|
||||||
fullName: user?.fullName || "",
|
firstName: user?.firstName || "",
|
||||||
|
lastName: user?.lastName || "",
|
||||||
email: user?.email || "",
|
email: user?.email || "",
|
||||||
phone: user?.phone || "",
|
phone: user?.phone || "",
|
||||||
|
password: "",
|
||||||
|
confirmPassword: "",
|
||||||
});
|
});
|
||||||
}, [user]);
|
}, [user]);
|
||||||
|
|
||||||
@@ -117,11 +121,37 @@ export default function ProfilePage() {
|
|||||||
}, [clearPetImageObjectUrls]);
|
}, [clearPetImageObjectUrls]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (user?.role === "CUSTOMER" || user?.role === "ADMIN") {
|
if (user?.role === "CUSTOMER" || user?.role === "ADMIN") {
|
||||||
loadPets();
|
loadPets();
|
||||||
}
|
}
|
||||||
}, [user, loadPets]);
|
}, [user, loadPets]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let objectUrl = null;
|
||||||
|
|
||||||
|
if (user?.avatarUrl && token) {
|
||||||
|
fetch(`${API_BASE}${user.avatarUrl}`, {
|
||||||
|
headers: { Authorization: `Bearer ${token}` },
|
||||||
|
})
|
||||||
|
.then((res) => (res.ok ? res.blob() : null))
|
||||||
|
.then((blob) => {
|
||||||
|
if (blob) {
|
||||||
|
objectUrl = URL.createObjectURL(blob);
|
||||||
|
setAvatarObjectUrl(objectUrl);
|
||||||
|
} else {
|
||||||
|
setAvatarObjectUrl(null);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => setAvatarObjectUrl(null));
|
||||||
|
} else {
|
||||||
|
setAvatarObjectUrl(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (objectUrl) URL.revokeObjectURL(objectUrl);
|
||||||
|
};
|
||||||
|
}, [user?.avatarUrl, token]);
|
||||||
|
|
||||||
function handleLogout() {
|
function handleLogout() {
|
||||||
logout();
|
logout();
|
||||||
router.push("/");
|
router.push("/");
|
||||||
@@ -129,10 +159,26 @@ if (user?.role === "CUSTOMER" || user?.role === "ADMIN") {
|
|||||||
|
|
||||||
async function handleProfileSubmit(e) {
|
async function handleProfileSubmit(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setProfileSubmitting(true);
|
|
||||||
setProfileError(null);
|
setProfileError(null);
|
||||||
|
|
||||||
|
if (profileForm.password && profileForm.password !== profileForm.confirmPassword) {
|
||||||
|
setProfileError("Passwords do not match.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setProfileSubmitting(true);
|
||||||
setProfileSuccess(null);
|
setProfileSuccess(null);
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
firstName: profileForm.firstName,
|
||||||
|
lastName: profileForm.lastName,
|
||||||
|
email: profileForm.email,
|
||||||
|
phone: profileForm.phone,
|
||||||
|
};
|
||||||
|
if (profileForm.password) {
|
||||||
|
payload.password = profileForm.password;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await fetch(`${API_BASE}/api/v1/auth/me`, {
|
const res = await fetch(`${API_BASE}/api/v1/auth/me`, {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
@@ -140,7 +186,7 @@ if (user?.role === "CUSTOMER" || user?.role === "ADMIN") {
|
|||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${token}`,
|
||||||
},
|
},
|
||||||
body: JSON.stringify(profileForm),
|
body: JSON.stringify(payload),
|
||||||
});
|
});
|
||||||
|
|
||||||
const data = await res.json().catch(() => null);
|
const data = await res.json().catch(() => null);
|
||||||
@@ -149,6 +195,7 @@ if (user?.role === "CUSTOMER" || user?.role === "ADMIN") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await refreshUser();
|
await refreshUser();
|
||||||
|
setProfileForm((prev) => ({ ...prev, password: "", confirmPassword: "" }));
|
||||||
setProfileSuccess("Profile updated successfully.");
|
setProfileSuccess("Profile updated successfully.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,12 +387,14 @@ if (user?.role === "CUSTOMER" || user?.role === "ADMIN") {
|
|||||||
return <main className="auth-page"><p className="profile-loading">Loading…</p></main>;
|
return <main className="auth-page"><p className="profile-loading">Loading…</p></main>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const displayName = [user.firstName, user.lastName].filter(Boolean).join(" ") || user.username;
|
||||||
|
|
||||||
const fields = [
|
const fields = [
|
||||||
{label: "Full Name", value: user.fullName},
|
{label: "First Name", value: user.firstName || "N/A"},
|
||||||
|
{label: "Last Name", value: user.lastName || "N/A"},
|
||||||
{label: "Username", value: user.username},
|
{label: "Username", value: user.username},
|
||||||
{label: "Email", value: user.email},
|
{label: "Email", value: user.email},
|
||||||
{label: "Phone", value: user.phone || "—"},
|
{label: "Phone", value: user.phone || "N/A"},
|
||||||
{label: "Role", value: user.role},
|
|
||||||
...(user.storeName ? [{ label: "Store", value: user.storeName }] : []),
|
...(user.storeName ? [{ label: "Store", value: user.storeName }] : []),
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -353,14 +402,14 @@ if (user?.role === "CUSTOMER" || user?.role === "ADMIN") {
|
|||||||
<main className="profile-page-layout">
|
<main className="profile-page-layout">
|
||||||
<div className="profile-card">
|
<div className="profile-card">
|
||||||
<div className="profile-avatar-circle">
|
<div className="profile-avatar-circle">
|
||||||
{user.avatarUrl ? (
|
{avatarObjectUrl ? (
|
||||||
<img src={user.avatarUrl} alt={user.fullName || user.username} className="profile-avatar-image" />
|
<img src={avatarObjectUrl} alt={displayName} className="profile-avatar-image" />
|
||||||
) : (
|
) : (
|
||||||
(user.fullName || user.username).charAt(0).toUpperCase()
|
displayName.charAt(0).toUpperCase()
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1 className="profile-name">{user.fullName || user.username}</h1>
|
<h1 className="profile-name">{displayName}</h1>
|
||||||
<span className="profile-role-badge">{user.role}</span>
|
<span className="profile-role-badge">{user.role}</span>
|
||||||
|
|
||||||
<dl className="profile-fields">
|
<dl className="profile-fields">
|
||||||
@@ -377,13 +426,23 @@ if (user?.role === "CUSTOMER" || user?.role === "ADMIN") {
|
|||||||
{profileError && <div className="appt-error">{profileError}</div>}
|
{profileError && <div className="appt-error">{profileError}</div>}
|
||||||
{profileSuccess && <div className="appt-success">{profileSuccess}</div>}
|
{profileSuccess && <div className="appt-success">{profileSuccess}</div>}
|
||||||
<label className="appt-label">
|
<label className="appt-label">
|
||||||
Full Name
|
First Name
|
||||||
<input
|
<input
|
||||||
className="appt-input"
|
className="appt-input"
|
||||||
type="text"
|
type="text"
|
||||||
value={profileForm.fullName}
|
value={profileForm.firstName}
|
||||||
onChange={(e) => setProfileForm((current) => ({ ...current, fullName: e.target.value }))}
|
onChange={(e) => setProfileForm((current) => ({ ...current, firstName: e.target.value }))}
|
||||||
maxLength={100}
|
maxLength={50}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label className="appt-label">
|
||||||
|
Last Name
|
||||||
|
<input
|
||||||
|
className="appt-input"
|
||||||
|
type="text"
|
||||||
|
value={profileForm.lastName}
|
||||||
|
onChange={(e) => setProfileForm((current) => ({ ...current, lastName: e.target.value }))}
|
||||||
|
maxLength={50}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
<label className="appt-label">
|
<label className="appt-label">
|
||||||
@@ -406,6 +465,29 @@ if (user?.role === "CUSTOMER" || user?.role === "ADMIN") {
|
|||||||
maxLength={20}
|
maxLength={20}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
<label className="appt-label">
|
||||||
|
New Password
|
||||||
|
<input
|
||||||
|
className="appt-input"
|
||||||
|
type="password"
|
||||||
|
value={profileForm.password}
|
||||||
|
onChange={(e) => setProfileForm((current) => ({ ...current, password: e.target.value }))}
|
||||||
|
minLength={6}
|
||||||
|
autoComplete="new-password"
|
||||||
|
placeholder="Leave blank to keep current"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label className="appt-label">
|
||||||
|
Confirm New Password
|
||||||
|
<input
|
||||||
|
className="appt-input"
|
||||||
|
type="password"
|
||||||
|
value={profileForm.confirmPassword}
|
||||||
|
onChange={(e) => setProfileForm((current) => ({ ...current, confirmPassword: e.target.value }))}
|
||||||
|
autoComplete="new-password"
|
||||||
|
placeholder="Leave blank to keep current"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
<div className="profile-avatar-actions">
|
<div className="profile-avatar-actions">
|
||||||
<label className="profile-avatar-upload-btn">
|
<label className="profile-avatar-upload-btn">
|
||||||
<input
|
<input
|
||||||
|
|||||||
@@ -22,12 +22,14 @@ function RegisterPage() {
|
|||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
|
|
||||||
const [form, setForm] = useState({
|
const [form, setForm] = useState({
|
||||||
fullName: "",
|
firstName: "",
|
||||||
|
lastName: "",
|
||||||
username: "",
|
username: "",
|
||||||
email: "",
|
email: "",
|
||||||
phone: "",
|
phone: "",
|
||||||
password: "",
|
password: "",
|
||||||
confirmPassword: "",});
|
confirmPassword: "",
|
||||||
|
});
|
||||||
|
|
||||||
const [error, setError] = useState("");
|
const [error, setError] = useState("");
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@@ -47,7 +49,9 @@ function RegisterPage() {
|
|||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
try {
|
try {
|
||||||
await register({fullName: form.fullName,
|
await register({
|
||||||
|
firstName: form.firstName,
|
||||||
|
lastName: form.lastName,
|
||||||
username: form.username,
|
username: form.username,
|
||||||
email: form.email,
|
email: form.email,
|
||||||
phone: form.phone,
|
phone: form.phone,
|
||||||
@@ -74,12 +78,24 @@ function RegisterPage() {
|
|||||||
|
|
||||||
<form className="auth-form" onSubmit={handleSubmit}>
|
<form className="auth-form" onSubmit={handleSubmit}>
|
||||||
<label className="auth-label">
|
<label className="auth-label">
|
||||||
Full Name
|
First Name
|
||||||
<input
|
<input
|
||||||
className="auth-input"
|
className="auth-input"
|
||||||
type="text"
|
type="text"
|
||||||
name="fullName"
|
name="firstName"
|
||||||
value={form.fullName}
|
value={form.firstName}
|
||||||
|
onChange={handleChange}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<label className="auth-label">
|
||||||
|
Last Name
|
||||||
|
<input
|
||||||
|
className="auth-input"
|
||||||
|
type="text"
|
||||||
|
name="lastName"
|
||||||
|
value={form.lastName}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
required
|
required
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -79,15 +79,21 @@ export function AuthProvider({ children }) {
|
|||||||
return userInfo;
|
return userInfo;
|
||||||
}, [refreshUser]);
|
}, [refreshUser]);
|
||||||
|
|
||||||
const register = useCallback(async ({ username, password, email, fullName, phone }) => {
|
const register = useCallback(async ({ username, password, email, firstName, lastName, phone }) => {
|
||||||
const res = await fetch("/api/v1/auth/register", {
|
const res = await fetch("/api/v1/auth/register", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({ username, password, email, fullName, phone }),
|
body: JSON.stringify({ username, password, email, firstName, lastName, phone }),
|
||||||
});
|
});
|
||||||
const data = await res.json();
|
const data = await res.json();
|
||||||
|
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
|
if (data.errors && typeof data.errors === "object") {
|
||||||
|
const fieldErrors = Object.entries(data.errors)
|
||||||
|
.map(([field, msg]) => `${field}: ${msg}`)
|
||||||
|
.join(", ");
|
||||||
|
throw new Error(fieldErrors || data.message || "Registration failed");
|
||||||
|
}
|
||||||
throw new Error(data.message || "Registration failed");
|
throw new Error(data.message || "Registration failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user