diff --git a/backend/src/test/java/com/graphy/backend/domain/follow/controller/FollowControllerTest.java b/backend/src/test/java/com/graphy/backend/domain/follow/controller/FollowControllerTest.java index f5afed92..ae3a8dcf 100644 --- a/backend/src/test/java/com/graphy/backend/domain/follow/controller/FollowControllerTest.java +++ b/backend/src/test/java/com/graphy/backend/domain/follow/controller/FollowControllerTest.java @@ -3,7 +3,9 @@ import com.graphy.backend.domain.auth.util.MemberInfo; import com.graphy.backend.domain.follow.service.FollowService; import com.graphy.backend.domain.member.domain.Member; +import com.graphy.backend.domain.member.dto.response.GetMemberListResponse; import com.graphy.backend.test.MockApiTest; +import com.graphy.backend.test.util.WithMockCustomUser; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -17,15 +19,23 @@ import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.web.context.WebApplicationContext; +import java.util.Arrays; +import java.util.List; + import static com.graphy.backend.domain.member.domain.Role.ROLE_USER; import static com.graphy.backend.test.config.ApiDocumentUtil.getDocumentRequest; import static com.graphy.backend.test.config.ApiDocumentUtil.getDocumentResponse; +import static org.hamcrest.Matchers.hasSize; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.post; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; import static org.springframework.restdocs.request.RequestDocumentation.pathParameters; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @WebMvcTest(FollowController.class) @ExtendWith(RestDocumentationExtension.class) @@ -42,7 +52,7 @@ public void setup(RestDocumentationContextProvider provider) { memberInfo = new MemberInfo(Member.builder().id(1L).email("test@gmail.com").password("password").role(ROLE_USER).build()); } - private static String baseUrl = "/api/v1/follow"; + private static final String BASE_URL = "/api/v1/follow"; @Test @DisplayName("팔로우 신청 테스트") @@ -51,7 +61,7 @@ void followTest() throws Exception { Long id = 1L; // when & then - mvc.perform(post(baseUrl + "/{id}", id).principal(new TestingAuthenticationToken("testEmail", "testPassword"))) + mvc.perform(post(BASE_URL + "/{id}", id).principal(new TestingAuthenticationToken("testEmail", "testPassword"))) .andExpect(status().isCreated()) .andDo(document("follow/add/success", getDocumentRequest(), @@ -73,7 +83,7 @@ void unfollowTest() throws Exception { Long id = 1L; //then - mvc.perform(RestDocumentationRequestBuilders.delete(baseUrl + "/{id}", id).principal(new TestingAuthenticationToken("testEmail", "testPassword"))) + mvc.perform(RestDocumentationRequestBuilders.delete(BASE_URL + "/{id}", id).principal(new TestingAuthenticationToken("testEmail", "testPassword"))) .andExpect(status().isNoContent()) .andDo(document("follow/remove/success", getDocumentRequest(), @@ -88,84 +98,99 @@ void unfollowTest() throws Exception { ))); } -// @Test -// @DisplayName("팔로잉 리스트 조회 테스트") -// void getFollowingListTest() throws Exception { -// // given -// GetMemberListResponse following1 = new GetMemberListResponse() { -// public Long getId() { -// return 1L; -// } -// public String getNickname() { -// return "memberA"; -// } -// }; -// -// GetMemberListResponse following2 = new GetMemberListResponse() { -// public Long getId() { -// return 2L; -// } -// public String getNickname() { -// return "memberB"; -// } -// }; -// -// List followingList = Arrays.asList(following1, following2); -// -// // when -// given(followService.findFollowingList(any(Member.class))).willReturn(followingList); -// -// //then -// mvc.perform(get(baseUrl + "/following").with(user(memberInfo))) -// .andExpect(status().isOk()) -// .andExpect(jsonPath("$.data", hasSize(2))) -// .andExpect(jsonPath("$.data[0].id").exists()) -// .andExpect(jsonPath("$.data[0].nickname").value("memberA")) -// .andExpect(jsonPath("$.data[1].id").exists()) -// .andExpect(jsonPath("$.data[1].nickname").value("memberB")) -// .andDo(document("followingList-get", -// preprocessResponse(prettyPrint())) -// ); -// } - -// @Test -// @WithAnonymousUser -// @DisplayName("팔로워 리스트 조회 테스트") -// void getFollowerListTest() throws Exception { -// // given -// GetMemberListResponse follower1 = new GetMemberListResponse() { -// public Long getId() { -// return 1L; -// } -// public String getNickname() { -// return "memberA"; -// } -// }; -// -// GetMemberListResponse follower2 = new GetMemberListResponse() { -// public Long getId() { -// return 2L; -// } -// public String getNickname() { -// return "memberB"; -// } -// }; -// -// List followerList = Arrays.asList(follower1, follower2); -// -// // when -// given(followService.findFollowerList(any(Member.class))).willReturn(followerList); -// -// //then -// mvc.perform(get(baseUrl + "/follower").principal(new TestingAuthenticationToken("testEmail", "testPassword"))) -// .andExpect(status().isOk()) -// .andExpect(jsonPath("$.data", hasSize(2))) -// .andExpect(jsonPath("$.data[0].id").exists()) -// .andExpect(jsonPath("$.data[0].nickname").value("memberA")) -// .andExpect(jsonPath("$.data[1].id").exists()) -// .andExpect(jsonPath("$.data[1].nickname").value("memberB")) -// .andDo(document("followerList-get", -// preprocessResponse(prettyPrint())) -// ); -// } + @Test + @WithMockCustomUser + @DisplayName("팔로잉 리스트 조회 테스트") + void getFollowingListTest() throws Exception { + // given + GetMemberListResponse following1 = new GetMemberListResponse() { + public Long getId() { + return 1L; + } + public String getNickname() { + return "memberA"; + } + }; + + GetMemberListResponse following2 = new GetMemberListResponse() { + public Long getId() { + return 2L; + } + public String getNickname() { + return "memberB"; + } + }; + + List followingList = Arrays.asList(following1, following2); + + // when + given(followService.findFollowingList(any(Member.class))).willReturn(followingList); + + //then + mvc.perform(get(BASE_URL + "/following")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.data", hasSize(2))) + .andExpect(jsonPath("$.data[0].id").exists()) + .andExpect(jsonPath("$.data[0].nickname").value("memberA")) + .andExpect(jsonPath("$.data[1].id").exists()) + .andExpect(jsonPath("$.data[1].nickname").value("memberB")) + .andDo(document("follow/followingList/success", + getDocumentRequest(), + getDocumentResponse(), + responseFields( + fieldWithPath("code").description("상태 코드"), + fieldWithPath("message").description("응답 메시지"), + fieldWithPath("data").description("응답 데이터"), + fieldWithPath("data[].id").description("팔로잉하는 사용자의 ID"), + fieldWithPath("data[].nickname").description("팔로잉하는 사용자의 nickname") + ))); + } + + @Test + @WithMockCustomUser + @DisplayName("팔로워 리스트 조회 테스트") + void getFollowerListTest() throws Exception { + // given + GetMemberListResponse follower1 = new GetMemberListResponse() { + public Long getId() { + return 1L; + } + public String getNickname() { + return "memberA"; + } + }; + + GetMemberListResponse follower2 = new GetMemberListResponse() { + public Long getId() { + return 2L; + } + public String getNickname() { + return "memberB"; + } + }; + + List followerList = Arrays.asList(follower1, follower2); + + // when + given(followService.findFollowerList(any(Member.class))).willReturn(followerList); + + //then + mvc.perform(get(BASE_URL + "/follower").principal(new TestingAuthenticationToken("testEmail", "testPassword"))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.data", hasSize(2))) + .andExpect(jsonPath("$.data[0].id").exists()) + .andExpect(jsonPath("$.data[0].nickname").value("memberA")) + .andExpect(jsonPath("$.data[1].id").exists()) + .andExpect(jsonPath("$.data[1].nickname").value("memberB")) + .andDo(document("follow/followingList/success", + getDocumentRequest(), + getDocumentResponse(), + responseFields( + fieldWithPath("code").description("상태 코드"), + fieldWithPath("message").description("응답 메시지"), + fieldWithPath("data").description("응답 데이터"), + fieldWithPath("data[].id").description("팔로워 사용자의 ID"), + fieldWithPath("data[].nickname").description("팔로워 사용자의 nickname") + ))); + } } diff --git a/backend/src/test/java/com/graphy/backend/domain/member/controller/MemberControllerTest.java b/backend/src/test/java/com/graphy/backend/domain/member/controller/MemberControllerTest.java index bc63b4fe..0a3e9da5 100644 --- a/backend/src/test/java/com/graphy/backend/domain/member/controller/MemberControllerTest.java +++ b/backend/src/test/java/com/graphy/backend/domain/member/controller/MemberControllerTest.java @@ -73,7 +73,7 @@ public void setup(RestDocumentationContextProvider provider) { @Test @DisplayName("닉네임으로 사용자를 조회한다") - public void findMemberTest() throws Exception { + void findMemberTest() throws Exception { // given GetMemberResponse response1 = GetMemberResponse.builder() .nickname(member1.getNickname()) @@ -122,7 +122,7 @@ public void findMemberTest() throws Exception { @Test @DisplayName("현재 로그인한 사용자의 정보로 마이페이지를 조회한다") - public void getMyPageTest() throws Exception { + void getMyPageTest() throws Exception { GetMyPageResponse result = GetMyPageResponse.builder() .nickname(member1.getNickname()) .introduction(member1.getIntroduction()) diff --git a/backend/src/test/java/com/graphy/backend/domain/project/controller/ProjectControllerTest.java b/backend/src/test/java/com/graphy/backend/domain/project/controller/ProjectControllerTest.java index 39794fad..7d50b6bf 100644 --- a/backend/src/test/java/com/graphy/backend/domain/project/controller/ProjectControllerTest.java +++ b/backend/src/test/java/com/graphy/backend/domain/project/controller/ProjectControllerTest.java @@ -1,11 +1,16 @@ package com.graphy.backend.domain.project.controller; import com.graphy.backend.domain.comment.service.CommentService; +import com.graphy.backend.domain.member.domain.Member; +import com.graphy.backend.domain.project.dto.request.CreateProjectRequest; +import com.graphy.backend.domain.project.dto.request.GetProjectPlanRequest; import com.graphy.backend.domain.project.dto.request.GetProjectsRequest; +import com.graphy.backend.domain.project.dto.response.CreateProjectResponse; import com.graphy.backend.domain.project.dto.response.GetProjectResponse; import com.graphy.backend.domain.project.service.ProjectService; import com.graphy.backend.global.config.SecurityConfig; import com.graphy.backend.test.MockApiTest; +import com.graphy.backend.test.util.WithMockCustomUser; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -15,9 +20,9 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; import org.springframework.data.domain.Pageable; +import org.springframework.http.MediaType; import org.springframework.restdocs.RestDocumentationContextProvider; import org.springframework.restdocs.RestDocumentationExtension; -import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; @@ -25,24 +30,25 @@ import java.time.LocalDateTime; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.concurrent.CompletableFuture; import static com.graphy.backend.test.config.ApiDocumentUtil.getDocumentRequest; import static com.graphy.backend.test.config.ApiDocumentUtil.getDocumentResponse; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.when; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document; import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration; -import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.get; -import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; -import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; +import static org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders.*; +import static org.springframework.restdocs.payload.PayloadDocumentation.*; import static org.springframework.restdocs.request.RequestDocumentation.parameterWithName; import static org.springframework.restdocs.request.RequestDocumentation.requestParameters; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @WebMvcTest(ProjectController.class) @ExtendWith(RestDocumentationExtension.class) -@WithMockUser(username = "yukeon@gmail.com") @Import(SecurityConfig.class) class ProjectControllerTest extends MockApiTest { @@ -55,7 +61,7 @@ class ProjectControllerTest extends MockApiTest { @MockBean CommentService commentService; - private static String baseUrl = "/api/v1/projects"; + private static final String BASE_URL = "/api/v1/projects"; @BeforeEach public void setup(RestDocumentationContextProvider provider) { @@ -66,43 +72,53 @@ public void setup(RestDocumentationContextProvider provider) { } -// @Test -// @DisplayName("프로젝트 생성 테스트") -// void createProject() throws Exception { -// //given -// CreateProjectRequest request = CreateProjectRequest.builder() -// .projectName("projectName") -// .description("description") -// .content("content") -// .build(); -// -// CreateProjectResponse response = CreateProjectResponse.builder().projectId(1L).build(); -// -// //when -// when(projectService.addProject(request, new Member())).thenReturn(response); -// -// //then -// mvc.perform(post(baseUrl) -// .contentType(MediaType.APPLICATION_JSON) -// .content(objectMapper.writeValueAsString(request))) -// .andExpect(status().isOk()) -// .andDo(document("project-create", -// preprocessResponse(prettyPrint())) -// ); -// } - -// @Test -// @DisplayName("프로젝트 삭제 테스트") -// void deleteProject() throws Exception { -// //given -// Long projectId = 1L; -// -// doNothing().when(projectService).removeProject(anyLong()); -// -// mvc.perform(delete(baseUrl + "/{projectId}", 1L) -// .contentType(MediaType.APPLICATION_JSON)) -// .andExpect(status().isOk()); -// } + @Test + @WithMockCustomUser + @DisplayName("프로젝트 생성 테스트") + void createProject() throws Exception { + //given + CreateProjectRequest request = CreateProjectRequest.builder() + .projectName("projectName") + .description("description") + .content("content") + .build(); + + CreateProjectResponse response = CreateProjectResponse.builder().projectId(1L).build(); + + //when + when(projectService.addProject(request, new Member())).thenReturn(response); + + //then + mvc.perform(post(BASE_URL) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isCreated()) + .andDo(document("project/add/success", + getDocumentRequest(), + getDocumentResponse(), + requestFields( + fieldWithPath("projectName").description("프로젝트 이름"), + fieldWithPath("description").description("프로젝트 설명"), + fieldWithPath("content").description("프로젝트 내용"), + fieldWithPath("techTags").description("기술 스택"), + fieldWithPath("thumbNail").description("썸네일") + ), + responseFields( + fieldWithPath("code").description("상태 코드"), + fieldWithPath("message").description("응답 메시지"), + fieldWithPath("data").description("응답 데이터") + ))); + } + + @Test + @WithMockCustomUser + @DisplayName("프로젝트 삭제 테스트") + void deleteProject() throws Exception { + + mvc.perform(delete(BASE_URL + "/{projectId}", 1L) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isNoContent()); + } @Test @DisplayName("프로젝트 이름/내용/전체 검색한다") @@ -111,10 +127,8 @@ void searchProjectsWithName() throws Exception { // given String projectName = "검색이름"; - GetProjectsRequest request = GetProjectsRequest.builder() - .projectName(projectName).build(); - List result = new ArrayList(); + List result = new ArrayList<>(); for (int i = 0; i < 5; i++) { GetProjectResponse response = @@ -130,7 +144,7 @@ void searchProjectsWithName() throws Exception { info.add("size", "5"); // when & then - mvc.perform(get(baseUrl).params(info)) + mvc.perform(get(BASE_URL).params(info)) .andExpect(status().isOk()) .andDo(document("project/list/success", getDocumentRequest(), @@ -154,29 +168,30 @@ void searchProjectsWithName() throws Exception { ))); } -// @Test -// @DisplayName("프로젝트 고도화 계획을 제안 받는다") -// void getProjectPlan() throws Exception { -// -// // given -// List features = new ArrayList<>(Arrays.asList("게시물 업로드", "좋아요 누르는 기능")); -// List techStacks = new ArrayList<>(Arrays.asList("Springboot", "React", "mySQL")); -// List plans = new ArrayList<>(Arrays.asList("Spring Security", "Docker")); -// String topic = "간단한 게시판"; -// -// GetProjectPlanRequest request = new GetProjectPlanRequest(topic, features, techStacks, plans); -// -// String apiResult = "API 결과"; -// CompletableFuture result = CompletableFuture.completedFuture(apiResult); -// -// given(projectService.getProjectPlanAsync(any())).willReturn(result); -// -// // when -// String body = objectMapper.writeValueAsString(request); -// mvc.perform(post(baseUrl+"/plans").principal(new TestingAuthenticationToken("testEmail", "testPassword")) -// .content(objectMapper.writeValueAsString(request)) -// .contentType(MediaType.APPLICATION_JSON)) -// .andExpect(status().isOk()); -// -// } + @Test + @WithMockCustomUser + @DisplayName("프로젝트 고도화 계획을 제안 받는다") + void getProjectPlan() throws Exception { + + // given + List features = new ArrayList<>(Arrays.asList("게시물 업로드", "좋아요 누르는 기능")); + List techStacks = new ArrayList<>(Arrays.asList("Springboot", "React", "mySQL")); + List plans = new ArrayList<>(Arrays.asList("Spring Security", "Docker")); + String topic = "간단한 게시판"; + + GetProjectPlanRequest request = new GetProjectPlanRequest(topic, features, techStacks, plans); + + String apiResult = "API 결과"; + CompletableFuture result = CompletableFuture.completedFuture(apiResult); + + given(projectService.getProjectPlanAsync(any())).willReturn(result); + + // when + + mvc.perform(post(BASE_URL +"/plans") + .content(objectMapper.writeValueAsString(request)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()); + + } } diff --git a/backend/src/test/java/com/graphy/backend/test/security/WithMockCustomUserSecurityContextFactory.java b/backend/src/test/java/com/graphy/backend/test/security/WithMockCustomUserSecurityContextFactory.java new file mode 100644 index 00000000..efa78f9c --- /dev/null +++ b/backend/src/test/java/com/graphy/backend/test/security/WithMockCustomUserSecurityContextFactory.java @@ -0,0 +1,30 @@ +package com.graphy.backend.test.security; + +import com.graphy.backend.domain.auth.util.MemberInfo; +import com.graphy.backend.domain.member.domain.Member; +import com.graphy.backend.test.util.WithMockCustomUser; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.context.SecurityContext; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.test.context.support.WithSecurityContextFactory; + +import java.util.ArrayList; +import java.util.List; + +public class WithMockCustomUserSecurityContextFactory implements WithSecurityContextFactory { + + @Override + public SecurityContext createSecurityContext(WithMockCustomUser withMockCustomUser) { + SecurityContext context = SecurityContextHolder.createEmptyContext(); + List grantedAuthorities = new ArrayList<>(); + grantedAuthorities.add((GrantedAuthority) () -> "ROLE_USER"); + Member member = Member.builder().id(1L).email("testEamil").password("testPassword").build(); + MemberInfo memberInfo = new MemberInfo(member); + + UsernamePasswordAuthenticationToken authentication = + new UsernamePasswordAuthenticationToken(memberInfo, "testPassword", grantedAuthorities); + context.setAuthentication(authentication); + return context; + } +} diff --git a/backend/src/test/java/com/graphy/backend/test/util/WithMockCustomUser.java b/backend/src/test/java/com/graphy/backend/test/util/WithMockCustomUser.java new file mode 100644 index 00000000..aa8109f6 --- /dev/null +++ b/backend/src/test/java/com/graphy/backend/test/util/WithMockCustomUser.java @@ -0,0 +1,12 @@ +package com.graphy.backend.test.util; + +import com.graphy.backend.test.security.WithMockCustomUserSecurityContextFactory; +import org.springframework.security.test.context.support.WithSecurityContext; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +@WithSecurityContext(factory = WithMockCustomUserSecurityContextFactory.class) +public @interface WithMockCustomUser { +} diff --git a/frontend/package.json b/frontend/package.json index 9607bf1a..082c482a 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -16,10 +16,12 @@ "@toast-ui/editor-plugin-code-syntax-highlight": "^3.1.0", "@toast-ui/editor-plugin-color-syntax": "^3.1.0", "@toast-ui/react-editor": "^3.2.3", + "@tanstack/react-query": "^4.35.3", "@types/node": "20.6.3", "@types/prismjs": "^1.26.1", "@types/react": "18.2.22", "@types/react-dom": "18.2.7", + "@types/uuid": "^9.0.4", "@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/parser": "^6.0.0", "autoprefixer": "10.4.15", @@ -27,6 +29,7 @@ "eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb-typescript": "^17.1.0", "eslint-config-next": "13.5.1", + "lottie-react": "^2.4.0", "next": "^13.5.3", "postcss": "8.4.30", "prettier": "^3.0.3", @@ -37,8 +40,11 @@ "recoil": "^0.7.7", "recoil-persist": "^5.1.0", "short-uuid": "^4.2.2", + "sass": "^1.68.0", + "swiper": "^10.3.0", "tailwindcss": "3.3.3", "typescript": "5.2.2", + "uuid": "^9.0.1", "yup": "^1.3.0" }, "devDependencies": { diff --git a/frontend/src/app/(search)/search-post/[postName]/page.tsx b/frontend/src/app/(search)/search-post/[postName]/page.tsx new file mode 100644 index 00000000..d1774ce3 --- /dev/null +++ b/frontend/src/app/(search)/search-post/[postName]/page.tsx @@ -0,0 +1,95 @@ +'use client' + +import { useEffect, useState } from 'react' +import { useRouter } from 'next/navigation' + +import WriteIcon from '../../../../../public/images/svg/pencil-square.svg' +// TODO: import NavBar from '../../../components/general/NavBar' +import Banner from '../../../../components/main/Banner' +import ProjectCard from '../../../../components/main/ProjectCard' + +type DataObject = { + id: number + createdAt: string + projectName: string + description: string + techTags: string[] + thumbNail: string +} + +type ParamsType = { + params: { + postName: string + } +} + +export default function SearchProjectPage({ params }: ParamsType) { + const [data, setData] = useState([]) // 데이터를 담을 state 선언 + const router = useRouter() // react-router-dom useNavigate 사용 선언 + + function toWrite() { + router.push('/write') + } + + async function getData() { + const res = await fetch( + `${process.env.NEXT_PUBLIC_BASE_URL}/projects?${params.postName}`, + { + headers: { + 'Content-Type': 'application/json', + }, + }, + ) + + const resData = await res.json() + + if (!res.ok) { + alert('검색 결과가 없습니다.') + router.push('/') + throw new Error('프로젝트 검색에 실패했습니다.') + } + setData(resData.data) + } + + useEffect(() => { + getData() + }, [params]) + + return ( +
+ {/* TODO: */} + + +
+ {/* 프로젝트 공유 버튼 */} + + +
+ {/* All */} +
+
+
+ {data.map((item, i) => ( +
+ +
+ ))} +
+
+
+
+ ) +} diff --git a/frontend/src/app/(search)/search-post/page.tsx b/frontend/src/app/(search)/search-post/page.tsx deleted file mode 100644 index e69de29b..00000000 diff --git a/frontend/src/app/(search)/search-user/[userName]/page.tsx b/frontend/src/app/(search)/search-user/[userName]/page.tsx new file mode 100644 index 00000000..ae4ce3de --- /dev/null +++ b/frontend/src/app/(search)/search-user/[userName]/page.tsx @@ -0,0 +1,138 @@ +'use client' + +import { useEffect, useState } from 'react' +import { useRouter } from 'next/navigation' +import { v4 as uuidv4 } from 'uuid' +import Image from 'next/image' + +import WriteIcon from '../../../../../public/images/svg/pencil-square.svg' +import ProfileIcon from '../../../../../public/images/svg/profileIcon.svg' +// TODO: import NavBar from '../../../components/general/NavBar' +import Banner from '../../../../components/main/Banner' + +type DataObject = { + nickname: string + email: string +} + +type ParamsType = { + params: { + userName: string + } +} + +export default function SearchUserPage({ params }: ParamsType) { + const [data, setData] = useState([]) // 데이터를 담을 state 선언 + const [hoveredEmail, setHoveredEmail] = useState('') + const router = useRouter() + const accessToken = + typeof window !== 'undefined' ? sessionStorage.getItem('accessToken') : null + const persistToken = + typeof window !== 'undefined' ? localStorage.getItem('persistToken') : null + + function handleMouseEnter(email: string) { + setHoveredEmail(email) + } + + function handleMouseLeave() { + setHoveredEmail('') + } + + function toWrite() { + router.push('/write') + } + + async function getData() { + const res = await fetch( + `${process.env.NEXT_PUBLIC_BASE_URL}/members?nickname=${params.userName}`, + { + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${accessToken || persistToken}`, + }, + }, + ) + + const resData = await res.json() + + if (resData.data.length === 0) { + setData([{ nickname: '검색 결과가 없습니다.', email: '' }]) + } else { + setData(resData.data) + } + + if (!res.ok) { + alert('검색 결과가 없습니다.') + router.push('/') + throw new Error('검색 결과가 없습니다.') + } + } + + useEffect(() => { + getData() + }, [params]) + + return ( +
+ {/* TODO: */} + + +
+ {/* 프로젝트 공유 버튼 */} + + +
+ {/* All */} +
+
+
+ {data.map((item) => ( +
+ {item.nickname === '검색 결과가 없습니다.' ? ( +
+ {item.nickname} +
+ ) : ( +
handleMouseEnter(item.email)} + onMouseLeave={handleMouseLeave} + > + ProfileIcon + + {item.nickname} + {hoveredEmail === item.email && ( + + {item.email} + + )} + +
+ )} +
+ ))} +
+
+
+
+ ) +} diff --git a/frontend/src/app/(search)/search-user/page.tsx b/frontend/src/app/(search)/search-user/page.tsx deleted file mode 100644 index e69de29b..00000000 diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx index 12e59501..b8733d8a 100644 --- a/frontend/src/app/layout.tsx +++ b/frontend/src/app/layout.tsx @@ -1,7 +1,7 @@ import './globals.css' import type { Metadata } from 'next' import { Inter } from 'next/font/google' -import RecoilRootProvider from '../utils/recoilRootProvider' +import Provider from '../components/general/Provider' const inter = Inter({ subsets: ['latin'] }) @@ -18,7 +18,7 @@ export default function RootLayout({ return ( - {children} + {children} ) diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx index 3d494060..e0157123 100644 --- a/frontend/src/app/page.tsx +++ b/frontend/src/app/page.tsx @@ -1,4 +1,130 @@ -export default function Home() { - // eslint-disable-next-line no-useless-return - return +'use client' + +import { useInfiniteQuery } from '@tanstack/react-query' +import { useEffect } from 'react' +import { useRouter } from 'next/navigation' +import { useRecoilValue } from 'recoil' +import Image from 'next/image' + +import WriteIcon from '../../public/images/svg/pencil-square.svg' +// TODO: import NavBar from '../components/general/NavBar' +import Banner from '../components/main/Banner' +import ProjectCard from '../components/main/ProjectCard' +import { searchTextState } from '../utils/atoms' + +type DataObject = { + id: number + createdAt: string + projectName: string + description: string + techTags: string[] + thumbNail: string +} + +export default function Main() { + const searchText = useRecoilValue(searchTextState) + + const router = useRouter() + + function toWrite() { + router.push('/write') + } + + async function getData({ pageParam = 1 }) { + const params = new URLSearchParams() + params.set('page', String(pageParam)) + params.set('size', '12') + + const res = await fetch( + `${process.env.NEXT_PUBLIC_BASE_URL}/projects?${params.toString()}`, + { + headers: { + 'Content-Type': 'application/json', + }, + }, + ) + + if (!res.ok) { + throw new Error('프로젝트 검색에 실패했습니다.') + } + + const data = await res.json() + + return data.data + } + + const { data, fetchNextPage, hasNextPage, isFetchingNextPage, status } = + useInfiniteQuery(['projects'], getData, { + getNextPageParam: (lastPage, pages) => + lastPage.length < 12 ? undefined : pages.length + 1, + }) + + useEffect(() => { + if (!isFetchingNextPage) { + const handleScroll = () => { + if ( + document.documentElement.scrollHeight - + document.documentElement.scrollTop === + document.documentElement.clientHeight + ) { + fetchNextPage() + } + } + window.addEventListener('scroll', handleScroll) + } + }, [fetchNextPage, isFetchingNextPage, searchText]) + + if (status === 'loading') { + return Loading... + } + + if (status === 'error') { + return Error fetching data + } + + return ( +
+ {/* TODO: NavBar */} + +
+ {/* 프로젝트 공유 버튼 */} + + +
+ {/* All */} +
+ +
+ {data.pages.map((group, i) => ( +
+ {group.map((item: DataObject) => ( +
+ +
+ ))} +
+ ))} + {hasNextPage && isFetchingNextPage && Loading more...} +
+
+
+ ) } diff --git a/frontend/src/components/general/Provider.tsx b/frontend/src/components/general/Provider.tsx new file mode 100644 index 00000000..c80ce5bc --- /dev/null +++ b/frontend/src/components/general/Provider.tsx @@ -0,0 +1,18 @@ +'use client' + +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { RecoilRoot } from 'recoil' + +const queryClient = new QueryClient() + +export default function QueryProvider({ + children, +}: { + children: React.ReactNode +}) { + return ( + + {children} + + ) +} diff --git a/frontend/src/components/main/Banner.tsx b/frontend/src/components/main/Banner.tsx new file mode 100644 index 00000000..c5d9f34b --- /dev/null +++ b/frontend/src/components/main/Banner.tsx @@ -0,0 +1,52 @@ +import Lottie from 'lottie-react' +import { Pagination, Autoplay } from 'swiper/modules' +import { Swiper, SwiperSlide } from 'swiper/react' +import 'swiper/css' +import 'swiper/scss/pagination' +import lotties from '../../utils/lotties' + +export default function Banner() { + return ( +
+ + +
+

+ 프로젝트 기록과 공유의 공간, Graphy +

+

+ Graphy와 함께 성장해보세요. +

+
+
+ +
+
+

+ 프로젝트 공유하러 출발! +

+

+ Graphy에서 누구나 프로젝트를 작성하고 공유할 수 있습니다. 이제 + 출발하세요! +

+
+ +
+
+
+
+ ) +} diff --git a/frontend/src/components/main/ProjectCard.tsx b/frontend/src/components/main/ProjectCard.tsx new file mode 100644 index 00000000..30e3b5f1 --- /dev/null +++ b/frontend/src/components/main/ProjectCard.tsx @@ -0,0 +1,113 @@ +'use client' + +import { useRouter } from 'next/navigation' +import { useRecoilState } from 'recoil' +import Image from 'next/image' +import project from '../../../public/images/png/project.png' + +import { projectIdState } from '../../utils/atoms' +import AllStacks from '../../utils/stacks' + +type ProjectCardProps = { + items: { + id: number + createdAt: string + projectName: string + description: string + techTags: string[] + thumbNail: string + } + index: number +} + +export default function ProjectCard({ items, index }: ProjectCardProps) { + const [, setProjectId] = useRecoilState(projectIdState) + const router = useRouter() + + function findImage(tag: string) { + return AllStacks.map((x) => x.image)[ + AllStacks.map((x) => x.name).findIndex((x) => x === tag) + ] + } + + function toRead() { + const urlToCheck = `${process.env.NEXT_PUBLIC_BASE_URL}/projects/${items.id}` + + if ( + !navigator.onLine && + 'serviceWorker' in navigator && + navigator.serviceWorker.controller + ) { + const messageChannel = new MessageChannel() + + messageChannel.port1.onmessage = (event) => { + if (event.data.hasMatch) { + router.push(`/read/${items.id}`) + setProjectId(items.id) + } else { + alert('오프라인 상태입니다. 네트워크 연결을 확인해주세요.') + } + } + + Promise.resolve().then(() => { + if (navigator.serviceWorker.controller) { + navigator.serviceWorker.controller.postMessage( + { action: 'cache-contains', url: urlToCheck }, + [messageChannel.port2], + ) + } + }) + } else { + router.push(`/read/${items.id}`) + setProjectId(items.id) + } + } + + return ( + + ) +} diff --git a/frontend/src/utils/atoms.ts b/frontend/src/utils/atoms.ts index cf1ad0a0..0dbb6a15 100644 --- a/frontend/src/utils/atoms.ts +++ b/frontend/src/utils/atoms.ts @@ -30,7 +30,7 @@ const contentsState = atom({ default: '', }) -const autoLoginState = atom({ +const autoLoginState = atom({ key: 'autoLoginState', default: false, effects_UNSTABLE: [persistAtom], @@ -42,6 +42,11 @@ const projectIdState = atom({ effects_UNSTABLE: [persistAtom], }) +const searchTextState = atom({ + key: 'searchTextState', + default: '', +}) + export { titleState, tldrState, @@ -50,4 +55,5 @@ export { contentsState, autoLoginState, projectIdState, + searchTextState, } diff --git a/frontend/src/utils/recoilRootProvider.tsx b/frontend/src/utils/recoilRootProvider.tsx deleted file mode 100644 index 32768a57..00000000 --- a/frontend/src/utils/recoilRootProvider.tsx +++ /dev/null @@ -1,11 +0,0 @@ -'use client' - -import { RecoilRoot } from 'recoil' - -export default function RecoilRootProvider({ - children, -}: { - children: React.ReactNode -}) { - return {children} -} diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 5f97e1da..03824099 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -1189,6 +1189,19 @@ dependencies: tslib "^2.4.0" +"@tanstack/query-core@4.35.7": + version "4.35.7" + resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-4.35.7.tgz#31d6f520ab8abedb6024d2d870af8afca764d048" + integrity sha512-PgDJtX75ubFS0WCYFM7DqEoJ4QbxU3S5OH3gJSI40xr7UVVax3/J4CM3XUMOTs+EOT5YGEfssi3tfRVGte4DEw== + +"@tanstack/react-query@^4.35.3": + version "4.35.7" + resolved "https://registry.yarnpkg.com/@tanstack/react-query/-/react-query-4.35.7.tgz#35a1db50156411b2a9eb68a020bae416948939db" + integrity sha512-0MankquP/6EOM2ATfEov6ViiKemey5uTbjGlFMX1xGotwNaqC76YKDMJdHumZupPbZcZPWAeoPGEHQmVKIKoOQ== + dependencies: + "@tanstack/query-core" "4.35.7" + use-sync-external-store "^1.2.0" + "@toast-ui/editor-plugin-code-syntax-highlight@^3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@toast-ui/editor-plugin-code-syntax-highlight/-/editor-plugin-code-syntax-highlight-3.1.0.tgz#3a8b537e03ec495bde8a25d2571a1c28caaa0a4b" @@ -1224,11 +1237,6 @@ dependencies: "@toast-ui/editor" "^3.2.2" -"@types/crypto-js@^4.0.2": - version "4.1.2" - resolved "https://registry.yarnpkg.com/@types/crypto-js/-/crypto-js-4.1.2.tgz#fb56b34f397d9ae2335611e416f15e7d65e276e6" - integrity sha512-t33RNmTu5ufG/sorROIafiCVJMx3jz95bXUMoPAZcUD14fxMXnuTzqzXZoxpR0tNx2xpw11Dlmem9vGCsrSOfA== - "@types/json-schema@^7.0.12": version "7.0.13" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.13.tgz#02c24f4363176d2d18fc8b70b9f3c54aba178a85" @@ -1254,13 +1262,6 @@ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.6.tgz#bbf819813d6be21011b8f5801058498bec555572" integrity sha512-RK/kBbYOQQHLYj9Z95eh7S6t7gq4Ojt/NT8HTk8bWVhA5DaF+5SMnxHKkP4gPNN3wAZkKP+VjAf0ebtYzf+fxg== -"@types/quill@^1.3.10": - version "1.3.10" - resolved "https://registry.yarnpkg.com/@types/quill/-/quill-1.3.10.tgz#dc1f7b6587f7ee94bdf5291bc92289f6f0497613" - integrity sha512-IhW3fPW+bkt9MLNlycw8u8fWb7oO7W5URC9MfZYHBlA24rex9rs23D5DETChu1zvgVdc5ka64ICjJOgQMr6Shw== - dependencies: - parchment "^1.1.2" - "@types/react-dom@18.2.7": version "18.2.7" resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.7.tgz#67222a08c0a6ae0a0da33c3532348277c70abb63" @@ -1287,6 +1288,11 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.2.tgz#31f6eec1ed7ec23f4f05608d3a2d381df041f564" integrity sha512-7aqorHYgdNO4DM36stTiGO3DvKoex9TQRwsJU6vMaFGyqpBA1MNZkz+PG3gaNUPpTAOYhT1WR7M1JyA3fbS9Cw== +"@types/uuid@^9.0.4": + version "9.0.4" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.4.tgz#e884a59338da907bda8d2ed03e01c5c49d036f1c" + integrity sha512-zAuJWQflfx6dYJM62vna+Sn5aeSWhh3OB+wfUEACNcqUSc0AGc5JKl+ycL1vrH7frGTXhJchYjE1Hak8L819dA== + "@typescript-eslint/eslint-plugin@^6.0.0": version "6.7.2" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.2.tgz#f18cc75c9cceac8080a9dc2e7d166008c5207b9f" @@ -1547,22 +1553,6 @@ available-typed-arrays@^1.0.5: resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== -aws-sdk@^2.1268.0: - version "2.1466.0" - resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1466.0.tgz#ad7f4766b1d5feb54dacd3289e7a2e033803838e" - integrity sha512-wkpWe0TBNziEI5wNw2twRofCaNQAgQ+v91HoPylmcuD5qqgRm6hoV7M5NSOMKO8ALlglZdR66EmGusaZ2dMJwA== - dependencies: - buffer "4.9.2" - events "1.1.1" - ieee754 "1.1.13" - jmespath "0.16.0" - querystring "0.2.0" - sax "1.2.1" - url "0.10.3" - util "^0.12.4" - uuid "8.0.0" - xml2js "0.5.0" - axe-core@^4.6.2: version "4.8.1" resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.8.1.tgz#6948854183ee7e7eae336b9877c5bafa027998ea" @@ -1580,11 +1570,6 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base64-js@^1.0.2, base64-js@^1.3.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" - integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== - binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" @@ -1620,23 +1605,6 @@ browserslist@^4.21.10: node-releases "^2.0.13" update-browserslist-db "^1.0.11" -buffer@4.9.2: - version "4.9.2" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" - integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - isarray "^1.0.0" - -buffer@^6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" - integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.2.1" - busboy@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" @@ -1675,7 +1643,7 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chokidar@^3.5.3: +"chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== @@ -1695,11 +1663,6 @@ client-only@0.0.1: resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== -clone@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" - integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w== - color-convert@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" @@ -1736,11 +1699,6 @@ cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" -crypto-js@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-4.1.1.tgz#9e485bcf03521041bd85844786b83fb7619736cf" - integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw== - cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" @@ -1770,18 +1728,6 @@ debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: dependencies: ms "2.1.2" -deep-equal@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" - integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== - dependencies: - is-arguments "^1.0.4" - is-date-object "^1.0.1" - is-regex "^1.0.4" - object-is "^1.0.1" - object-keys "^1.1.1" - regexp.prototype.flags "^1.2.0" - deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -2200,31 +2146,11 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -eventemitter3@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-2.0.3.tgz#b5e1079b59fb5e1ba2771c0a993be060a58c99ba" - integrity sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg== - -events@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" - integrity sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw== - -extend@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-diff@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.1.2.tgz#4b62c42b8e03de3f848460b639079920695d0154" - integrity sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig== - fast-glob@^3.2.12, fast-glob@^3.2.9, fast-glob@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.1.tgz#784b4e897340f3dbbef17413b3f11acf03c874c4" @@ -2507,26 +2433,16 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" -highlight.js@^11.8.0: - version "11.8.0" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.8.0.tgz#966518ea83257bae2e7c9a48596231856555bb65" - integrity sha512-MedQhoqVdr0U6SSnWPzfiadUcDHfN/Wzq25AkXiQv9oiOO/sG0S7XkvpFIqWBl9Yq1UYyYOOVORs5UW2XlPyzg== - -ieee754@1.1.13: - version "1.1.13" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" - integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== - -ieee754@^1.1.4, ieee754@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" - integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== - ignore@^5.2.0, ignore@^5.2.4: version "5.2.4" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== +immutable@^4.0.0: + version "4.3.4" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.4.tgz#2e07b33837b4bb7662f288c244d1ced1ef65a78f" + integrity sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA== + import-fresh@^3.2.1: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" @@ -2548,7 +2464,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.3: +inherits@2: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -2562,14 +2478,6 @@ internal-slot@^1.0.5: has "^1.0.3" side-channel "^1.0.4" -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" @@ -2639,7 +2547,7 @@ is-finalizationregistry@^1.0.2: dependencies: call-bind "^1.0.2" -is-generator-function@^1.0.10, is-generator-function@^1.0.7: +is-generator-function@^1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== @@ -2680,7 +2588,7 @@ is-path-inside@^3.0.3: resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== -is-regex@^1.0.4, is-regex@^1.1.4: +is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== @@ -2714,7 +2622,7 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" -is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.3, is-typed-array@^1.1.9: +is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.9: version "1.1.12" resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== @@ -2741,11 +2649,6 @@ is-weakset@^2.0.1: call-bind "^1.0.2" get-intrinsic "^1.1.1" -isarray@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - isarray@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" @@ -2772,11 +2675,6 @@ jiti@^1.18.2: resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.20.0.tgz#2d823b5852ee8963585c8dd8b7992ffc1ae83b42" integrity sha512-3TV69ZbrvV6U5DfQimop50jE9Dl6J8O1ja1dvBbMba/sZ3YBEQqJ2VZRoQPVnhlzjNtU1vaXRZVrVjU4qtm8yA== -jmespath@0.16.0: - version "0.16.0" - resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.16.0.tgz#b15b0a85dfd4d930d43e69ed605943c802785076" - integrity sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw== - "js-tokens@^3.0.0 || ^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -2870,11 +2768,6 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash@^4.17.4: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" @@ -2882,6 +2775,18 @@ loose-envify@^1.1.0, loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" +lottie-react@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/lottie-react/-/lottie-react-2.4.0.tgz#f7249eee2b1deee70457a2d142194fdf2456e4bd" + integrity sha512-pDJGj+AQlnlyHvOHFK7vLdsDcvbuqvwPZdMlJ360wrzGFurXeKPr8SiRCjLf3LrNYKANQtSsh5dz9UYQHuqx4w== + dependencies: + lottie-web "^5.10.2" + +lottie-web@^5.10.2: + version "5.12.2" + resolved "https://registry.yarnpkg.com/lottie-web/-/lottie-web-5.12.2.tgz#579ca9fe6d3fd9e352571edd3c0be162492f68e5" + integrity sha512-uvhvYPC8kGPjXT3MyKMrL3JitEAmDMp30lVkuq/590Mw9ok6pWcFCwXJveo0t5uqYw1UREQHofD+jVpdjBv8wg== + lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -2997,14 +2902,6 @@ object-inspect@^1.12.3, object-inspect@^1.9.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== -object-is@^1.0.1: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" @@ -3103,11 +3000,6 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" -parchment@^1.1.2, parchment@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/parchment/-/parchment-1.1.4.tgz#aeded7ab938fe921d4c34bc339ce1168bc2ffde5" - integrity sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg== - parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -3318,58 +3210,16 @@ prosemirror-view@^1.18.7, prosemirror-view@^1.27.0, prosemirror-view@^1.31.0: prosemirror-state "^1.0.0" prosemirror-transform "^1.1.0" -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw== - punycode@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g== - queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== -quill-delta@^3.6.2: - version "3.6.3" - resolved "https://registry.yarnpkg.com/quill-delta/-/quill-delta-3.6.3.tgz#b19fd2b89412301c60e1ff213d8d860eac0f1032" - integrity sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg== - dependencies: - deep-equal "^1.0.1" - extend "^3.0.2" - fast-diff "1.1.2" - -quill@^1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/quill/-/quill-1.3.7.tgz#da5b2f3a2c470e932340cdbf3668c9f21f9286e8" - integrity sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g== - dependencies: - clone "^2.1.1" - deep-equal "^1.0.1" - eventemitter3 "^2.0.3" - extend "^3.0.2" - parchment "^1.1.4" - quill-delta "^3.6.2" - -react-aws-s3-typescript@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/react-aws-s3-typescript/-/react-aws-s3-typescript-1.1.5.tgz#ee4e7a206a3cf131c2ecff8c5491c71ff5cd74c6" - integrity sha512-CqVFMUPRaNXwton+98A1ZrqtMcJ4+9u/zQE3Y5aW5BLMFv/LXH0yrn9l73AVgOsujs0+Xwekss/M8sGeF14G3Q== - dependencies: - "@types/crypto-js" "^4.0.2" - aws-sdk "^2.1268.0" - buffer "^6.0.3" - crypto-js "^4.1.1" - short-uuid "^4.2.0" - react-dom@18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" @@ -3388,15 +3238,6 @@ react-is@^16.13.1: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== -react-quill@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/react-quill/-/react-quill-2.0.0.tgz#67a0100f58f96a246af240c9fa6841b363b3e017" - integrity sha512-4qQtv1FtCfLgoD3PXAur5RyxuUbPXQGOHgTlFie3jtxp43mXDtzCKaOgQ3mLyZfi1PUlyjycfivKelFhy13QUg== - dependencies: - "@types/quill" "^1.3.10" - lodash "^4.17.4" - quill "^1.3.7" - react@18.2.0: version "18.2.0" resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" @@ -3447,7 +3288,7 @@ regenerator-runtime@^0.14.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45" integrity sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA== -regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.5.0, regexp.prototype.flags@^1.5.1: +regexp.prototype.flags@^1.5.0, regexp.prototype.flags@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz#90ce989138db209f81492edd734183ce99f9677e" integrity sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg== @@ -3527,15 +3368,14 @@ safe-regex-test@^1.0.0: get-intrinsic "^1.1.3" is-regex "^1.1.4" -sax@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" - integrity sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA== - -sax@>=0.6.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.3.0.tgz#a5dbe77db3be05c9d1ee7785dbd3ea9de51593d0" - integrity sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA== +sass@^1.68.0: + version "1.68.0" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.68.0.tgz#0034b0cc9a50248b7d1702ac166fd25990023669" + integrity sha512-Lmj9lM/fef0nQswm1J2HJcEsBUba4wgNx2fea6yJHODREoMFnwRpZydBnX/RjyXw2REIwdkbqE4hrTo4qfDBUA== + dependencies: + chokidar ">=3.0.0 <4.0.0" + immutable "^4.0.0" + source-map-js ">=0.6.2 <2.0.0" scheduler@^0.23.0: version "0.23.0" @@ -3577,7 +3417,7 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -short-uuid@^4.2.0, short-uuid@^4.2.2: +short-uuid@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/short-uuid/-/short-uuid-4.2.2.tgz#4bb3d926da04a4a5f34420d17b5551fd6d9d535c" integrity sha512-IE7hDSGV2U/VZoCsjctKX6l5t5ak2jE0+aeGJi3KtvjIUNuZVmHVYUjNBhmo369FIWGDtaieRaO8A83Lvwfpqw== @@ -3599,7 +3439,7 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -source-map-js@^1.0.2: +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== @@ -3705,6 +3545,11 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +swiper@^10.3.0: + version "10.3.1" + resolved "https://registry.yarnpkg.com/swiper/-/swiper-10.3.1.tgz#4d19d7e9d0bd184c30accf2c1b180cfe41b9f4af" + integrity sha512-24Wk3YUdZHxjc9faID97GTu6xnLNia+adMt6qMTZG/HgdSUt4fS0REsGUXJOgpTED0Amh/j+gRGQxsLayJUlBQ== + tailwindcss@3.3.3: version "3.3.3" resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.3.3.tgz#90da807393a2859189e48e9e7000e6880a736daf" @@ -3895,40 +3740,26 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -url@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64" - integrity sha512-hzSUW2q06EqL1gKM/a+obYHLIO6ct2hwPuviqTTOcfFVc61UbfJ2Q32+uGL/HCPxKqrdGB5QUwIe7UqlDgwsOQ== - dependencies: - punycode "1.3.2" - querystring "0.2.0" +use-sync-external-store@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" + integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== util-deprecate@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -util@^0.12.4: - version "0.12.5" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" - integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - is-typed-array "^1.1.3" - which-typed-array "^1.1.2" - -uuid@8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.0.0.tgz#bc6ccf91b5ff0ac07bbcdbf1c7c4e150db4dbb6c" - integrity sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw== - uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +uuid@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + w3c-keyname@^2.2.0: version "2.2.8" resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-2.2.8.tgz#7b17c8c6883d4e8b86ac8aba79d39e880f8869c5" @@ -3981,7 +3812,7 @@ which-collection@^1.0.1: is-weakmap "^2.0.1" is-weakset "^2.0.1" -which-typed-array@^1.1.11, which-typed-array@^1.1.2, which-typed-array@^1.1.9: +which-typed-array@^1.1.11, which-typed-array@^1.1.9: version "1.1.11" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.11.tgz#99d691f23c72aab6768680805a271b69761ed61a" integrity sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew== @@ -4004,19 +3835,6 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -xml2js@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7" - integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA== - dependencies: - sax ">=0.6.0" - xmlbuilder "~11.0.0" - -xmlbuilder@~11.0.0: - version "11.0.1" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" - integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== - yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"