diff --git a/js/src/features/member-profile/api/schemas.ts b/js/src/features/member-profile/api/schemas.ts index 4cb0e21..16aaf3d 100644 --- a/js/src/features/member-profile/api/schemas.ts +++ b/js/src/features/member-profile/api/schemas.ts @@ -1,7 +1,8 @@ import { z } from "zod"; export const memberProfileSchema = z.object({ - fullName: z.string().min(1, "Full Name is required."), + firstName: z.string().min(1, "First Name is required."), + lastName: z.string().min(1, "Last Name is required."), email: z .string() .min(1, "Email Address is required.") diff --git a/js/src/features/member-profile/types.ts b/js/src/features/member-profile/types.ts index 1d15cb2..bcfad51 100644 --- a/js/src/features/member-profile/types.ts +++ b/js/src/features/member-profile/types.ts @@ -1,5 +1,6 @@ export interface MemberProfileValues { - fullName: string; + firstName: string; + lastName: string; email: string; linkedInUrl: string; introduction: string; diff --git a/js/src/features/sign-up/components/SignUpForm.tsx b/js/src/features/sign-up/components/SignUpForm.tsx index 76da1ac..bc87d62 100644 --- a/js/src/features/sign-up/components/SignUpForm.tsx +++ b/js/src/features/sign-up/components/SignUpForm.tsx @@ -28,7 +28,8 @@ const industryPrefOptions = INDUSTRIES.map((v) => ({ value: v, label: v })); // Define initial values const initialFormValues: MemberProfileValues = { - fullName: "", + firstName: "", + lastName: "", email: "", linkedInUrl: "", introduction: "", @@ -153,15 +154,25 @@ export function SignUpForm() { Contact - handleFieldChange("fullName", event.target.value) + handleFieldChange("firstName", event.target.value) } - onBlur={() => handleFieldBlur("fullName")} - error={errors.fullName} + onBlur={() => handleFieldBlur("firstName")} + error={errors.firstName} autoFocus /> + + handleFieldChange("lastName", event.target.value) + } + onBlur={() => handleFieldBlur("lastName")} + error={errors.lastName} + /> new MemberNotFoundException(id)); - if (request.fullName() != null) { - member.setFullName(request.fullName()); + if (request.firstName() != null) { + member.setFirstName(request.firstName()); + } + if (request.lastName() != null) { + member.setLastName(request.lastName()); } if (request.email() != null) { member.setEmail(request.email()); diff --git a/src/main/java/org/patinanetwork/patchats/api/member/db/models/Member.java b/src/main/java/org/patinanetwork/patchats/api/member/db/models/Member.java index 56ad188..aad7c9e 100644 --- a/src/main/java/org/patinanetwork/patchats/api/member/db/models/Member.java +++ b/src/main/java/org/patinanetwork/patchats/api/member/db/models/Member.java @@ -18,7 +18,10 @@ public class Member { private UUID id; @Setter - private String fullName; + private String firstName; + + @Setter + private String lastName; @Setter private String email; diff --git a/src/main/java/org/patinanetwork/patchats/api/member/db/repos/MemberRepo.java b/src/main/java/org/patinanetwork/patchats/api/member/db/repos/MemberRepo.java index a37a108..304d0d8 100644 --- a/src/main/java/org/patinanetwork/patchats/api/member/db/repos/MemberRepo.java +++ b/src/main/java/org/patinanetwork/patchats/api/member/db/repos/MemberRepo.java @@ -10,7 +10,8 @@ public interface MemberRepo { * @param member - required fields: *
    *
  • id - *
  • fullName + *
  • firstName + *
  • lastName *
  • email *
  • introduction *
  • active @@ -24,7 +25,8 @@ public interface MemberRepo { * @note - The provided object's methods will be overridden with any returned data from the database. * @param member - overridden fields: *
      - *
    • fullName + *
    • firstName + *
    • lastName *
    • email *
    • linkedInUrl *
    • introduction diff --git a/src/main/java/org/patinanetwork/patchats/api/member/db/repos/MemberSqlRepo.java b/src/main/java/org/patinanetwork/patchats/api/member/db/repos/MemberSqlRepo.java index a2dddd8..e4c312a 100644 --- a/src/main/java/org/patinanetwork/patchats/api/member/db/repos/MemberSqlRepo.java +++ b/src/main/java/org/patinanetwork/patchats/api/member/db/repos/MemberSqlRepo.java @@ -19,7 +19,8 @@ public class MemberSqlRepo implements MemberRepo { private Member parseResultSetToMember(final ResultSet rs) throws SQLException { return Member.builder() .id(UUID.fromString(rs.getString("id"))) - .fullName(rs.getString("full_name")) + .firstName(rs.getString("first_name")) + .lastName(rs.getString("last_name")) .email(rs.getString("email")) .linkedInUrl(rs.getString("linked_in_url")) .introduction(rs.getString("introduction")) @@ -40,7 +41,8 @@ public Member createMember(Member member) { String sql = """ INSERT INTO "members" ( "id", - "full_name", + "first_name", + "last_name", "email", "linked_in_url", "introduction", @@ -54,7 +56,8 @@ public Member createMember(Member member) { ) VALUES( :id, - :full_name, + :first_name, + :last_name, :email, :linked_in_url, :introduction, @@ -71,7 +74,8 @@ public Member createMember(Member member) { """; return jdbc.sql(sql) .param("id", member.getId()) - .param("full_name", member.getFullName()) + .param("first_name", member.getFirstName()) + .param("last_name", member.getLastName()) .param("email", member.getEmail()) .param("linked_in_url", member.getLinkedInUrl()) .param("introduction", member.getIntroduction()) diff --git a/src/main/java/org/patinanetwork/patchats/api/member/dto/CreateMemberRequest.java b/src/main/java/org/patinanetwork/patchats/api/member/dto/CreateMemberRequest.java index f95a4d7..7f65379 100644 --- a/src/main/java/org/patinanetwork/patchats/api/member/dto/CreateMemberRequest.java +++ b/src/main/java/org/patinanetwork/patchats/api/member/dto/CreateMemberRequest.java @@ -4,7 +4,8 @@ import jakarta.validation.constraints.NotBlank; public record CreateMemberRequest( - @NotBlank String fullName, + @NotBlank String firstName, + @NotBlank String lastName, @NotBlank @Email String email, String linkedInUrl, @NotBlank String introduction, diff --git a/src/main/java/org/patinanetwork/patchats/api/member/dto/MemberDto.java b/src/main/java/org/patinanetwork/patchats/api/member/dto/MemberDto.java index 96920ca..611c42f 100644 --- a/src/main/java/org/patinanetwork/patchats/api/member/dto/MemberDto.java +++ b/src/main/java/org/patinanetwork/patchats/api/member/dto/MemberDto.java @@ -19,7 +19,10 @@ public class MemberDto { private UUID id; @Schema(requiredMode = Schema.RequiredMode.REQUIRED) - private String fullName; + private String firstName; + + @Schema(requiredMode = Schema.RequiredMode.REQUIRED) + private String lastName; // TODO: Changes to email require verification after authentication is implemented @Schema(requiredMode = Schema.RequiredMode.REQUIRED) @@ -61,7 +64,8 @@ public class MemberDto { public static MemberDto from(final Member member) { return MemberDto.builder() .id(member.getId()) - .fullName(member.getFullName()) + .firstName(member.getFirstName()) + .lastName(member.getLastName()) .email(member.getEmail()) .linkedInUrl(member.getLinkedInUrl()) .introduction(member.getIntroduction()) diff --git a/src/main/java/org/patinanetwork/patchats/api/member/dto/UpdateMemberRequest.java b/src/main/java/org/patinanetwork/patchats/api/member/dto/UpdateMemberRequest.java index d61cbf6..290ec98 100644 --- a/src/main/java/org/patinanetwork/patchats/api/member/dto/UpdateMemberRequest.java +++ b/src/main/java/org/patinanetwork/patchats/api/member/dto/UpdateMemberRequest.java @@ -3,7 +3,8 @@ import jakarta.validation.constraints.Email; public record UpdateMemberRequest( - String fullName, + String firstName, + String lastName, // TODO: Changes to email require verification after authentication is implemented @Email String email, String linkedInUrl, diff --git a/src/test/java/org/patinanetwork/patchats/api/member/MemberControllerTest.java b/src/test/java/org/patinanetwork/patchats/api/member/MemberControllerTest.java index 3a23b44..722421f 100644 --- a/src/test/java/org/patinanetwork/patchats/api/member/MemberControllerTest.java +++ b/src/test/java/org/patinanetwork/patchats/api/member/MemberControllerTest.java @@ -34,7 +34,8 @@ class MemberControllerTest { @Test void createMember_ReturnsOkAndMemberDto() throws Exception { final CreateMemberRequest request = new CreateMemberRequest( - "John Doe", + "John", + "Doe", "john.doe@example.com", "https://www.linkedin.com/in/johndoe", "Hello, I'm John!", @@ -48,7 +49,8 @@ void createMember_ReturnsOkAndMemberDto() throws Exception { when(memberService.createMember(any())) .thenReturn(MemberDto.builder() .id(UUID.randomUUID()) - .fullName(request.fullName()) + .firstName(request.firstName()) + .lastName(request.lastName()) .email(request.email()) .linkedInUrl(request.linkedInUrl()) .introduction(request.introduction()) @@ -64,10 +66,11 @@ void createMember_ReturnsOkAndMemberDto() throws Exception { post("/api/members") .contentType(MediaType.APPLICATION_JSON) .content( - "{\"fullName\":\"John Doe\",\"email\":\"john.doe@example.com\",\"linkedInUrl\":\"https://www.linkedin.com/in/johndoe\",\"introduction\":\"Hello, I'm John!\",\"referralSource\":\"Friend\",\"matchPref\":\"Mentor - I am looking for guidance from someone with more experience\",\"industryPref\":\"Technology\",\"rolePref\":\"Software Engineer\",\"topics\":\"College, Career Development\",\"extraNotes\":\"I want to be meet someone in person in NYC\"}")) + "{\"firstName\":\"John\",\"lastName\":\"Doe\",\"email\":\"john.doe@example.com\",\"linkedInUrl\":\"https://www.linkedin.com/in/johndoe\",\"introduction\":\"Hello, I'm John!\",\"referralSource\":\"Friend\",\"matchPref\":\"Mentor - I am looking for guidance from someone with more experience\",\"industryPref\":\"Technology\",\"rolePref\":\"Software Engineer\",\"topics\":\"College, Career Development\",\"extraNotes\":\"I want to be meet someone in person in NYC\"}")) .andExpect(status().isOk()) .andExpect(jsonPath("$.success").value(true)) - .andExpect(jsonPath("$.payload.fullName").value(request.fullName())) + .andExpect(jsonPath("$.payload.firstName").value(request.firstName())) + .andExpect(jsonPath("$.payload.lastName").value(request.lastName())) .andExpect(jsonPath("$.payload.email").value(request.email())) .andExpect(jsonPath("$.payload.linkedInUrl").value(request.linkedInUrl())) .andExpect(jsonPath("$.payload.introduction").value(request.introduction())) @@ -82,12 +85,12 @@ void createMember_ReturnsOkAndMemberDto() throws Exception { } @Test - void createMember_returnsBadRequestWhenFullNameIsBlank() throws Exception { + void createMember_returnsBadRequestWhenFirstNameIsBlank() throws Exception { mockMvc.perform( post("/api/members") .contentType(MediaType.APPLICATION_JSON) .content( - "{\"fullName\":\"\",\"email\":\"john.doe@example.com\",\"linkedInUrl\":\"https://www.linkedin.com/in/johndoe\",\"introduction\":\"Hello, I'm John!\",\"referralSource\":\"Friend\",\"matchPref\":\"Mentor - I am looking for guidance from someone with more experience\",\"industryPref\":\"Technology\",\"rolePref\":\"Software Engineer\",\"topics\":\"College, Career Development\",\"extraNotes\":\"I want to be meet someone in person in NYC\"}")) + "{\"firstName\":\"\",\"lastName\":\"Doe\",\"email\":\"john.doe@example.com\",\"linkedInUrl\":\"https://www.linkedin.com/in/johndoe\",\"introduction\":\"Hello, I'm John!\",\"referralSource\":\"Friend\",\"matchPref\":\"Mentor - I am looking for guidance from someone with more experience\",\"industryPref\":\"Technology\",\"rolePref\":\"Software Engineer\",\"topics\":\"College, Career Development\",\"extraNotes\":\"I want to be meet someone in person in NYC\"}")) .andExpect(status().isBadRequest()) .andExpect(jsonPath("$.success").value(false)); } @@ -99,7 +102,7 @@ void createMember_returnsConflictOnDuplicateEmail() throws Exception { post("/api/members") .contentType(MediaType.APPLICATION_JSON) .content( - "{\"fullName\":\"John Doe\",\"email\":\"john.doe@example.com\",\"linkedInUrl\":\"https://www.linkedin.com/in/johndoe\",\"introduction\":\"Hello, I'm John!\",\"referralSource\":\"Friend\",\"matchPref\":\"Mentor - I am looking for guidance from someone with more experience\",\"industryPref\":\"Technology\",\"rolePref\":\"Software Engineer\",\"topics\":\"College, Career Development\",\"extraNotes\":\"I want to be meet someone in person in NYC\"}")) + "{\"firstName\":\"John\",\"lastName\":\"Doe\",\"email\":\"john.doe@example.com\",\"linkedInUrl\":\"https://www.linkedin.com/in/johndoe\",\"introduction\":\"Hello, I'm John!\",\"referralSource\":\"Friend\",\"matchPref\":\"Mentor - I am looking for guidance from someone with more experience\",\"industryPref\":\"Technology\",\"rolePref\":\"Software Engineer\",\"topics\":\"College, Career Development\",\"extraNotes\":\"I want to be meet someone in person in NYC\"}")) .andExpect(status().isConflict()) .andExpect(jsonPath("$.success").value(false)); } diff --git a/src/test/java/org/patinanetwork/patchats/api/member/MemberServiceTest.java b/src/test/java/org/patinanetwork/patchats/api/member/MemberServiceTest.java index ce41b29..251a49c 100644 --- a/src/test/java/org/patinanetwork/patchats/api/member/MemberServiceTest.java +++ b/src/test/java/org/patinanetwork/patchats/api/member/MemberServiceTest.java @@ -29,7 +29,8 @@ class MemberServiceTest { @Test void createMember_successWithAllFieldsFilled() { final CreateMemberRequest request = new CreateMemberRequest( - "John Doe", + "John", + "Doe", "john.doe@example.com", "https://www.linkedin.com/in/johndoe", "Hello, I'm John!", @@ -44,7 +45,8 @@ void createMember_successWithAllFieldsFilled() { when(memberRepo.createMember(any())) .thenReturn(Member.builder() .id(UUID.randomUUID()) - .fullName(request.fullName()) + .firstName(request.firstName()) + .lastName(request.lastName()) .email(request.email()) .linkedInUrl(request.linkedInUrl()) .introduction(request.introduction()) @@ -58,7 +60,8 @@ void createMember_successWithAllFieldsFilled() { .build()); final MemberDto response = memberService.createMember(request); - assertEquals(request.fullName(), response.getFullName()); + assertEquals(request.firstName(), response.getFirstName()); + assertEquals(request.lastName(), response.getLastName()); assertEquals(request.email(), response.getEmail()); assertEquals(request.linkedInUrl(), response.getLinkedInUrl()); assertEquals(request.introduction(), response.getIntroduction()); @@ -76,7 +79,8 @@ void createMember_successWithAllFieldsFilled() { @Test void createMember_throwsExceptionWhenEmailAlreadyExists() { final CreateMemberRequest request = new CreateMemberRequest( - "John Doe", + "John", + "Doe", "john.doe@example.com", "https://www.linkedin.com/in/johndoe", "Hello, I'm John!", @@ -90,7 +94,8 @@ void createMember_throwsExceptionWhenEmailAlreadyExists() { when(memberRepo.getMemberByEmail(any())) .thenReturn(Optional.of(Member.builder() .id(UUID.randomUUID()) - .fullName(request.fullName()) + .firstName(request.firstName()) + .lastName(request.lastName()) .email(request.email()) .linkedInUrl(request.linkedInUrl()) .introduction(request.introduction()) @@ -111,7 +116,8 @@ void createMember_throwsExceptionWhenEmailAlreadyExists() { void updateMember_throwsExceptionWhenMemberNotFound() { final UUID id = UUID.randomUUID(); final UpdateMemberRequest request = new UpdateMemberRequest( - "Updated Name", + "UpdatedFirstName", + "UpdatedLastName", "updated@example.com", "https://linkedin.com/in/updated", "Updated intro", @@ -131,11 +137,12 @@ void updateMember_throwsExceptionWhenMemberNotFound() { void updateMember_successWithOnlyNameField() { final UUID id = UUID.randomUUID(); final UpdateMemberRequest request = - new UpdateMemberRequest("Updated Name", null, null, null, null, null, null, null, null); + new UpdateMemberRequest("UpdatedFirstName", null, null, null, null, null, null, null, null, null); final Member existingMember = Member.builder() .id(id) - .fullName("Old Name") + .firstName("OldFirstName") + .lastName("OldLastName") .email("old@example.com") .linkedInUrl("https://linkedin.com/in/old") .introduction("Old intro") @@ -148,7 +155,8 @@ void updateMember_successWithOnlyNameField() { final Member updatedMember = Member.builder() .id(id) - .fullName("Updated Name") + .firstName("UpdatedFirstName") + .lastName("OldLastName") .email("old@example.com") .linkedInUrl("https://linkedin.com/in/old") .introduction("Old intro") @@ -164,7 +172,7 @@ void updateMember_successWithOnlyNameField() { final MemberDto response = memberService.updateMember(request, id); - assertEquals("Updated Name", response.getFullName()); + assertEquals("UpdatedFirstName", response.getFirstName()); assertEquals("old@example.com", response.getEmail()); assertEquals("https://linkedin.com/in/old", response.getLinkedInUrl()); assertEquals("Old intro", response.getIntroduction()); @@ -174,11 +182,12 @@ void updateMember_successWithOnlyNameField() { void updateMember_successWithAllNullFields() { final UUID id = UUID.randomUUID(); final UpdateMemberRequest request = - new UpdateMemberRequest(null, null, null, null, null, null, null, null, null); + new UpdateMemberRequest(null, null, null, null, null, null, null, null, null, null); final Member existingMember = Member.builder() .id(id) - .fullName("Name") + .firstName("OldFirstName") + .lastName("OldLastName") .email("email@example.com") .linkedInUrl("https://linkedin.com/in/john") .introduction("intro") @@ -194,7 +203,8 @@ void updateMember_successWithAllNullFields() { final MemberDto response = memberService.updateMember(request, id); - assertEquals("Name", response.getFullName()); + assertEquals("OldFirstName", response.getFirstName()); + assertEquals("OldLastName", response.getLastName()); assertEquals("email@example.com", response.getEmail()); assertEquals("https://linkedin.com/in/john", response.getLinkedInUrl()); assertEquals("intro", response.getIntroduction()); @@ -204,7 +214,8 @@ void updateMember_successWithAllNullFields() { void updateMember_successWithAllFields() { final UUID id = UUID.randomUUID(); final UpdateMemberRequest request = new UpdateMemberRequest( - "Updated Name", + "UpdatedFirstName", + "UpdatedLastName", "updated@example.com", "https://linkedin.com/in/updated", "Updated intro", @@ -216,7 +227,8 @@ void updateMember_successWithAllFields() { final Member existingMember = Member.builder() .id(id) - .fullName("Old Name") + .firstName("OldFirstName") + .lastName("OldLastName") .email("old@example.com") .linkedInUrl("https://linkedin.com/in/old") .introduction("Old intro") @@ -229,7 +241,8 @@ void updateMember_successWithAllFields() { final Member updatedMember = Member.builder() .id(id) - .fullName(request.fullName()) + .firstName(request.firstName()) + .lastName(request.lastName()) .email(request.email()) .linkedInUrl(request.linkedInUrl()) .introduction(request.introduction()) @@ -245,7 +258,8 @@ void updateMember_successWithAllFields() { final MemberDto response = memberService.updateMember(request, id); - assertEquals(request.fullName(), response.getFullName()); + assertEquals(request.firstName(), response.getFirstName()); + assertEquals(request.lastName(), response.getLastName()); assertEquals(request.email(), response.getEmail()); assertEquals(request.linkedInUrl(), response.getLinkedInUrl()); assertEquals(request.introduction(), response.getIntroduction());