diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 926756e..870bd85 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -4,23 +4,24 @@ module.exports = { es2021: true, }, extends: [ - "standard-with-typescript", - "plugin:react/recommended", - "prettier", - "plugin:prettier/recommended", - "plugin:storybook/recommended", + 'standard-with-typescript', + 'plugin:react/recommended', + 'prettier', + 'plugin:prettier/recommended', + 'plugin:storybook/recommended', + 'eslint-config-prettier', ], parserOptions: { - ecmaVersion: "latest", - sourceType: "module", - project: "./tsconfig.json", + ecmaVersion: 'latest', + sourceType: 'module', + //project: './tsconfig.json', }, - plugins: ["react", "@typescript-eslint"], + plugins: ['react', '@typescript-eslint'], rules: { - "react/react-in-jsx-scope": "off", - "@typescript-eslint/explicit-function-return-type": "off", - "@typescript-eslint/triple-slash-reference": "off", - "@typescript-eslint/no-non-null-assertion": "off", + 'react/react-in-jsx-scope': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/triple-slash-reference': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', }, - ignorePatterns: [".eslintrc.cjs", "vite.config.ts"], + ignorePatterns: ['.eslintrc.cjs', 'vite.config.ts'], }; diff --git a/index.html b/index.html index 96e1ec4..97194af 100644 --- a/index.html +++ b/index.html @@ -7,6 +7,11 @@
+ + diff --git a/mockServer/mockData.js b/mockServer/mockData.js new file mode 100644 index 0000000..b272f24 --- /dev/null +++ b/mockServer/mockData.js @@ -0,0 +1,669 @@ +const mockData = { + memories: [ + { + id: '1', + title: '(추억)얌샘김밥 갔다온 건에 대하여..', + category: '여행', + tags: [ + { + id: 1, + name: '분식', + color: 'red', + }, + ], + visitedAt: '2023-07-14', + content: + '봄은 동틀 무렵. 산 능선이 점점 하얗게 변하면서 조금씩 밝아지고, 그 위로 보랏빛 구름이 가늘게 떠 있는 풍경이 멋있다. 여름은 밤. 달이 뜨면 더할 나위 없이 좋고, 칠흑같이 어두운 밤에도 반딧불이가 반짝반짝 여기저기에서 날아다니는 광경이 근사하다. 반딧불이가 한 마리나 두 마리 희미하게 빛을 내며 지나가는 것도 운치 있다. 비 오는 밤도 좋다. ', + star: 5, + images: [ + 'https://images.unsplash.com/photo-1480714378408-67cf0d13bc1b?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxleHBsb3JlLWZlZWR8Mnx8fGVufDB8fHx8fA%3D%3D&w=1000&q=80', + ], + location: { + latitude: 37.5741, + longitude: 126.9768, + }, + }, + { + id: '2', + title: '(후회)1얌샘김밥 갔다온 건에 대하여2..', + category: '음식점', + tags: [ + { + id: 1, + name: '분식', + color: 'blue', + }, + ], + visitedAt: '2023-07-14', + content: + '최고의 시간이었고, 최악의 시간이었다. 지혜의 시대였고, 어리석음의 시대였다. 믿음의 세기였고, 불신의 세기였다. 빛의 계절이었고, 어둠의 계절이었다. 희망의 봄이었고, 절망의 겨울이었다. 우리 앞에 모든 것이 있었고, 우리 앞에 아무것도 없었다', + star: 1, + images: [ + 'https://images.unsplash.com/photo-1444723121867-7a241cacace9?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2940&q=80', + ], + location: { + latitude: 132.32, + longitude: 82.2123, + }, + }, + { + id: '3', + title: '(추억)마카롱 카페에서 휴식', + category: '카페', + tags: [ + { + id: 2, + name: '디저트', + color: 'yellow', + }, + ], + visitedAt: '2023-07-15', + content: + '그래서 우리는 계속 앞으로 나아가는 것이다. 흐름을 거슬러가는 조각배처럼, 끊임없이 과거로 떠밀려가면서도.', + star: 4, + images: [ + 'https://images.unsplash.com/photo-1514565131-fce0801e5785?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2156&q=80', + ], + location: { + latitude: 132.43, + longitude: 82.102, + }, + }, + { + id: '4', + title: '(후회)마카롱 카페에서 휴식', + category: '카페', + tags: [ + { + id: 2, + name: '디저트', + color: 'FF00FF', + }, + ], + visitedAt: '2023-07-15', + content: + ' 겨울은 새벽녘. 눈이 내리면 더없이 좋고, 서리가 하얗게 내린 것도 멋있다. 아주 추운 날 급하게 피운 숯을 들고 지나가는 모습은 그 나름대로 겨울에 어울리는 풍경이다. 이때 숯을 뜨겁게 피우지 않으면 화로 속이 금방 흰 재로 변해 버려 좋지 않다', + star: 2, + images: [ + 'https://images.unsplash.com/photo-1444084316824-dc26d6657664?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80', + ], + location: { + latitude: 132.43, + longitude: 82.102, + }, + }, + { + id: '5', + title: '마카롱 카페에서 휴식', + category: '카페', + tags: [ + { + id: 2, + name: '디저트', + color: 'FF00FF', + }, + ], + visitedAt: '2023-07-15', + content: + '가을은 해 질 녘. 석양이 비추고 산봉우리가 가깝게 보일 때 까마귀가 둥지를 향해 세 마리나 네 마리, 아니면 두 마리씩 떼 지어 날아가는 모습에 가슴이 뭉클해진다. 기러기가 줄지어 저 멀리로 날아가는 광경은 한층 더 정취 있다. 해가 진 후 바람 소리나 벌레 소리가 들려오는 것도 기분 좋다.', + star: 3, + images: [ + 'https://images.unsplash.com/photo-1540959733332-eab4deabeeaf?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2094&q=80', + ], + location: { + latitude: 132.43, + longitude: 82.102, + }, + }, + + { + id: '6', + title: '마카롱 카페에서 휴식', + category: '카페', + tags: [ + { + id: 2, + name: '디저트', + color: 'FF00FF', + }, + ], + visitedAt: '2023-07-15', + star: 3, + images: ['a1s2d3f4g5.png'], + location: { + latitude: 132.43, + longitude: 82.102, + }, + }, + { + id: '7', + title: '얌샘김밥 갔다온 건에 대하여5..', + category: '여행', + tags: [ + { + id: 1, + name: '분식', + color: '000FFF', + }, + ], + visitedAt: '2023-07-14', + content: + '봄은 동틀 무렵. 산 능선이 점점 하얗게 변하면서 조금씩 밝아지고, 그 위로 보랏빛 구름이 가늘게 떠 있는 풍경이 멋있다. 여름은 밤. 달이 뜨면 더할 나위 없이 좋고, 칠흑같이 어두운 밤에도 반딧불이가 반짝반짝 여기저기에서 날아다니는 광경이 근사하다. 반딧불이가 한 마리나 두 마리 희미하게 빛을 내며 지나가는 것도 운치 있다. 비 오는 밤도 좋다. 가을은 해 질 녘. 석양이 비추고 산봉우리가 가깝게 보일 때 까마귀가 둥지를 향해 세 마리나 네 마리, 아니면 두 마리씩 떼 지어 날아가는 모습에 가슴이 뭉클해진다. 기러기가 줄지어 저 멀리로 날아가는 광경은 한층 더 정취 있다. 해가 진 후 바람 소리나 벌레 소리가 들려오는 것도 기분 좋다. 겨울은 새벽녘. 눈이 내리면 더없이 좋고, 서리가 하얗게 내린 것도 멋있다. 아주 추운 날 급하게 피운 숯을 들고 지나가는 모습은 그 나름대로 겨울에 어울리는 풍경이다. 이때 숯을 뜨겁게 피우지 않으면 화로 속이 금방 흰 재로 변해 버려 좋지 않다', + star: 1, + images: [ + 'https://images.unsplash.com/photo-1480714378408-67cf0d13bc1b?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxleHBsb3JlLWZlZWR8Mnx8fGVufDB8fHx8fA%3D%3D&w=1000&q=80', + ], + location: { + latitude: 132.32, + longitude: 82.2123, + }, + }, + { + id: '8', + title: '얌샘김밥 갔다온 건에 대하여6..', + category: '음식점', + tags: [ + { + id: 1, + name: '분식', + color: '000FFF', + }, + ], + visitedAt: '2023-07-14', + content: + '최고의 시간이었고, 최악의 시간이었다. 지혜의 시대였고, 어리석음의 시대였다. 믿음의 세기였고, 불신의 세기였다. 빛의 계절이었고, 어둠의 계절이었다. 희망의 봄이었고, 절망의 겨울이었다. 우리 앞에 모든 것이 있었고, 우리 앞에 아무것도 없었다', + star: 1, + images: [ + 'https://images.unsplash.com/photo-1444723121867-7a241cacace9?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2940&q=80', + ], + location: { + latitude: 132.32, + longitude: 82.2123, + }, + }, + { + id: '9', + title: '마카롱 카페에서 휴식', + category: '카페', + tags: [ + { + id: 2, + name: '디저트', + color: 'FF00FF', + }, + ], + visitedAt: '2023-07-15', + content: + '그래서 우리는 계속 앞으로 나아가는 것이다. 흐름을 거슬러가는 조각배처럼, 끊임없이 과거로 떠밀려가면서도.', + star: 3, + images: [ + 'https://images.unsplash.com/photo-1514565131-fce0801e5785?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2156&q=80', + ], + location: { + latitude: 132.43, + longitude: 82.102, + }, + }, + { + id: '10', + title: '마카롱 카페에서 휴식', + category: '카페', + tags: [ + { + id: 2, + name: '디저트', + color: 'FF00FF', + }, + ], + visitedAt: '2023-07-15', + star: 3, + images: [ + 'https://images.unsplash.com/photo-1444084316824-dc26d6657664?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80', + ], + location: { + latitude: 132.43, + longitude: 82.102, + }, + }, + { + id: '11', + title: '마카롱 카페에서 휴식', + category: '카페', + tags: [ + { + id: 2, + name: '디저트', + color: 'FF00FF', + }, + ], + visitedAt: '2023-07-15', + star: 3, + images: [ + 'https://images.unsplash.com/photo-1540959733332-eab4deabeeaf?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2094&q=80', + ], + location: { + latitude: 132.43, + longitude: 82.102, + }, + }, + + { + id: '12', + title: '마카롱 카페에서 휴식', + category: '카페', + tags: [ + { + id: 2, + name: '디저트', + color: 'FF00FF', + }, + ], + visitedAt: '2023-07-15', + star: 3, + images: ['a1s2d3f4g5.png'], + location: { + latitude: 132.43, + longitude: 82.102, + }, + }, + { + id: '13', + title: '얌샘김밥 갔다온 건에 대하여..', + category: '여행', + tags: [ + { + id: 1, + name: '분식', + color: '000FFF', + }, + ], + visitedAt: '2023-07-14', + content: + '봄은 동틀 무렵. 산 능선이 점점 하얗게 변하면서 조금씩 밝아지고, 그 위로 보랏빛 구름이 가늘게 떠 있는 풍경이 멋있다. 여름은 밤. 달이 뜨면 더할 나위 없이 좋고, 칠흑같이 어두운 밤에도 반딧불이가 반짝반짝 여기저기에서 날아다니는 광경이 근사하다. 반딧불이가 한 마리나 두 마리 희미하게 빛을 내며 지나가는 것도 운치 있다. 비 오는 밤도 좋다. 가을은 해 질 녘. 석양이 비추고 산봉우리가 가깝게 보일 때 까마귀가 둥지를 향해 세 마리나 네 마리, 아니면 두 마리씩 떼 지어 날아가는 모습에 가슴이 뭉클해진다. 기러기가 줄지어 저 멀리로 날아가는 광경은 한층 더 정취 있다. 해가 진 후 바람 소리나 벌레 소리가 들려오는 것도 기분 좋다. 겨울은 새벽녘. 눈이 내리면 더없이 좋고, 서리가 하얗게 내린 것도 멋있다. 아주 추운 날 급하게 피운 숯을 들고 지나가는 모습은 그 나름대로 겨울에 어울리는 풍경이다. 이때 숯을 뜨겁게 피우지 않으면 화로 속이 금방 흰 재로 변해 버려 좋지 않다', + star: 1, + images: [ + 'https://images.unsplash.com/photo-1480714378408-67cf0d13bc1b?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxleHBsb3JlLWZlZWR8Mnx8fGVufDB8fHx8fA%3D%3D&w=1000&q=80', + ], + location: { + latitude: 132.32, + longitude: 82.2123, + }, + }, + { + id: '14', + title: '얌샘김밥 갔다온 건에 대하여2..', + category: '음식점', + tags: [ + { + id: 1, + name: '분식', + color: '000FFF', + }, + ], + visitedAt: '2023-07-14', + content: + '최고의 시간이었고, 최악의 시간이었다. 지혜의 시대였고, 어리석음의 시대였다. 믿음의 세기였고, 불신의 세기였다. 빛의 계절이었고, 어둠의 계절이었다. 희망의 봄이었고, 절망의 겨울이었다. 우리 앞에 모든 것이 있었고, 우리 앞에 아무것도 없었다', + star: 1, + images: [ + 'https://images.unsplash.com/photo-1444723121867-7a241cacace9?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2940&q=80', + ], + location: { + latitude: 132.32, + longitude: 82.2123, + }, + }, + { + id: '15', + title: '마카롱 카페에서 휴식', + category: '카페', + tags: [ + { + id: 2, + name: '디저트', + color: 'FF00FF', + }, + ], + visitedAt: '2023-07-15', + content: + '그래서 우리는 계속 앞으로 나아가는 것이다. 흐름을 거슬러가는 조각배처럼, 끊임없이 과거로 떠밀려가면서도.', + star: 3, + images: [ + 'https://images.unsplash.com/photo-1514565131-fce0801e5785?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2156&q=80', + ], + location: { + latitude: 132.43, + longitude: 82.102, + }, + }, + { + id: '16', + title: '마카롱 카페에서 휴식', + category: '카페', + tags: [ + { + id: 2, + name: '디저트', + color: 'FF00FF', + }, + ], + visitedAt: '2023-07-15', + star: 3, + images: [ + 'https://images.unsplash.com/photo-1444084316824-dc26d6657664?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80', + ], + location: { + latitude: 132.43, + longitude: 82.102, + }, + }, + { + id: '17', + title: '마카롱 카페에서 휴식', + category: '카페', + tags: [ + { + id: 2, + name: '디저트', + color: 'FF00FF', + }, + ], + visitedAt: '2023-07-15', + star: 3, + images: [ + 'https://images.unsplash.com/photo-1540959733332-eab4deabeeaf?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2094&q=80', + ], + location: { + latitude: 132.43, + longitude: 82.102, + }, + }, + + { + id: '18', + title: '마카롱 카페에서 휴식', + category: '카페', + tags: [ + { + id: 2, + name: '디저트', + color: 'FF00FF', + }, + ], + visitedAt: '2023-07-15', + star: 3, + images: ['a1s2d3f4g5.png'], + location: { + latitude: 132.43, + longitude: 82.102, + }, + }, + { + id: '19', + title: '얌샘김밥 갔다온 건에 대하여12..', + category: '여행', + tags: [ + { + id: 1, + name: '분식', + color: '000FFF', + }, + ], + visitedAt: '2023-07-14', + content: + '봄은 동틀 무렵. 산 능선이 점점 하얗게 변하면서 조금씩 밝아지고, 그 위로 보랏빛 구름이 가늘게 떠 있는 풍경이 멋있다. 여름은 밤. 달이 뜨면 더할 나위 없이 좋고, 칠흑같이 어두운 밤에도 반딧불이가 반짝반짝 여기저기에서 날아다니는 광경이 근사하다. 반딧불이가 한 마리나 두 마리 희미하게 빛을 내며 지나가는 것도 운치 있다. 비 오는 밤도 좋다. 가을은 해 질 녘. 석양이 비추고 산봉우리가 가깝게 보일 때 까마귀가 둥지를 향해 세 마리나 네 마리, 아니면 두 마리씩 떼 지어 날아가는 모습에 가슴이 뭉클해진다. 기러기가 줄지어 저 멀리로 날아가는 광경은 한층 더 정취 있다. 해가 진 후 바람 소리나 벌레 소리가 들려오는 것도 기분 좋다. 겨울은 새벽녘. 눈이 내리면 더없이 좋고, 서리가 하얗게 내린 것도 멋있다. 아주 추운 날 급하게 피운 숯을 들고 지나가는 모습은 그 나름대로 겨울에 어울리는 풍경이다. 이때 숯을 뜨겁게 피우지 않으면 화로 속이 금방 흰 재로 변해 버려 좋지 않다', + star: 1, + images: [ + 'https://images.unsplash.com/photo-1480714378408-67cf0d13bc1b?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxleHBsb3JlLWZlZWR8Mnx8fGVufDB8fHx8fA%3D%3D&w=1000&q=80', + ], + location: { + latitude: 132.32, + longitude: 82.2123, + }, + }, + { + id: '20', + title: '얌샘김밥 갔다온 건에 대하여..', + category: '여행', + tags: [ + { + id: 1, + name: '분식', + color: '000FFF', + }, + ], + visitedAt: '2023-07-14', + content: + '봄은 동틀 무렵. 산 능선이 점점 하얗게 변하면서 조금씩 밝아지고, 그 위로 보랏빛 구름이 가늘게 떠 있는 풍경이 멋있다. 여름은 밤. 달이 뜨면 더할 나위 없이 좋고, 칠흑같이 어두운 밤에도 반딧불이가 반짝반짝 여기저기에서 날아다니는 광경이 근사하다. 반딧불이가 한 마리나 두 마리 희미하게 빛을 내며 지나가는 것도 운치 있다. 비 오는 밤도 좋다. 가을은 해 질 녘. 석양이 비추고 산봉우리가 가깝게 보일 때 까마귀가 둥지를 향해 세 마리나 네 마리, 아니면 두 마리씩 떼 지어 날아가는 모습에 가슴이 뭉클해진다. 기러기가 줄지어 저 멀리로 날아가는 광경은 한층 더 정취 있다. 해가 진 후 바람 소리나 벌레 소리가 들려오는 것도 기분 좋다. 겨울은 새벽녘. 눈이 내리면 더없이 좋고, 서리가 하얗게 내린 것도 멋있다. 아주 추운 날 급하게 피운 숯을 들고 지나가는 모습은 그 나름대로 겨울에 어울리는 풍경이다. 이때 숯을 뜨겁게 피우지 않으면 화로 속이 금방 흰 재로 변해 버려 좋지 않다', + star: 1, + images: [ + 'https://images.unsplash.com/photo-1480714378408-67cf0d13bc1b?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxleHBsb3JlLWZlZWR8Mnx8fGVufDB8fHx8fA%3D%3D&w=1000&q=80', + ], + location: { + latitude: 132.32, + longitude: 82.2123, + }, + }, + { + id: '21', + title: '얌샘김밥 갔다온 건에 대하여2..', + category: '음식점', + tags: [ + { + id: 1, + name: '분식', + color: '000FFF', + }, + ], + visitedAt: '2023-07-14', + content: + '최고의 시간이었고, 최악의 시간이었다. 지혜의 시대였고, 어리석음의 시대였다. 믿음의 세기였고, 불신의 세기였다. 빛의 계절이었고, 어둠의 계절이었다. 희망의 봄이었고, 절망의 겨울이었다. 우리 앞에 모든 것이 있었고, 우리 앞에 아무것도 없었다', + star: 1, + images: [ + 'https://images.unsplash.com/photo-1444723121867-7a241cacace9?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2940&q=80', + ], + location: { + latitude: 132.32, + longitude: 82.2123, + }, + }, + { + id: '22', + title: '마카롱 카페에서 휴식', + category: '카페', + tags: [ + { + id: 2, + name: '디저트', + color: 'FF00FF', + }, + ], + visitedAt: '2023-07-15', + content: + '그래서 우리는 계속 앞으로 나아가는 것이다. 흐름을 거슬러가는 조각배처럼, 끊임없이 과거로 떠밀려가면서도.', + star: 3, + images: [ + 'https://images.unsplash.com/photo-1514565131-fce0801e5785?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2156&q=80', + ], + location: { + latitude: 132.43, + longitude: 82.102, + }, + }, + { + id: '23', + title: '마카롱 카페에서 휴식', + category: '카페', + tags: [ + { + id: 2, + name: '디저트', + color: 'FF00FF', + }, + ], + visitedAt: '2023-07-15', + star: 3, + images: [ + 'https://images.unsplash.com/photo-1444084316824-dc26d6657664?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80', + ], + location: { + latitude: 132.43, + longitude: 82.102, + }, + }, + { + id: '24', + title: '마카롱 카페에서 휴식', + category: '카페', + tags: [ + { + id: 2, + name: '디저트', + color: 'FF00FF', + }, + ], + visitedAt: '2023-07-15', + star: 3, + images: [ + 'https://images.unsplash.com/photo-1540959733332-eab4deabeeaf?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2094&q=80', + ], + location: { + latitude: 132.43, + longitude: 82.102, + }, + }, + + { + id: '25', + title: '마카롱 카페에서 휴식', + category: '카페', + tags: [ + { + id: 2, + name: '디저트', + color: 'FF00FF', + }, + ], + visitedAt: '2023-07-15', + star: 3, + images: ['a1s2d3f4g5.png'], + location: { + latitude: 132.43, + longitude: 82.102, + }, + }, + { + id: '26', + title: '얌샘김밥 갔다온 건에 대하여5..', + category: '여행', + tags: [ + { + id: 1, + name: '분식', + color: '000FFF', + }, + ], + visitedAt: '2023-07-14', + content: + '봄은 동틀 무렵. 산 능선이 점점 하얗게 변하면서 조금씩 밝아지고, 그 위로 보랏빛 구름이 가늘게 떠 있는 풍경이 멋있다. 여름은 밤. 달이 뜨면 더할 나위 없이 좋고, 칠흑같이 어두운 밤에도 반딧불이가 반짝반짝 여기저기에서 날아다니는 광경이 근사하다. 반딧불이가 한 마리나 두 마리 희미하게 빛을 내며 지나가는 것도 운치 있다. 비 오는 밤도 좋다. 가을은 해 질 녘. 석양이 비추고 산봉우리가 가깝게 보일 때 까마귀가 둥지를 향해 세 마리나 네 마리, 아니면 두 마리씩 떼 지어 날아가는 모습에 가슴이 뭉클해진다. 기러기가 줄지어 저 멀리로 날아가는 광경은 한층 더 정취 있다. 해가 진 후 바람 소리나 벌레 소리가 들려오는 것도 기분 좋다. 겨울은 새벽녘. 눈이 내리면 더없이 좋고, 서리가 하얗게 내린 것도 멋있다. 아주 추운 날 급하게 피운 숯을 들고 지나가는 모습은 그 나름대로 겨울에 어울리는 풍경이다. 이때 숯을 뜨겁게 피우지 않으면 화로 속이 금방 흰 재로 변해 버려 좋지 않다', + star: 1, + images: [ + 'https://images.unsplash.com/photo-1480714378408-67cf0d13bc1b?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxleHBsb3JlLWZlZWR8Mnx8fGVufDB8fHx8fA%3D%3D&w=1000&q=80', + ], + location: { + latitude: 132.32, + longitude: 82.2123, + }, + }, + { + id: '27', + title: '얌샘김밥 갔다온 건에 대하여6..', + category: '음식점', + tags: [ + { + id: 1, + name: '분식', + color: '000FFF', + }, + ], + visitedAt: '2023-07-14', + content: + '최고의 시간이었고, 최악의 시간이었다. 지혜의 시대였고, 어리석음의 시대였다. 믿음의 세기였고, 불신의 세기였다. 빛의 계절이었고, 어둠의 계절이었다. 희망의 봄이었고, 절망의 겨울이었다. 우리 앞에 모든 것이 있었고, 우리 앞에 아무것도 없었다', + star: 1, + images: [ + 'https://images.unsplash.com/photo-1444723121867-7a241cacace9?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2940&q=80', + ], + location: { + latitude: 132.32, + longitude: 82.2123, + }, + }, + { + id: '28', + title: '마카롱 카페에서 휴식', + category: '카페', + tags: [ + { + id: 2, + name: '디저트', + color: 'FF00FF', + }, + ], + visitedAt: '2023-07-15', + content: + '그래서 우리는 계속 앞으로 나아가는 것이다. 흐름을 거슬러가는 조각배처럼, 끊임없이 과거로 떠밀려가면서도.', + star: 3, + images: [ + 'https://images.unsplash.com/photo-1514565131-fce0801e5785?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2156&q=80', + ], + location: { + latitude: 132.43, + longitude: 82.102, + }, + }, + { + id: '29', + title: '마카롱 카페에서 휴식', + category: '카페', + tags: [ + { + id: 2, + name: '디저트', + color: 'FF00FF', + }, + ], + visitedAt: '2023-07-15', + star: 3, + images: [ + 'https://images.unsplash.com/photo-1444084316824-dc26d6657664?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80', + ], + location: { + latitude: 132.43, + longitude: 82.102, + }, + }, + { + id: '30', + title: '마지막 마카롱 카페에서 휴식', + category: '카페', + tags: [ + { + id: 2, + name: '디저트', + color: 'FF00FF', + }, + ], + visitedAt: '2023-07-15', + star: 3, + images: [ + 'https://images.unsplash.com/photo-1540959733332-eab4deabeeaf?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2094&q=80', + ], + location: { + latitude: 132.43, + longitude: 82.102, + }, + }, + ], + pageSize: 10, +}; + +module.exports = mockData; diff --git a/mockServer/package.json b/mockServer/package.json new file mode 100644 index 0000000..c0aca09 --- /dev/null +++ b/mockServer/package.json @@ -0,0 +1,10 @@ +{ + "name": "mockserver", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "dependencies": { + "cors": "^2.8.5", + "express": "^4.18.2" + } +} diff --git a/mockServer/server.ts b/mockServer/server.ts new file mode 100644 index 0000000..54e31b5 --- /dev/null +++ b/mockServer/server.ts @@ -0,0 +1,73 @@ +const mockData = require('./mockData'); + +const express = require('express'); +const app = express(); +const cors = require('cors'); + +const PORT = 3000; // 포트 번호를 원하는 숫자로 변경 가능 + +// 데이터를 저장할 배열 (임시로 메모리에 저장) +app.use(cors()); +// Parse incoming JSON data +app.use(express.json()); + +// 새로운 메모리 추가 +app.post('/memories', (req, res) => { + const newMemory = req.body; + mockData.push(newMemory); + res.status(201).json({ message: 'Memory added successfully' }); +}); + +// 모든 메모리 조회 +app.get('/memories', (req, res) => { + const { page = 1 } = req.query; + // params로 'memories?min=1&max=3&category=cafe&page=0&size=10'와 같이 전달된 쿼리스트링을 받아올 수 있음 + const { min, max, category, size } = req.query; + + const pageSize = 10; // 페이지당 항목 수 + const startIndex = (page - 1) * pageSize; + const endIndex = startIndex + pageSize; + + // 전체 데이터 배열 + const allMemories = mockData.memories; + + // 현재 페이지에 해당하는 데이터 추출 + const paginatedMemories = allMemories + .filter((memory) => { + if (min && max) { + return memory.star >= min && memory.star <= max; + } + if (min) { + return memory.star >= min; + } + if (category) { + return memory.category === category; + } + return true; + }) + .slice(startIndex, endIndex); + + // 전체 페이지 수 계산 + const totalPages = Math.ceil(allMemories.length / pageSize); + + // 응답 데이터 구성 + const response = { + data: paginatedMemories, + nextPage: page < totalPages ? parseInt(page) + 1 : null, + totalPages, + }; + + res.status(200).json(response); +}); + +// 특정 메모리 조회 +app.get('/memory/:id', (req, res) => { + const { id } = req.params; + const memory = mockData.memories.find((memory) => memory.id === id); + res.status(200).json(memory); +}); + +// 서버 시작 +app.listen(PORT, () => { + console.log(`Server is running on port ${PORT}`); +}); diff --git a/mockServer/yarn.lock b/mockServer/yarn.lock new file mode 100644 index 0000000..f6f8c4a --- /dev/null +++ b/mockServer/yarn.lock @@ -0,0 +1,424 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== + +body-parser@1.20.1: + version "1.20.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" + integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== + dependencies: + bytes "3.1.2" + content-type "~1.0.4" + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" + iconv-lite "0.4.24" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.1" + type-is "~1.6.18" + unpipe "1.0.0" + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + +call-bind@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== + dependencies: + safe-buffer "5.2.1" + +content-type@~1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== + +cookie@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== + +cors@^2.8.5: + version "2.8.5" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + +debug@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== + +escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== + +express@^4.18.2: + version "4.18.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" + integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== + dependencies: + accepts "~1.3.8" + array-flatten "1.1.1" + body-parser "1.20.1" + content-disposition "0.5.4" + content-type "~1.0.4" + cookie "0.5.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "2.0.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "1.2.0" + fresh "0.5.2" + http-errors "2.0.0" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "2.4.1" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.7" + qs "6.11.0" + range-parser "~1.2.1" + safe-buffer "5.2.1" + send "0.18.0" + serve-static "1.15.0" + setprototypeof "1.2.0" + statuses "2.0.1" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "2.4.1" + parseurl "~1.3.3" + statuses "2.0.1" + unpipe "~1.0.0" + +forwarded@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" + integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +get-intrinsic@^1.0.2: + version "1.2.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" + integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-proto "^1.0.1" + has-symbols "^1.0.3" + +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + +has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== + dependencies: + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" + +iconv-lite@0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +inherits@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ipaddr.js@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + +ms@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== + +object-assign@^4: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +object-inspect@^1.9.0: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + +parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== + +proxy-addr@~2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" + integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== + dependencies: + forwarded "0.2.0" + ipaddr.js "1.9.1" + +qs@6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" + +range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== + dependencies: + bytes "3.1.2" + http-errors "2.0.0" + iconv-lite "0.4.24" + unpipe "1.0.0" + +safe-buffer@5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== + dependencies: + debug "2.6.9" + depd "2.0.0" + destroy "1.2.0" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "2.0.0" + mime "1.6.0" + ms "2.1.3" + on-finished "2.4.1" + range-parser "~1.2.1" + statuses "2.0.1" + +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.18.0" + +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== + +type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== + +vary@^1, vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== diff --git a/package.json b/package.json index f091ccd..adaf4b3 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "build-storybook": "storybook build" }, "dependencies": { + "@react-google-maps/api": "^2.19.2", "@tanstack/react-query": "^4.32.5", "@vanilla-extract/css": "^1.12.0", "react": "^18.2.0", @@ -49,6 +50,7 @@ "prettier": "^3.0.0", "storybook": "^7.1.0", "typescript": "^5.1.6", - "vite": "^4.4.5" + "vite": "^4.4.5", + "vite-plugin-svgr": "^3.2.0" } } diff --git a/src/App.css b/src/App.css index b9d355d..d62b652 100644 --- a/src/App.css +++ b/src/App.css @@ -1,42 +1,24 @@ -#root { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; +/* 요소 기본 스타일 초기화 */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; } -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; - transition: filter 300ms; -} -.logo:hover { - filter: drop-shadow(0 0 2em #646cffaa); -} -.logo.react:hover { - filter: drop-shadow(0 0 2em #61dafbaa); -} - -@keyframes logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} - -@media (prefers-reduced-motion: no-preference) { - a:nth-of-type(2) .logo { - animation: logo-spin infinite 20s linear; - } -} - -.card { - padding: 2em; +/* 브라우저 기본 스타일 초기화 */ +html, +body { + height: 100%; + font-size: 16px; + margin: 0; } -.read-the-docs { - color: #888; +body { + line-height: 1.5; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, + Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + color: #333; + background-color: #fff; } diff --git a/src/App.tsx b/src/App.tsx index 7263a5e..e69de29 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,20 +0,0 @@ -import './App.css'; -import { - useQuery, - useMutation, - useQueryClient, - QueryClient, - QueryClientProvider, -} from '@tanstack/react-query'; - -const queryClient = new QueryClient(); - -function App() { - return ( - - hello, world! - - ); -} - -export default App; diff --git a/src/assets/Calender.svg b/src/assets/Calender.svg new file mode 100644 index 0000000..d424f8c --- /dev/null +++ b/src/assets/Calender.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/assets/Place.svg b/src/assets/Place.svg new file mode 100644 index 0000000..d9f4ff3 --- /dev/null +++ b/src/assets/Place.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/Star.svg b/src/assets/Star.svg new file mode 100644 index 0000000..1b650a2 --- /dev/null +++ b/src/assets/Star.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/component/Card.css.ts b/src/component/Card.css.ts new file mode 100644 index 0000000..02e1c89 --- /dev/null +++ b/src/component/Card.css.ts @@ -0,0 +1,106 @@ +import { style, keyframes } from '@vanilla-extract/css'; + +export const card = style({ + position: 'relative', + height: '120px', + borderRadius: '4px', + boxShadow: '0 4px 6px rgba(0, 0, 0, 0.2)', + padding: '16px', + marginBottom: '8px', + display: 'flex', + flexDirection: 'column', + alignItems: 'flex-start', + gap: '8px', + background: 'transparent', + //zIndex: '100', +}); + +export const date = style({ + fontSize: '12px', + color: 'gray', + margin: 0, +}); + +export const heading = style({ + fontSize: '16px', + fontWeight: 'bold', + color: 'black', + margin: 0, +}); + +export const description = style({ + fontSize: '12px', + color: 'gray', + margin: 0, + overflow: 'hidden', + display: '-webkit-box', + WebkitLineClamp: 1, + WebkitBoxOrient: 'vertical', + textAlign: 'left', +}); + +export const category = style({ + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + backgroundColor: 'black', + border: '1px solid #333a', + borderRadius: '4px', + color: 'white', + width: '36px', + height: '24px', + fontSize: '12px', + padding: '0px', + textAlign: 'center', +}); + +export const image = style({ + width: '100%', + borderRadius: '4px', +}); + +export const cardImage = style({ + width: '100%', + borderRadius: '4px', +}); + +export const avatarImage = style({ + borderRadius: '50%', +}); + +export const backgroundImage = style({ + position: 'absolute', + width: '100%', + height: '100%', + top: '0', + left: '0', + opacity: '0.25', +}); + +const skeletonPulse = keyframes({ + '0%': { + backgroundColor: '#E0E0E0', + }, + '50%': { + backgroundColor: '#F0F0F0', + }, + '100%': { + backgroundColor: '#E0E0E0', + }, +}); + +const skeleton = style({ + backgroundColor: '#E0E0E0', + borderRadius: '4px', + animation: `${skeletonPulse} 1.5s ease-in-out infinite`, +}); + +export const skeletonDate = style([date, skeleton]); +export const skeletonCategory = style([category, skeleton]); +export const skeletonHeading = style([heading, skeleton, { height: '16px' }]); +export const skeletonDescription = style([ + description, + skeleton, + { height: '12px' }, +]); +export const skeletonImage = style([image, skeleton]); diff --git a/src/component/Card.tsx b/src/component/Card.tsx new file mode 100644 index 0000000..0d1bd4e --- /dev/null +++ b/src/component/Card.tsx @@ -0,0 +1,94 @@ +import type { ReactNode } from 'react'; +import { createContext, useContext } from 'react'; +import { + card, + date, + heading, + backgroundImage, + description, + category, +} from './Card.css'; + +interface CardContextProps { + onClick?: () => void; +} + +const CardContext = createContext({}); + +function useCardContext(): CardContextProps { + const context = useContext(CardContext); + + if (!context.onClick) { + throw new Error( + 'Child components of Card cannot be rendered outside the Card component!' + ); + } + + return context; +} + +interface ChildrenProps { + children: ReactNode; +} + +interface CardProps extends ChildrenProps { + onClick?: () => void; +} + +const Card = ({ children, onClick }: CardProps) => { + return ( + +
+ {children} +
+
+ ); +}; + +const Date = ({ children }: ChildrenProps) => { + return

{children}

; +}; + +Card.Date = Date; + +const Heading = ({ children }: ChildrenProps) => { + return

{children}

; +}; + +Card.Heading = Heading; + +const Description = ({ children }: ChildrenProps) => { + return
{children}
; +}; + +Card.Description = Description; + +const Category = ({ children }: ChildrenProps) => { + return
{children}
; +}; + +Card.Category = Category; + +interface ImageProps { + src: string; + alt: string; + type?: string; +} + +const Image = ({ src, alt, type }: ImageProps) => { + const context = useCardContext(); + const { onClick } = context; + + return ( + {alt} + ); +}; + +Card.Image = Image; + +export default Card; diff --git a/src/component/Map.tsx b/src/component/Map.tsx new file mode 100644 index 0000000..e3798d9 --- /dev/null +++ b/src/component/Map.tsx @@ -0,0 +1,63 @@ +import React, { useCallback, useEffect, useState } from 'react'; +import { GoogleMap, Marker, useJsApiLoader } from '@react-google-maps/api'; + +const containerStyle = { + minWidth: '100%', + minHeight: '40vh', + height: '100%', +}; + +function Map({ center }) { + const { isLoaded } = useJsApiLoader({ + id: 'google-map-script', + googleMapsApiKey: 'AIzaSyBgdt7wA-iBp5bQ8oW-SL-1cYIthSUFvrA', + }); + + const [map, setMap] = useState(null); + + const onLoad = useCallback(function callback(map) { + // const marker = new window.google.maps.Marker({ + // position: center, + // map, + // title: 'Hello World!', + // optimized: true, + // }); + // const infoWindow = new window.google.maps.InfoWindow({ + // content: 'Hello World!', + // }); + // infoWindow.open({ + // anchor: marker, + // map, + // }); + // marker.setMap(map); + // setMap(map); + }, []); + + const onUnmount = useCallback(function callback(map) { + setMap(null); + }, []); + + useEffect(() => { + if (map) { + map.panTo(center); + map.setZoom(14); + } + }, [map, center]); + + return isLoaded ? ( + + {/* Child components, such as markers, info windows, etc. */} + + + ) : ( + <> + ); +} + +export default React.memo(Map); diff --git a/src/component/Modal.css.ts b/src/component/Modal.css.ts new file mode 100644 index 0000000..c497b6c --- /dev/null +++ b/src/component/Modal.css.ts @@ -0,0 +1,86 @@ +import { style } from '@vanilla-extract/css'; + +export const modal = style({ + display: 'none', + position: 'fixed', + margin: 'auto', + zIndex: 1, + width: '100%', + height: '100%', + overflow: 'auto', + backgroundColor: 'rgba(0, 0, 0, 0.4)', +}); + +export const openedModal = style({ + display: 'flex', + flexDirection: 'column', + position: 'fixed', + width: '100%', + height: '100%', + backgroundColor: 'rgba(0, 0, 0, 0.4)', +}); + +export const modalContent = style({ + position: 'relative', + margin: 'auto 0px', + backgroundColor: '#fefefe', + border: '1px solid #888', + borderRadius: '4px', +}); + +export const modalHeader = style({ + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + backgroundColor: '#f1f1f1', + padding: '10px', + borderBottom: '1px solid #ccc', + fontWeight: 'bold', +}); + +export const modalHeaderButton = style({ + background: 'transparent', + border: 'none', + fontSize: '1.5em', + fontWeight: 'bold', + cursor: 'pointer', +}); + +export const modalBody = style({ + position: 'relative', + display: 'flex', + flexDirection: 'column', +}); + +export const modalFooter = style({ + display: 'flex', + justifyContent: 'flex-end', + alignItems: 'center', + backgroundColor: '#f1f1f1', + padding: '10px', + borderTop: '1px solid #ccc', +}); + +export const modalFooterButton = style({ + backgroundColor: '#44336', + border: 'none', + color: 'white', + fontWeight: 'bold', + textAlign: 'center', + textDecoration: 'none', + display: 'inline-block', + fontSize: '14px', + margin: '4px 2px', + cursor: 'pointer', + padding: '10px 20px', + borderRadius: '4px', +}); + +export const dimmed = style({ + position: 'fixed', + top: '0', + left: '0', + width: '100%', + height: '100%', + background: 'rgba(0, 0, 0, 0.5)', +}); diff --git a/src/component/Modal.tsx b/src/component/Modal.tsx new file mode 100644 index 0000000..32ebadf --- /dev/null +++ b/src/component/Modal.tsx @@ -0,0 +1,64 @@ +import { createContext, useContext, ReactNode } from 'react'; +import { + dimmed, + modal, + modalBody, + modalFooter, + modalHeader, + openedModal, +} from './Modal.css'; + +type ModalContextType = { + isOpened: boolean; + closeModal: () => void; +}; + +const ModalContext = createContext({ + isOpened: false, + closeModal: () => {}, +}); + +const Modal = ({ children, closeModal, isOpened }) => { + return ( + +
+
{children}
+
+
+ ); +}; + +type ModalComponentProps = { + children: ReactNode; +}; + +Modal.Dimmed = () => { + const { closeModal } = useContext(ModalContext); + return
; +}; + +Modal.Header = ({ children }: ModalComponentProps) => { + const { closeModal } = useContext(ModalContext); + return ( +
+ {children} + +
+ ); +}; + +Modal.Body = ({ children }: ModalComponentProps) => { + return
{children}
; +}; + +Modal.Footer = ({ children }: ModalComponentProps) => { + const { closeModal } = useContext(ModalContext); + return ( +
+ {children} + +
+ ); +}; + +export default Modal; diff --git a/src/component/Select.css.ts b/src/component/Select.css.ts new file mode 100644 index 0000000..91e1299 --- /dev/null +++ b/src/component/Select.css.ts @@ -0,0 +1,53 @@ +import { style } from '@vanilla-extract/css'; + +export const scrollableContainer = style({ + display: 'flex', + justifyContent: 'stretch', + width: '100%', + overflowX: 'auto', + height: '32px', + padding: '0px 12px', + zIndex: 1, + background: 'white', + position: 'sticky', + top: '0', + '::-webkit-scrollbar': { + display: 'none', + }, +}); + +export const tagStyle = style({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + minWidth: '60px', + width: '60px', + padding: '5px 10px', + margin: '0 5px', + backgroundColor: 'white', + color: 'black', + fontSize: '14px', + fontWeight: 'bold', + textAlign: 'center', + borderRadius: '5px', + border: '1px solid #ccc', + cursor: 'pointer', +}); + +export const selectedTagStyle = style({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + backgroundColor: 'black', + color: 'white', + minWidth: '60px', + width: '60px', + padding: '5px 10px', + margin: '0 5px', + fontSize: '14px', + fontWeight: 'bold', + textAlign: 'center', + borderRadius: '5px', + border: '1px solid #ccc', + cursor: 'pointer', +}); diff --git a/src/component/Select.tsx b/src/component/Select.tsx new file mode 100644 index 0000000..fdc2096 --- /dev/null +++ b/src/component/Select.tsx @@ -0,0 +1,69 @@ +import { ReactNode, createContext, useContext, useState } from 'react'; + +interface SelectContextProps { + selected: string; + onSelect: (value: string) => void; +} + +const SelectContext = createContext(null); + +interface SelectProps { + children: ReactNode; + defaultOption: string; + onChange: (value: string) => void; + className?: string; +} + +const Select = ({ + children, + defaultOption, + onChange, + className, +}: SelectProps) => { + const [selected, setSelected] = useState(defaultOption); + + const handleChange = (value) => { + setSelected(value); + if (onChange) onChange(value); + }; + + const contextValue: SelectContextProps = { + selected, + onSelect: handleChange, + }; + + return ( + +
    {children}
+
+ ); +}; + +interface OptionProps { + value: string; + children: ReactNode; + className?: { selectedTagStyle: string; tagStyle: string }; +} + +const Option = ({ value, children, className }: OptionProps) => { + const context = useContext(SelectContext); + if (context === undefined) { + throw new Error('은 Select 아래에서만 사용 가능!!'); + } + + const { selected, onSelect } = context; + const { selectedTagStyle, tagStyle } = className; + + const isSelected = selected === value; + const optionClassName = `${isSelected ? selectedTagStyle : tagStyle}`; + + return ( +
  • onSelect(value)} className={`${optionClassName}`}> + {children} +
  • + ); +}; + +Select.Option = Option; + +export default Select; diff --git a/src/component/Tag.css.ts b/src/component/Tag.css.ts new file mode 100644 index 0000000..fc0779a --- /dev/null +++ b/src/component/Tag.css.ts @@ -0,0 +1,6 @@ +import { style } from '@vanilla-extract/css'; + +export const tagStyle = style({ + display: 'inline-block', + fontSize: '8px', +}); diff --git a/src/component/Tag.tsx b/src/component/Tag.tsx new file mode 100644 index 0000000..392200a --- /dev/null +++ b/src/component/Tag.tsx @@ -0,0 +1,11 @@ +import { tagStyle } from './Tag.css'; + +const Tag = ({ color, children }) => { + return ( +
    + #{children} +
    + ); +}; + +export default Tag; diff --git a/src/constant/filterBar.ts b/src/constant/filterBar.ts new file mode 100644 index 0000000..06e01c8 --- /dev/null +++ b/src/constant/filterBar.ts @@ -0,0 +1,9 @@ +export const options = [ + { value: '', label: '전부' }, + { value: 'min=3', label: '추억' }, + { value: 'min=1&max=3', label: '후회' }, + { value: '혼자', label: '혼자' }, + { value: '같이', label: '같이' }, +] as const; + +export type FilterOption = (typeof options)[number]['label']; diff --git a/src/constant/path.ts b/src/constant/path.ts new file mode 100644 index 0000000..2775a93 --- /dev/null +++ b/src/constant/path.ts @@ -0,0 +1,4 @@ +export const NAVIGATE_PATH = { + kaleidoscopePage: `/kaleidoscope`, + memoryPage: `/memory`, +} as const; diff --git a/src/hooks/queries/memories.ts b/src/hooks/queries/memories.ts new file mode 100644 index 0000000..c977a29 --- /dev/null +++ b/src/hooks/queries/memories.ts @@ -0,0 +1,13 @@ +import { useQuery } from '@tanstack/react-query'; +import { fetchApi } from '../../utils/fetchApi'; + +export function memories({ options = {} } = {}) { + return useQuery( + ['memories'], + () => { + const url = '/memories'; + return fetchApi(url); + }, + { ...options } + ); +} diff --git a/src/hooks/queries/memory.ts b/src/hooks/queries/memory.ts new file mode 100644 index 0000000..06cd4bb --- /dev/null +++ b/src/hooks/queries/memory.ts @@ -0,0 +1,13 @@ +import { useQuery } from '@tanstack/react-query'; +import { fetchApi } from '../../utils/fetchApi'; + +export function memory(memoryId: string, { options = {} } = {}) { + return useQuery( + ['memory', memoryId], + () => { + const url = `/memory/${memoryId}`; // url의 id 부분을 변수로 변경 + return fetchApi(url); + }, + { ...options } + ); +} diff --git a/src/hooks/useIntersectionObserver.ts b/src/hooks/useIntersectionObserver.ts new file mode 100644 index 0000000..0bd412a --- /dev/null +++ b/src/hooks/useIntersectionObserver.ts @@ -0,0 +1,40 @@ +import { useEffect, useState } from 'react'; +import { InfiniteQueryObserverResult } from '@tanstack/react-query'; + +interface useIntersectionObserverProps { + threshold?: number; + hasNextPage: boolean | undefined; + fetchNextPage: () => Promise; +} + +export function useIntersectionObserver({ + threshold = 0.1, + hasNextPage, + fetchNextPage, +}: useIntersectionObserverProps) { + //관찰 요소 => 스크롤 최하단 div요소에 setTarget을 ref로 넘겨줌 + const [target, setTarget] = useState(null); + + const observerCallback: IntersectionObserverCallback = (entries) => { + entries.forEach((entry) => { + //target 관찰 0 => 다음페이지 호출 + if (entry.isIntersecting && hasNextPage) { + fetchNextPage(); + } + }); + }; + + useEffect(() => { + if (!target) return; + + const observer = new IntersectionObserver(observerCallback, { + threshold, + }); + + observer.observe(target); + + return () => observer.unobserve(target); + }, [observerCallback, threshold, target]); + + return { setTarget }; +} diff --git a/src/hooks/usePageNavigate.ts b/src/hooks/usePageNavigate.ts new file mode 100644 index 0000000..68046ac --- /dev/null +++ b/src/hooks/usePageNavigate.ts @@ -0,0 +1,23 @@ +import { useNavigate } from 'react-router-dom'; + +export const usePageNavigate = () => { + const navigate = useNavigate(); + + const goToKaleidoscopePage = () => { + navigate(`/kaleidoscope`); + }; + + const goToMemoryPage = (memoryId) => { + navigate(`/memory/${memoryId}`); + }; + + const goToMemoryMapPage = () => { + navigate(`/map`); + }; + + return { + goToKaleidoscopePage, + goToMemoryPage, + goToMemoryMapPage, + }; +}; diff --git a/src/index.css b/src/index.css index 2c3fac6..d62b652 100644 --- a/src/index.css +++ b/src/index.css @@ -1,69 +1,24 @@ -:root { - font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; - line-height: 1.5; - font-weight: 400; - - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: #242424; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} -a:hover { - color: #535bf2; +/* 요소 기본 스타일 초기화 */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; } +/* 브라우저 기본 스타일 초기화 */ +html, body { + height: 100%; + font-size: 16px; margin: 0; - display: flex; - place-items: center; - min-width: 320px; - min-height: 100vh; } -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - background-color: #1a1a1a; - cursor: pointer; - transition: border-color 0.25s; -} -button:hover { - border-color: #646cff; -} -button:focus, -button:focus-visible { - outline: 4px auto -webkit-focus-ring-color; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - a:hover { - color: #747bff; - } - button { - background-color: #f9f9f9; - } +body { + line-height: 1.5; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, + Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + color: #333; + background-color: #fff; } diff --git a/src/main.tsx b/src/main.tsx index aca35cc..859f4eb 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1,19 +1,49 @@ import ReactDOM from 'react-dom/client'; -import App from './App'; import './index.css'; -import { StrictMode } from 'react'; +import { StrictMode, Suspense } from 'react'; import { createBrowserRouter, RouterProvider } from 'react-router-dom'; +import Kaleidoscope from './pages/Kaleidoscope/Kaleidoscope'; +import Layout from './pages/Layout'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import Memory from './pages/Memory/Memory'; +import MemoryMap from './pages/Map/MemoryMap'; const router = createBrowserRouter([ { - path: '/', - element: , + path: '/kaleidoscope', + element: ( + + + + ), + }, + { + path: '/memory/:id', + element: ( + + loading...}> + + + + ), + }, + { + path: '/map', + element: ( + + + + ), }, ]); +const queryClient = new QueryClient(); + ReactDOM.createRoot(document.getElementById('root')!).render( - + + + ); diff --git a/src/pages/Kaleidoscope/Kaleidoscope.css.ts b/src/pages/Kaleidoscope/Kaleidoscope.css.ts new file mode 100644 index 0000000..9d2ff0a --- /dev/null +++ b/src/pages/Kaleidoscope/Kaleidoscope.css.ts @@ -0,0 +1,51 @@ +import { style } from '@vanilla-extract/css'; + +export const pageWrapper = style({ + marginTop: '16px', + display: 'flex', + flexDirection: 'column', + overflowY: 'scroll', + height: '100%', + backgroundColor: 'white', +}); + +export const MemoryPageWrapper = style({ + marginTop: '16px', + display: 'flex', + flexDirection: 'column', + backgroundColor: 'white', +}); + +export const pageTitle = style({ + fontFamily: 'SF Pro Display', + fontSize: '24px', + whiteSpace: 'nowrap', + textOverflow: 'ellipsis', + padding: '0 20px', +}); + +export const blurText = style({ + fontWeight: 'normal', + fontSize: '20px', + color: 'rgba(0, 0, 0, 0.6)', +}); + +export const boldText = style({ + fontWeight: 'bold', + fontSize: '26px', + color: 'black', +}); + +export const pageContent = style({ + height: '100%', + display: 'flex', + flexDirection: 'column', + overflow: 'scroll', + padding: '16px', +}); + +export const cardHeader = style({ + display: 'flex', + width: '100%', + justifyContent: 'space-between', +}); diff --git a/src/pages/Kaleidoscope/Kaleidoscope.tsx b/src/pages/Kaleidoscope/Kaleidoscope.tsx new file mode 100644 index 0000000..e849468 --- /dev/null +++ b/src/pages/Kaleidoscope/Kaleidoscope.tsx @@ -0,0 +1,70 @@ +import { Suspense, useState } from 'react'; +import Select from '../../component/Select'; +import { + scrollableContainer, + selectedTagStyle, + tagStyle, +} from '../../component/Select.css'; +import { + boldText, + pageContent, + pageTitle, + pageWrapper, +} from './Kaleidoscope.css'; +import MemoryList from './MemoriesList'; +import { FilterOption, options } from '../../constant/filterBar'; + +const Kaleidoscope = () => { + const [selectedOption, setSelectedOption] = useState('전부'); + + const handleSelectChange = (value: FilterOption) => { + setSelectedOption(value); + }; + + return ( + <> +
    +

    + 주마등 +

    + + +
    + }> + + +
    +
    + + ); +}; + +export default Kaleidoscope; + +const TmpLoader = () => { + return ( +
    + 로딩중... +
    + ); +}; diff --git a/src/pages/Kaleidoscope/MemoriesList.tsx b/src/pages/Kaleidoscope/MemoriesList.tsx new file mode 100644 index 0000000..52caf5a --- /dev/null +++ b/src/pages/Kaleidoscope/MemoriesList.tsx @@ -0,0 +1,53 @@ +import { cardHeader } from './Kaleidoscope.css'; +import Card from '../../component/Card'; +import { useMemories } from './hooks/useInfiniteMemories'; +import { useIntersectionObserver } from '../../hooks/useIntersectionObserver'; +import { Fragment } from 'react'; +import { usePageNavigate } from '../../hooks/usePageNavigate'; +import { FilterOption } from '../../constant/filterBar'; + +type MemoryListProps = { + selectedOption: FilterOption; +}; + +const MemoryList = ({ selectedOption }: MemoryListProps) => { + console.log(selectedOption); + const { data, fetchNextPage, hasNextPage } = useMemories(selectedOption); + const { goToMemoryPage } = usePageNavigate(); + const { setTarget } = useIntersectionObserver({ + hasNextPage, + fetchNextPage, + }); + + return ( + <> + {data?.pages.map((page, pageIndex) => ( + + {page.data.map((memory) => ( + { + goToMemoryPage(memory.id); + }} + > +
    + {memory.visitedAt} + {memory.category} +
    + {memory.title} + {memory.content} + +
    + ))} +
    + ))} +
    + + ); +}; + +export default MemoryList; diff --git a/src/pages/Kaleidoscope/hooks/useInfiniteMemories.ts b/src/pages/Kaleidoscope/hooks/useInfiniteMemories.ts new file mode 100644 index 0000000..7e9f02d --- /dev/null +++ b/src/pages/Kaleidoscope/hooks/useInfiniteMemories.ts @@ -0,0 +1,27 @@ +import { + UseInfiniteQueryResult, + useInfiniteQuery, +} from '@tanstack/react-query'; +import { fetchApi } from '../../../utils/fetchApi'; +import { Memory } from '../../../types/memory'; +import { FilterOption } from '../../../constant/filterBar'; + +interface PageData { + data: Memory[]; + nextPage: number; +} + +export function useMemories( + filter: FilterOption +): UseInfiniteQueryResult { + return useInfiniteQuery( + ['memories', filter], + async ({ pageParam = 1 }) => { + const url = `/memories?page=${pageParam}&${filter}`; + return fetchApi(url); + }, + { + getNextPageParam: (lastPage) => lastPage.nextPage, + } + ); +} diff --git a/src/pages/Kaleidoscope/hooks/useMemories.ts b/src/pages/Kaleidoscope/hooks/useMemories.ts new file mode 100644 index 0000000..6e2bc2b --- /dev/null +++ b/src/pages/Kaleidoscope/hooks/useMemories.ts @@ -0,0 +1,9 @@ +import { memories } from '../../../hooks/queries/memories'; + +export function useMemories() { + return memories({ + options: { + suspense: true, + }, + }); +} diff --git a/src/pages/Layout.css.ts b/src/pages/Layout.css.ts new file mode 100644 index 0000000..3abb9b4 --- /dev/null +++ b/src/pages/Layout.css.ts @@ -0,0 +1,14 @@ +import { style } from '@vanilla-extract/css'; + +export const navBar = style({ + position: 'sticky', + bottom: 0, + left: 0, + width: '100%', + height: '56px', + backgroundColor: '#9BACB4', + display: 'flex', + justifyContent: 'space-around', + alignItems: 'center', + zIndex: 100, +}); diff --git a/src/pages/Layout.tsx b/src/pages/Layout.tsx new file mode 100644 index 0000000..5118337 --- /dev/null +++ b/src/pages/Layout.tsx @@ -0,0 +1,24 @@ +import { usePageNavigate } from '../hooks/usePageNavigate'; +import { navBar } from './Layout.css'; + +const Layout = ({ children }) => { + const { goToKaleidoscopePage, goToMemoryMapPage } = usePageNavigate(); + return ( + <> +
    + {children} + +
    + + ); +}; + +export default Layout; diff --git a/src/pages/Map/MemoryMap.tsx b/src/pages/Map/MemoryMap.tsx new file mode 100644 index 0000000..5874d9d --- /dev/null +++ b/src/pages/Map/MemoryMap.tsx @@ -0,0 +1,28 @@ +import Map from '../../component/Map'; +import { + boldText, + pageTitle, + pageWrapper, +} from '../Kaleidoscope/Kaleidoscope.css'; + +const MemoryMap = () => { + const center = { + lat: 37.5665, + lng: 126.978, + }; + + return ( + <> +
    +

    + 지도 +

    +
    + +
    +
    + + ); +}; + +export default MemoryMap; diff --git a/src/pages/Memory/Memory.css.ts b/src/pages/Memory/Memory.css.ts new file mode 100644 index 0000000..982d2c6 --- /dev/null +++ b/src/pages/Memory/Memory.css.ts @@ -0,0 +1,50 @@ +import { style } from '@vanilla-extract/css'; + +export const wrapper = style({ + height: '100%', + display: 'flex', + flexDirection: 'column', + backgroundColor: 'white', + overflow: 'scroll', +}); + +export const imageWrapper = style({ + height: '50%', + position: 'relative', + padding: '16px', +}); + +export const image = style({ + width: '100%', + height: '100%', + borderRadius: '8px', + objectFit: 'fill', + imageResolution: 'from-image', +}); + +export const contentWrapper = style({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'space-between', + padding: '16px', +}); + +export const description = style({ + color: 'black', + textAlign: 'left', + fontSize: '14px', + lineHeight: '1.5', + overflow: 'hidden', + display: '-webkit-box', + WebkitLineClamp: 4, +}); + +export const categoryTag = style({ + fontSize: '12px', + fontWeight: 'bold', + borderRadius: '4px', + padding: '2px 4px', + backgroundColor: 'black', + color: 'white', + margin: 0, +}); diff --git a/src/pages/Memory/Memory.tsx b/src/pages/Memory/Memory.tsx new file mode 100644 index 0000000..29e923d --- /dev/null +++ b/src/pages/Memory/Memory.tsx @@ -0,0 +1,137 @@ +import { Fragment, useState } from 'react'; +import { date, heading } from '../../component/Card.css'; +import Map from '../../component/Map'; +import { + MemoryPageWrapper, + boldText, + pageTitle, +} from '../Kaleidoscope/Kaleidoscope.css'; +import { + categoryTag, + contentWrapper, + description, + image, + imageWrapper, + wrapper, +} from './Memory.css'; +import Modal from '../../component/Modal'; +import { useMemory } from './hooks/useMemory'; +import { useParams } from 'react-router-dom'; +import { modalContent } from '../../component/Modal.css'; +import Tag from '../../component/Tag'; +import { ReactComponent as Star } from '../../assets/star.svg'; +import { ReactComponent as Calender } from '../../assets/calender.svg'; +import { ReactComponent as Place } from '../../assets/place.svg'; +const Memory = () => { + const { id } = useParams(); + const { data } = useMemory(id); + + const [isOpened, setIsOpened] = useState(false); + + const openModal = () => { + setIsOpened(true); + }; + + const closeModal = () => { + setIsOpened(false); + }; + + const memoryLocation = { + lat: data.location.latitude, + lng: data.location.longitude, + }; + + return ( + <> +
    +

    + 기억 +

    +
    +
    +
    + +

    {data.visitedAt}

    +
    +
    + +

    + 장소 +

    +
    +
    + +
    +
    + random +
    +
    +
    +

    {data.title}

    +

    {data.category}

    +
    + +

    {data.content}

    +
    +
    + {data.tags.map((tag) => ( + + {tag.name} + + ))} +
    + +
    +
    + +

    {data.star} ratings

    +
    +
    +
    +
    + + + +
    + 장소 + + + + 모달 푸터 영역입니다. +
    +
    +
    + + ); +}; + +export default Memory; diff --git a/src/pages/Memory/hooks/useMemory.ts b/src/pages/Memory/hooks/useMemory.ts new file mode 100644 index 0000000..e1e6b27 --- /dev/null +++ b/src/pages/Memory/hooks/useMemory.ts @@ -0,0 +1,11 @@ +import { UseQueryResult } from '@tanstack/react-query'; +import { memory } from '../../../hooks/queries/memory'; +import { Memory } from '../../../types/memory'; + +export function useMemory(id: string): UseQueryResult { + return memory(id, { + options: { + suspense: true, + }, + }); +} diff --git a/src/types/memory.ts b/src/types/memory.ts new file mode 100644 index 0000000..938a0fe --- /dev/null +++ b/src/types/memory.ts @@ -0,0 +1,20 @@ +export interface Memory { + id: number; + title: string; + content: string; + category: string; + tags: Tag[]; + visitedAt: string; + star: number; + images: string[]; + location: { + latitude: number; + longitude: number; + }; +} + +export interface Tag { + id: number; + name: string; + color: string; +} diff --git a/src/utils/fetchApi.ts b/src/utils/fetchApi.ts new file mode 100644 index 0000000..a64d357 --- /dev/null +++ b/src/utils/fetchApi.ts @@ -0,0 +1,27 @@ +const baseURL = 'http://localhost:3000' + +export async function fetchApi(url, options = {}) { + // 토큰을 가져와서 헤더에 넣어주는 경우 고려 + // header에 Authorization: Bearer {token} 추가만 하면 됨 + const defaultOptions = { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + }, + body: undefined, + }; + + const finalOptions = { ...defaultOptions, ...options }; + + if (finalOptions.method === 'POST' ) { + finalOptions.body = JSON.stringify(finalOptions.body); + } + + const response = await fetch(`${baseURL}${url}`, finalOptions); + + if (!response.ok) { + throw new Error('네트워크 에러!!'); + } + + return response.json(); +} \ No newline at end of file diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts index 11f02fe..b1f45c7 100644 --- a/src/vite-env.d.ts +++ b/src/vite-env.d.ts @@ -1 +1,2 @@ /// +/// diff --git a/tsconfig.json b/tsconfig.json index 376bd0b..a010911 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,6 +5,7 @@ "lib": ["ES2020", "DOM", "DOM.Iterable"], "module": "ESNext", "skipLibCheck": true, + "types": ["vite-plugin-svgr/client"], /* Bundler mode */ "moduleResolution": "node", @@ -20,6 +21,6 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true }, - "include": ["src/**/*"], + "include": ["src/**/*.tsx", "src/**/*.ts"], "references": [{ "path": "./tsconfig.node.json" }] } diff --git a/vite.config.ts b/vite.config.ts index 8dc6f09..cd07011 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,8 +1,9 @@ import { vanillaExtractPlugin } from '@vanilla-extract/vite-plugin'; -import react from '@vitejs/plugin-react' +import react from '@vitejs/plugin-react'; import { defineConfig } from 'vite'; +import svgr from 'vite-plugin-svgr'; // https://vitejs.dev/config/ export default defineConfig({ - plugins: [react(), vanillaExtractPlugin()], -}) + plugins: [react(), vanillaExtractPlugin(), svgr()], +}); diff --git a/yarn.lock b/yarn.lock index c2a1006..6d2115f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -29,6 +29,14 @@ dependencies: "@babel/highlight" "^7.22.5" +"@babel/code-frame@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.10.tgz#1c20e612b768fefa75f6e90d6ecb86329247f0a3" + integrity sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA== + dependencies: + "@babel/highlight" "^7.22.10" + chalk "^2.4.2" + "@babel/compat-data@^7.22.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.22.9": version "7.22.9" resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz" @@ -55,6 +63,27 @@ json5 "^2.2.2" semver "^6.3.1" +"@babel/core@^7.21.3": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.10.tgz#aad442c7bcd1582252cb4576747ace35bc122f35" + integrity sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.22.10" + "@babel/generator" "^7.22.10" + "@babel/helper-compilation-targets" "^7.22.10" + "@babel/helper-module-transforms" "^7.22.9" + "@babel/helpers" "^7.22.10" + "@babel/parser" "^7.22.10" + "@babel/template" "^7.22.5" + "@babel/traverse" "^7.22.10" + "@babel/types" "^7.22.10" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.2" + semver "^6.3.1" + "@babel/generator@^7.12.11", "@babel/generator@^7.22.0", "@babel/generator@^7.22.7", "@babel/generator@^7.22.9": version "7.22.9" resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.22.9.tgz" @@ -65,6 +94,16 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" +"@babel/generator@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.10.tgz#c92254361f398e160645ac58831069707382b722" + integrity sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A== + dependencies: + "@babel/types" "^7.22.10" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + "@babel/helper-annotate-as-pure@^7.22.5": version "7.22.5" resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz" @@ -79,6 +118,17 @@ dependencies: "@babel/types" "^7.22.5" +"@babel/helper-compilation-targets@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz#01d648bbc25dd88f513d862ee0df27b7d4e67024" + integrity sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q== + dependencies: + "@babel/compat-data" "^7.22.9" + "@babel/helper-validator-option" "^7.22.5" + browserslist "^4.21.9" + lru-cache "^5.1.1" + semver "^6.3.1" + "@babel/helper-compilation-targets@^7.22.5", "@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.22.9": version "7.22.9" resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz" @@ -245,6 +295,15 @@ "@babel/template" "^7.22.5" "@babel/types" "^7.22.5" +"@babel/helpers@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.10.tgz#ae6005c539dfbcb5cd71fb51bfc8a52ba63bc37a" + integrity sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw== + dependencies: + "@babel/template" "^7.22.5" + "@babel/traverse" "^7.22.10" + "@babel/types" "^7.22.10" + "@babel/helpers@^7.22.6": version "7.22.6" resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz" @@ -254,6 +313,15 @@ "@babel/traverse" "^7.22.6" "@babel/types" "^7.22.5" +"@babel/highlight@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.10.tgz#02a3f6d8c1cb4521b2fd0ab0da8f4739936137d7" + integrity sha512-78aUtVcT7MUscr0K5mIEnkwxPE0MaxkR5RxRwuHaQ+JuU5AmTPhY+do2mdzVTnIJJpyBglql2pehuBIWHug+WQ== + dependencies: + "@babel/helper-validator-identifier" "^7.22.5" + chalk "^2.4.2" + js-tokens "^4.0.0" + "@babel/highlight@^7.22.5": version "7.22.5" resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz" @@ -268,6 +336,11 @@ resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz" integrity sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q== +"@babel/parser@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.10.tgz#e37634f9a12a1716136c44624ef54283cabd3f55" + integrity sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ== + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.5": version "7.22.5" resolved "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz" @@ -1055,6 +1128,22 @@ debug "^4.1.0" globals "^11.1.0" +"@babel/traverse@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.10.tgz#20252acb240e746d27c2e82b4484f199cf8141aa" + integrity sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig== + dependencies: + "@babel/code-frame" "^7.22.10" + "@babel/generator" "^7.22.10" + "@babel/helper-environment-visitor" "^7.22.5" + "@babel/helper-function-name" "^7.22.5" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.22.10" + "@babel/types" "^7.22.10" + debug "^4.1.0" + globals "^11.1.0" + "@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.20.7", "@babel/types@^7.22.0", "@babel/types@^7.22.5", "@babel/types@^7.4.4": version "7.22.5" resolved "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz" @@ -1064,6 +1153,15 @@ "@babel/helper-validator-identifier" "^7.22.5" to-fast-properties "^2.0.0" +"@babel/types@^7.21.3", "@babel/types@^7.22.10": + version "7.22.10" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.10.tgz#4a9e76446048f2c66982d1a989dd12b8a2d2dc03" + integrity sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg== + dependencies: + "@babel/helper-string-parser" "^7.22.5" + "@babel/helper-validator-identifier" "^7.22.5" + to-fast-properties "^2.0.0" + "@base2/pretty-print-object@1.0.1": version "1.0.1" resolved "https://registry.npmjs.org/@base2/pretty-print-object/-/pretty-print-object-1.0.1.tgz" @@ -1351,6 +1449,21 @@ resolved "https://registry.npmjs.org/@fal-works/esbuild-plugin-global-externals/-/esbuild-plugin-global-externals-2.1.2.tgz" integrity sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ== +"@googlemaps/js-api-loader@1.16.2": + version "1.16.2" + resolved "https://registry.yarnpkg.com/@googlemaps/js-api-loader/-/js-api-loader-1.16.2.tgz#3fe748e21243f8e8322c677a5525c569ae9cdbe9" + integrity sha512-psGw5u0QM6humao48Hn4lrChOM2/rA43ZCm3tKK9qQsEj1/VzqkCqnvGfEOshDbBQflydfaRovbKwZMF4AyqbA== + dependencies: + fast-deep-equal "^3.1.3" + +"@googlemaps/markerclusterer@2.3.2": + version "2.3.2" + resolved "https://registry.yarnpkg.com/@googlemaps/markerclusterer/-/markerclusterer-2.3.2.tgz#b311c26a0c0e8bb6325759ea690aef68c7150d8a" + integrity sha512-zb9OQP8XscZp2Npt1uQUYnGKu1miuq4DPP28JyDuFd6HV17HCEcjV9MtBi4muG/iVRXXvuHW9bRCnHbao9ITfw== + dependencies: + fast-deep-equal "^3.1.3" + supercluster "^8.0.1" + "@humanwhocodes/config-array@^0.11.10": version "0.11.10" resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz" @@ -1545,6 +1658,28 @@ picocolors "^1.0.0" tslib "^2.6.0" +"@react-google-maps/api@^2.19.2": + version "2.19.2" + resolved "https://registry.yarnpkg.com/@react-google-maps/api/-/api-2.19.2.tgz#678dc1871fbab72cd46d338eed687a36bf556ab1" + integrity sha512-Vt57XWzCKfsUjKOmFUl2erVVfOePkPK5OigF/f+q7UuV/Nm9KDDy1PMFBx+wNahEqOd6a32BxfsykEhBnbU9wQ== + dependencies: + "@googlemaps/js-api-loader" "1.16.2" + "@googlemaps/markerclusterer" "2.3.2" + "@react-google-maps/infobox" "2.19.2" + "@react-google-maps/marker-clusterer" "2.19.2" + "@types/google.maps" "3.53.5" + invariant "2.2.4" + +"@react-google-maps/infobox@2.19.2": + version "2.19.2" + resolved "https://registry.yarnpkg.com/@react-google-maps/infobox/-/infobox-2.19.2.tgz#b6bda962a4fa1074fdd3dfd63bc4c7d68b1dd745" + integrity sha512-6wvBqeJsQ/eFSvoxg+9VoncQvNoVCdmxzxRpLvmjPD+nNC6mHM0vJH1xSqaKijkMrfLJT0nfkTGpovrF896jwg== + +"@react-google-maps/marker-clusterer@2.19.2": + version "2.19.2" + resolved "https://registry.yarnpkg.com/@react-google-maps/marker-clusterer/-/marker-clusterer-2.19.2.tgz#24d9fb9aa555bb063ba5fe82f80fcd7d48662184" + integrity sha512-x9ibmsP0ZVqzyCo1Pitbw+4b6iEXRw/r1TCy3vOUR3eKrzWLnHYZMR325BkZW2r8fnuWE/V3Fp4QZOP9qYORCw== + "@remix-run/router@1.7.2": version "1.7.2" resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.7.2.tgz#cba1cf0a04bc04cb66027c51fa600e9cbc388bc8" @@ -2277,6 +2412,88 @@ "@types/express" "^4.7.0" file-system-cache "2.3.0" +"@svgr/babel-plugin-add-jsx-attribute@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-7.0.0.tgz#80856c1b7a3b7422d232f6e079f0beb90c4a13e9" + integrity sha512-khWbXesWIP9v8HuKCl2NU2HNAyqpSQ/vkIl36Nbn4HIwEYSRWL0H7Gs6idJdha2DkpFDWlsqMELvoCE8lfFY6Q== + +"@svgr/babel-plugin-remove-jsx-attribute@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-7.0.0.tgz#91da77a009dc38e8d30da45d9b62ef8736f2d90a" + integrity sha512-iiZaIvb3H/c7d3TH2HBeK91uI2rMhZNwnsIrvd7ZwGLkFw6mmunOCoVnjdYua662MqGFxlN9xTq4fv9hgR4VXQ== + +"@svgr/babel-plugin-remove-jsx-empty-expression@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-7.0.0.tgz#5154ff1213509e36ab315974c8c2fd48dafb827b" + integrity sha512-sQQmyo+qegBx8DfFc04PFmIO1FP1MHI1/QEpzcIcclo5OAISsOJPW76ZIs0bDyO/DBSJEa/tDa1W26pVtt0FRw== + +"@svgr/babel-plugin-replace-jsx-attribute-value@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-7.0.0.tgz#7e72f44ee57fdbcb02fb0d4a7629466c5242725e" + integrity sha512-i6MaAqIZXDOJeikJuzocByBf8zO+meLwfQ/qMHIjCcvpnfvWf82PFvredEZElErB5glQFJa2KVKk8N2xV6tRRA== + +"@svgr/babel-plugin-svg-dynamic-title@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-7.0.0.tgz#8caf0449c678ea29be756b89960b2b16c9f33f00" + integrity sha512-BoVSh6ge3SLLpKC0pmmN9DFlqgFy4NxNgdZNLPNJWBUU7TQpDWeBuyVuDW88iXydb5Cv0ReC+ffa5h3VrKfk1w== + +"@svgr/babel-plugin-svg-em-dimensions@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-7.0.0.tgz#4db6b5af6d29e93db236b1a013fa953754071d41" + integrity sha512-tNDcBa+hYn0gO+GkP/AuNKdVtMufVhU9fdzu+vUQsR18RIJ9RWe7h/pSBY338RO08wArntwbDk5WhQBmhf2PaA== + +"@svgr/babel-plugin-transform-react-native-svg@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-7.0.0.tgz#236995e58b5e36ff06365d5310509ce5391aeec9" + integrity sha512-qw54u8ljCJYL2KtBOjI5z7Nzg8LnSvQOP5hPKj77H4VQL4+HdKbAT5pnkkZLmHKYwzsIHSYKXxHouD8zZamCFQ== + +"@svgr/babel-plugin-transform-svg-component@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-7.0.0.tgz#a9b62730acf10d22a2aa57e0f701c0ecbc270430" + integrity sha512-CcFECkDj98daOg9jE3Bh3uyD9kzevCAnZ+UtzG6+BQG/jOQ2OA3jHnX6iG4G1MCJkUQFnUvEv33NvQfqrb/F3A== + +"@svgr/babel-preset@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-7.0.0.tgz#55aaca4cec2ff6515a571715b6b6fa98675b66d9" + integrity sha512-EX/NHeFa30j5UjldQGVQikuuQNHUdGmbh9kEpBKofGUtF0GUPJ4T4rhoYiqDAOmBOxojyot36JIFiDUHUK1ilQ== + dependencies: + "@svgr/babel-plugin-add-jsx-attribute" "^7.0.0" + "@svgr/babel-plugin-remove-jsx-attribute" "^7.0.0" + "@svgr/babel-plugin-remove-jsx-empty-expression" "^7.0.0" + "@svgr/babel-plugin-replace-jsx-attribute-value" "^7.0.0" + "@svgr/babel-plugin-svg-dynamic-title" "^7.0.0" + "@svgr/babel-plugin-svg-em-dimensions" "^7.0.0" + "@svgr/babel-plugin-transform-react-native-svg" "^7.0.0" + "@svgr/babel-plugin-transform-svg-component" "^7.0.0" + +"@svgr/core@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@svgr/core/-/core-7.0.0.tgz#def863d2670c682615583c80b408e83c095c2233" + integrity sha512-ztAoxkaKhRVloa3XydohgQQCb0/8x9T63yXovpmHzKMkHO6pkjdsIAWKOS4bE95P/2quVh1NtjSKlMRNzSBffw== + dependencies: + "@babel/core" "^7.21.3" + "@svgr/babel-preset" "^7.0.0" + camelcase "^6.2.0" + cosmiconfig "^8.1.3" + +"@svgr/hast-util-to-babel-ast@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-7.0.0.tgz#d457dfbe74ebc1e5a6daf97ded49e9576a3a00cf" + integrity sha512-42Ej9sDDEmsJKjrfQ1PHmiDiHagh/u9AHO9QWbeNx4KmD9yS5d1XHmXUNINfUcykAU+4431Cn+k6Vn5mWBYimQ== + dependencies: + "@babel/types" "^7.21.3" + entities "^4.4.0" + +"@svgr/plugin-jsx@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-7.0.0.tgz#b9e0c7d05bc890d70163ac0490ba8c41f1afab90" + integrity sha512-SWlTpPQmBUtLKxXWgpv8syzqIU8XgFRvyhfkam2So8b3BE0OS0HPe5UfmlJ2KIC+a7dpuuYovPR2WAQuSyMoPw== + dependencies: + "@babel/core" "^7.21.3" + "@svgr/babel-preset" "^7.0.0" + "@svgr/hast-util-to-babel-ast" "^7.0.0" + svg-parser "^2.0.4" + "@tanstack/query-core@4.32.5": version "4.32.5" resolved "https://registry.yarnpkg.com/@tanstack/query-core/-/query-core-4.32.5.tgz#1c9da404ba4906c35b3998ba03ea4ab44019750c" @@ -2437,6 +2654,11 @@ "@types/minimatch" "*" "@types/node" "*" +"@types/google.maps@3.53.5": + version "3.53.5" + resolved "https://registry.yarnpkg.com/@types/google.maps/-/google.maps-3.53.5.tgz#0f3010ab4eabe46721f3604462196975b640aab9" + integrity sha512-HoRq4Te8J6krH7hj+TfdYepqegoKZCj3kkaK5gf+ySFSHLvyqYkDvkrtbcVJXQ6QBphQ0h1TF7p4J6sOh4r/zg== + "@types/graceful-fs@^4.1.3": version "4.1.6" resolved "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz" @@ -3334,12 +3556,17 @@ camelcase@^5.3.1: resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== +camelcase@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + caniuse-lite@^1.0.30001503: version "1.0.30001517" resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz" integrity sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA== -chalk@^2.0.0: +chalk@^2.0.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -3565,6 +3792,16 @@ core-util-is@~1.0.0: resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== +cosmiconfig@^8.1.3: + version "8.2.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-8.2.0.tgz#f7d17c56a590856cd1e7cee98734dca272b0d8fd" + integrity sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ== + dependencies: + import-fresh "^3.2.1" + js-yaml "^4.1.0" + parse-json "^5.0.0" + path-type "^4.0.0" + cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" @@ -3854,6 +4091,11 @@ enhanced-resolve@^5.12.0: graceful-fs "^4.2.4" tapable "^2.2.0" +entities@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + envinfo@^7.7.3: version "7.10.0" resolved "https://registry.npmjs.org/envinfo/-/envinfo-7.10.0.tgz" @@ -5031,6 +5273,13 @@ internal-slot@^1.0.3, internal-slot@^1.0.4, internal-slot@^1.0.5: has "^1.0.3" side-channel "^1.0.4" +invariant@2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + ip@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz" @@ -5538,6 +5787,11 @@ jsonfile@^6.0.1: object.assign "^4.1.4" object.values "^1.1.6" +kdbush@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/kdbush/-/kdbush-4.0.2.tgz#2f7b7246328b4657dd122b6c7f025fbc2c868e39" + integrity sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA== + kind-of@^6.0.2: version "6.0.3" resolved "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz" @@ -5625,7 +5879,7 @@ log-symbols@^4.1.0: chalk "^4.1.0" is-unicode-supported "^0.1.0" -loose-envify@^1.1.0, loose-envify@^1.4.0: +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== @@ -7230,6 +7484,13 @@ strip-json-comments@^3.0.1, strip-json-comments@^3.1.1: resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +supercluster@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/supercluster/-/supercluster-8.0.1.tgz#9946ba123538e9e9ab15de472531f604e7372df5" + integrity sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ== + dependencies: + kdbush "^4.0.2" + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" @@ -7256,6 +7517,11 @@ supports-preserve-symlinks-flag@^1.0.0: resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +svg-parser@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" + integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ== + synchronous-promise@^2.0.15: version "2.0.17" resolved "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.17.tgz" @@ -7723,6 +7989,15 @@ vite-node@^0.28.5: source-map-support "^0.5.21" vite "^3.0.0 || ^4.0.0" +vite-plugin-svgr@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/vite-plugin-svgr/-/vite-plugin-svgr-3.2.0.tgz#920375aaf6635091c9ac8e467825f92d32544476" + integrity sha512-Uvq6niTvhqJU6ga78qLKBFJSDvxWhOnyfQSoKpDPMAGxJPo5S3+9hyjExE5YDj6Lpa4uaLkGc1cBgxXov+LjSw== + dependencies: + "@rollup/pluginutils" "^5.0.2" + "@svgr/core" "^7.0.0" + "@svgr/plugin-jsx" "^7.0.0" + "vite@^3.0.0 || ^4.0.0", vite@^4.4.5: version "4.4.6" resolved "https://registry.npmjs.org/vite/-/vite-4.4.6.tgz"