From cc1fc8d08ba97ef2571fb59563c3068c613a1653 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 9 Aug 2025 17:40:45 +0900 Subject: [PATCH 001/253] =?UTF-8?q?feat=20[#1]=20=EA=B3=B5=ED=86=B5=20?= =?UTF-8?q?=EC=83=89=EC=83=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 2 ++ src/app.jsx | 3 ++- src/main.jsx | 1 - src/styles/colors.css | 46 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 src/styles/colors.css diff --git a/index.html b/index.html index 010885c..75975a8 100644 --- a/index.html +++ b/index.html @@ -3,6 +3,8 @@ + + Rolling diff --git a/src/app.jsx b/src/app.jsx index 2580dee..7d6224b 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -1,5 +1,6 @@ function App() { - return

Hello, world!

; + const style = { color: "var(--color-purple-500)" }; + return

Hello, world!

; } export default App; diff --git a/src/main.jsx b/src/main.jsx index 6b87c5e..2f3a963 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -1,7 +1,6 @@ import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; import App from "./app"; -import "./styles/global.css"; const root = createRoot(document.getElementById("root")); diff --git a/src/styles/colors.css b/src/styles/colors.css new file mode 100644 index 0000000..608d4f9 --- /dev/null +++ b/src/styles/colors.css @@ -0,0 +1,46 @@ +:root { + /* Semantics */ + + --color-error: #dc3a3a; + --color-surface: #f6f8ff; + + /* Palette */ + + --color-purple-100: #f8f0ff; + --color-purple-200: #ecd9ff; + --color-purple-300: #dcb9ff; + --color-purple-400: #c894fd; + --color-purple-500: #ab57ff; + --color-purple-600: #9935ff; + --color-purple-700: #861dee; + --color-purple-800: #6e0ad1; + --color-purple-900: #5603a7; + + --color-beige-100: #fff0d6; + --color-beige-200: #ffe2ad; + --color-beige-300: #ffc583; + --color-beige-400: #ffae65; + --color-beige-500: #ff8832; + + --color-blue-100: #e2f5ff; + --color-blue-200: #b1e4ff; + --color-blue-300: #7cd2ff; + --color-blue-400: #34b9ff; + --color-blue-500: #00a2fe; + + --color-green-100: #e4fbdc; + --color-green-200: #d0f5c3; + --color-green-300: #9be282; + --color-green-400: #60cf37; + --color-green-500: #2ba600; + + --color-gray-100: #f6f6f6; + --color-gray-200: #eeeeee; + --color-gray-300: #cccccc; + --color-gray-400: #999999; + --color-gray-500: #555555; + --color-gray-600: #4a4a4a; + --color-gray-700: #3a3a3a; + --color-gray-800: #2b2b2b; + --color-gray-900: #181818; +} From 5022b734556868dba83c95b3f3802a29502d626d Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 9 Aug 2025 18:02:14 +0900 Subject: [PATCH 002/253] =?UTF-8?q?feat=20[#1]=20Pretendard=20font=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 6 ++++++ src/styles/global.css | 6 ++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index 75975a8..3c20db6 100644 --- a/index.html +++ b/index.html @@ -5,6 +5,12 @@ + Rolling diff --git a/src/styles/global.css b/src/styles/global.css index 81e6a17..dd123e7 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -4,6 +4,8 @@ body { margin: 0; - font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, - Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; + font-family: "Pretendard Variable", Pretendard, -apple-system, + BlinkMacSystemFont, system-ui, Roboto, "Helvetica Neue", "Segoe UI", + "Apple SD Gothic Neo", "Noto Sans KR", "Malgun Gothic", "Apple Color Emoji", + "Segoe UI Emoji", "Segoe UI Symbol", sans-serif; } From a09da78a4b38d8b21b923a6f23aaadcece0e37de Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 9 Aug 2025 18:44:07 +0900 Subject: [PATCH 003/253] =?UTF-8?q?config=20[#2]=20`styled-components`=20p?= =?UTF-8?q?ackage=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 143 +++++++++++++++++++++++++++++-- package.json | 3 +- src/components/button/button.jsx | 0 3 files changed, 140 insertions(+), 6 deletions(-) create mode 100644 src/components/button/button.jsx diff --git a/package-lock.json b/package-lock.json index d001ce6..6237549 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,8 @@ "version": "0.0.0", "dependencies": { "react": "^19.1.1", - "react-dom": "^19.1.1" + "react-dom": "^19.1.1", + "styled-components": "^6.1.19" }, "devDependencies": { "@eslint/js": "^9.32.0", @@ -319,6 +320,27 @@ "node": ">=6.9.0" } }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz", + "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.8.1" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==", + "license": "MIT" + }, + "node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==", + "license": "MIT" + }, "node_modules/@esbuild/aix-ppc64": { "version": "0.25.8", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.8.tgz", @@ -1386,6 +1408,12 @@ "@types/react": "^19.0.0" } }, + "node_modules/@types/stylis": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz", + "integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==", + "license": "MIT" + }, "node_modules/@vitejs/plugin-react": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", @@ -1531,6 +1559,15 @@ "node": ">=6" } }, + "node_modules/camelize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001733", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001733.tgz", @@ -1618,11 +1655,30 @@ "node": ">= 8" } }, + "node_modules/css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==", + "license": "ISC", + "engines": { + "node": ">=4" + } + }, + "node_modules/css-to-react-native": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", + "license": "MIT", + "dependencies": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true, "license": "MIT" }, "node_modules/debug": { @@ -2263,7 +2319,6 @@ "version": "3.3.11", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, "funding": [ { "type": "github", @@ -2379,7 +2434,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { @@ -2424,6 +2478,12 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "license": "MIT" + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -2541,6 +2601,12 @@ "semver": "bin/semver.js" } }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==", + "license": "MIT" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -2568,7 +2634,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -2587,6 +2652,68 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/styled-components": { + "version": "6.1.19", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.19.tgz", + "integrity": "sha512-1v/e3Dl1BknC37cXMhwGomhO8AkYmN41CqyX9xhUDxry1ns3BFQy2lLDRQXJRdVVWB9OHemv/53xaStimvWyuA==", + "license": "MIT", + "dependencies": { + "@emotion/is-prop-valid": "1.2.2", + "@emotion/unitless": "0.8.1", + "@types/stylis": "4.2.5", + "css-to-react-native": "3.2.0", + "csstype": "3.1.3", + "postcss": "8.4.49", + "shallowequal": "1.1.0", + "stylis": "4.3.2", + "tslib": "2.6.2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/styled-components" + }, + "peerDependencies": { + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0" + } + }, + "node_modules/styled-components/node_modules/postcss": { + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/stylis": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz", + "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==", + "license": "MIT" + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -2617,6 +2744,12 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "license": "0BSD" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", diff --git a/package.json b/package.json index 3653c72..c3553fb 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ }, "dependencies": { "react": "^19.1.1", - "react-dom": "^19.1.1" + "react-dom": "^19.1.1", + "styled-components": "^6.1.19" }, "devDependencies": { "@eslint/js": "^9.32.0", diff --git a/src/components/button/button.jsx b/src/components/button/button.jsx new file mode 100644 index 0000000..e69de29 From c583ee3de491d5307c4b180a20722eb5b584fdc6 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 9 Aug 2025 21:26:03 +0900 Subject: [PATCH 004/253] =?UTF-8?q?feat=20[#2]=20`PrimaryButton`=20compone?= =?UTF-8?q?nt=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.jsx | 5 +- src/components/button/button-size.js | 8 +++ src/components/button/button.jsx | 93 ++++++++++++++++++++++++++++ src/pages/test-page.jsx | 17 +++++ 4 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 src/components/button/button-size.js create mode 100644 src/pages/test-page.jsx diff --git a/src/app.jsx b/src/app.jsx index 7d6224b..c2cf85c 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -1,6 +1,7 @@ +import TestPage from "./pages/test-page"; + function App() { - const style = { color: "var(--color-purple-500)" }; - return

Hello, world!

; + return ; } export default App; diff --git a/src/components/button/button-size.js b/src/components/button/button-size.js new file mode 100644 index 0000000..c2aed8a --- /dev/null +++ b/src/components/button/button-size.js @@ -0,0 +1,8 @@ +const BUTTON_SIZE = Object.freeze({ + large: "large", + medium: "medium", + small: "small", + extraSmall: "extraSmall", +}); + +export default BUTTON_SIZE; diff --git a/src/components/button/button.jsx b/src/components/button/button.jsx index e69de29..92f0610 100644 --- a/src/components/button/button.jsx +++ b/src/components/button/button.jsx @@ -0,0 +1,93 @@ +import styled from "styled-components"; +import BUTTON_SIZE from "./button-size"; + +const styles = { + padding: { + [BUTTON_SIZE.large]: "0 24px", + [BUTTON_SIZE.medium]: "0 16px", + [BUTTON_SIZE.small]: "0 16px", + [BUTTON_SIZE.extraSmall]: "0 16px", + }, + minWidth: { + [BUTTON_SIZE.large]: "160px", + [BUTTON_SIZE.medium]: "90px", + [BUTTON_SIZE.small]: "90px", + [BUTTON_SIZE.extraSmall]: "90px", + }, + height: { + [BUTTON_SIZE.large]: "56px", + [BUTTON_SIZE.medium]: "40px", + [BUTTON_SIZE.small]: "36px", + [BUTTON_SIZE.extraSmall]: "28px", + }, + fontSize: { + [BUTTON_SIZE.large]: "18px", + [BUTTON_SIZE.medium]: "16px", + [BUTTON_SIZE.small]: "16px", + [BUTTON_SIZE.extraSmall]: "14px", + }, + fontWeight: { + [BUTTON_SIZE.large]: "700", + [BUTTON_SIZE.medium]: "400", + [BUTTON_SIZE.small]: "400", + [BUTTON_SIZE.extraSmall]: "400", + }, + lineHeight: { + [BUTTON_SIZE.large]: "28px", + [BUTTON_SIZE.medium]: "26px", + [BUTTON_SIZE.small]: "24px", + [BUTTON_SIZE.extraSmall]: "20px", + }, + borderRadius: { + [BUTTON_SIZE.large]: "12px", + [BUTTON_SIZE.medium]: "6px", + [BUTTON_SIZE.small]: "6px", + [BUTTON_SIZE.extraSmall]: "6px", + }, +}; + +const BaseButton = styled.button` + border: none; + cursor: pointer; + padding: ${({ $size }) => styles.padding[$size]}; + font-size: ${({ $size }) => styles.fontSize[$size]}; + font-weight: ${({ $size }) => styles.fontWeight[$size]}; + line-height: ${({ $size }) => styles.lineHeight[$size]}; + border-radius: ${({ $size }) => styles.borderRadius[$size]}; + height: ${({ $size }) => styles.height[$size]}; + min-width: ${({ $size }) => styles.minWidth[$size]}; +`; + +/* Primary Button */ + +const StyledPrimaryButton = styled(BaseButton)` + background-color: var(--color-purple-600); + color: white; + + &:disabled { + background-color: var(--color-gray-300); + } + + &:hover { + background-color: var(--color-purple-700); + } + + &:active { + background-color: var(--color-purple-800); + } + + &:focus { + background-color: var(--color-purple-800); + border: 1px solid var(--color-purple-900); + } +`; + +function PrimaryButton({ title, size, ...props }) { + return ( + + {title} + + ); +} + +export { PrimaryButton }; diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx new file mode 100644 index 0000000..fb94e98 --- /dev/null +++ b/src/pages/test-page.jsx @@ -0,0 +1,17 @@ +import { PrimaryButton } from "../components/button/button"; +import BUTTON_SIZE from "../components/button/button-size"; + +function TestPage() { + return ( +
+
+ + + + +
+
+ ); +} + +export default TestPage; From 9cc02f0598e381dfcd47436a35ef2c409ab18812 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 9 Aug 2025 21:32:06 +0900 Subject: [PATCH 005/253] =?UTF-8?q?feat=20[#2]=20`SecondaryButton`componen?= =?UTF-8?q?t=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/button/button.jsx | 40 +++++++++++++++++++++++++++++++- src/pages/test-page.jsx | 19 +++++++++++++-- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/src/components/button/button.jsx b/src/components/button/button.jsx index 92f0610..d148396 100644 --- a/src/components/button/button.jsx +++ b/src/components/button/button.jsx @@ -90,4 +90,42 @@ function PrimaryButton({ title, size, ...props }) { ); } -export { PrimaryButton }; +/* Secondary Button */ + +const StyledSecondaryButton = styled(BaseButton)` + background-color: white; + color: var(--color-purple-700); + border: 1px solid var(--color-purple-600); + + &:disabled { + background-color: var(--color-gray-300); + color: white; + border: none; + } + + &:hover { + background-color: var(--color-purple-100); + color: var(--color-purple-600); + border: 1px solid var(--color-purple-700); + } + + &:active { + background-color: var(--color-purple-100); + color: var(--color-purple-600); + border: 1px solid var(--color-purple-800); + } + + &:focus { + border: 1px solid var(--color-purple-800); + } +`; + +function SecondaryButton({ title, size, ...props }) { + return ( + + {title} + + ); +} + +export { PrimaryButton, SecondaryButton }; diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index fb94e98..e1d32f9 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -1,14 +1,29 @@ -import { PrimaryButton } from "../components/button/button"; +import { PrimaryButton, SecondaryButton } from "../components/button/button"; import BUTTON_SIZE from "../components/button/button-size"; function TestPage() { return ( -
+
+ +
+
+ + + + +
); From 5b225fe10fb6c02164212ec0a8177c957b3b64df Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 9 Aug 2025 21:36:02 +0900 Subject: [PATCH 006/253] =?UTF-8?q?feat=20[#2]=20`OutlinedButton`=20compon?= =?UTF-8?q?ent=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/button/button.jsx | 36 +++++++++++++++++++++++++++++++- src/pages/test-page.jsx | 13 +++++++++++- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/components/button/button.jsx b/src/components/button/button.jsx index d148396..fdfe0a7 100644 --- a/src/components/button/button.jsx +++ b/src/components/button/button.jsx @@ -128,4 +128,38 @@ function SecondaryButton({ title, size, ...props }) { ); } -export { PrimaryButton, SecondaryButton }; +/* Outlined Button */ + +const StyledOutlinedButton = styled(BaseButton)` + background-color: white; + color: var(--color-gray-900); + border: 1px solid var(--color-gray-300); + + &:disabled { + background-color: var(--color-gray-300); + color: white; + border: none; + } + + &:hover { + background-color: var(--color-gray-100); + } + + &:active { + background-color: var(--color-gray-100); + } + + &:focus { + border: 1px solid var(--color-gray-500); + } +`; + +function OutlinedButton({ title, size, ...props }) { + return ( + + {title} + + ); +} + +export { OutlinedButton, PrimaryButton, SecondaryButton }; diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index e1d32f9..e9f463c 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -1,4 +1,8 @@ -import { PrimaryButton, SecondaryButton } from "../components/button/button"; +import { + OutlinedButton, + PrimaryButton, + SecondaryButton, +} from "../components/button/button"; import BUTTON_SIZE from "../components/button/button-size"; function TestPage() { @@ -25,6 +29,13 @@ function TestPage() {
+
+ + + + + +
); } From 7aafed51b4eec507a6accb7019238b5e682478f5 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 9 Aug 2025 21:46:41 +0900 Subject: [PATCH 007/253] =?UTF-8?q?feat=20[#2]=20`ArrowButton`=20component?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/ic-chevron-left.svg | 3 ++ src/assets/ic-chevron-right.svg | 3 ++ .../button/arrow-button-direction.js | 6 ++++ src/components/button/arrow-button.jsx | 34 +++++++++++++++++++ src/pages/test-page.jsx | 6 ++++ 5 files changed, 52 insertions(+) create mode 100644 src/assets/ic-chevron-left.svg create mode 100644 src/assets/ic-chevron-right.svg create mode 100644 src/components/button/arrow-button-direction.js create mode 100644 src/components/button/arrow-button.jsx diff --git a/src/assets/ic-chevron-left.svg b/src/assets/ic-chevron-left.svg new file mode 100644 index 0000000..eb1b8f6 --- /dev/null +++ b/src/assets/ic-chevron-left.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/ic-chevron-right.svg b/src/assets/ic-chevron-right.svg new file mode 100644 index 0000000..16a36c8 --- /dev/null +++ b/src/assets/ic-chevron-right.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/button/arrow-button-direction.js b/src/components/button/arrow-button-direction.js new file mode 100644 index 0000000..bf595af --- /dev/null +++ b/src/components/button/arrow-button-direction.js @@ -0,0 +1,6 @@ +const ARROW_BUTTON_DIRECTION = Object.freeze({ + left: "left", + right: "right", +}); + +export default ARROW_BUTTON_DIRECTION; diff --git a/src/components/button/arrow-button.jsx b/src/components/button/arrow-button.jsx new file mode 100644 index 0000000..4e962db --- /dev/null +++ b/src/components/button/arrow-button.jsx @@ -0,0 +1,34 @@ +import styled from "styled-components"; +import arrowLeftImg from "../../assets/ic-chevron-left.svg"; +import arrowRightImg from "../../assets/ic-chevron-right.svg"; +import ARROW_BUTTON_DIRECTION from "./arrow-button-direction"; + +const arrowImg = { + [ARROW_BUTTON_DIRECTION.left]: arrowLeftImg, + [ARROW_BUTTON_DIRECTION.right]: arrowRightImg, +}; + +const StyledArrowButton = styled.button` + background: none; + border: 1px solid var(--color-gray-300); + width: 40px; + height: 40px; + border-radius: 20px; + padding: 12px; + box-shadow: 0 4px 8px 0px rgba(0, 0, 0, 0.08); + + img { + width: 100%; + height: 100%; + } +`; + +function ArrowButton({ direction }) { + return ( + + 화살표 + + ); +} + +export default ArrowButton; diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index e9f463c..fce50b4 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -1,3 +1,5 @@ +import ArrowButton from "../components/button/arrow-button"; +import ARROW_BUTTON_DIRECTION from "../components/button/arrow-button-direction"; import { OutlinedButton, PrimaryButton, @@ -36,6 +38,10 @@ function TestPage() { +
+ + +
); } From 7a7b001bab00aaaf6b5e8f9aa8feb1415b388724 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 9 Aug 2025 22:06:43 +0900 Subject: [PATCH 008/253] =?UTF-8?q?feat=20[#2]=20`ToggleButton`=20componen?= =?UTF-8?q?t=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 좌우로 이동하는 animation은 나중에 개선할 때 구현할 예정입니다. --- src/components/button/toggle-button.jsx | 51 +++++++++++++++++++++++++ src/pages/test-page.jsx | 4 ++ 2 files changed, 55 insertions(+) create mode 100644 src/components/button/toggle-button.jsx diff --git a/src/components/button/toggle-button.jsx b/src/components/button/toggle-button.jsx new file mode 100644 index 0000000..82de1a7 --- /dev/null +++ b/src/components/button/toggle-button.jsx @@ -0,0 +1,51 @@ +import { useState } from "react"; +import styled from "styled-components"; + +const StyledToggleButton = styled.div` + background-color: var(--color-gray-100); + border-radius: 6px; +`; + +const ToggleItem = styled.button` + background: ${({ $selected }) => ($selected ? "white" : "none")}; + border: none; + color: ${({ $selected }) => + $selected ? "var(--color-purple-700)" : "var(--color-gray-900)"}; + box-shadow: ${({ $selected }) => + $selected ? "0 0 0 2px var(--color-purple-600) inset" : "none"}; + border-radius: 6px; + padding: 0 16px; + height: 40px; + cursor: pointer; + + span { + display: block; + min-width: 90px; + font-size: 16px; + font-weight: ${({ $selected }) => ($selected ? 700 : 400)}; + } +`; + +function ToggleButton({ value, options = [] }) { + const [selected, setSelected] = useState(value); + + const handleOptionClick = (event) => { + setSelected(event.target.innerHTML); + }; + + return ( + + {options.map((title, index) => ( + + {title} + + ))} + + ); +} + +export default ToggleButton; diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index fce50b4..49d3693 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -6,6 +6,7 @@ import { SecondaryButton, } from "../components/button/button"; import BUTTON_SIZE from "../components/button/button-size"; +import ToggleButton from "../components/button/toggle-button"; function TestPage() { return ( @@ -42,6 +43,9 @@ function TestPage() { +
+ +
); } From cb0c018140a3dc9dc3d118836254c2c0ecd11e06 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 9 Aug 2025 22:12:32 +0900 Subject: [PATCH 009/253] =?UTF-8?q?refactor=20[#2]=20Primary,=20secondary,?= =?UTF-8?q?=20outlined=20button=EC=9D=98=20border=EB=A5=BC=20box-shadow?= =?UTF-8?q?=EB=A1=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `border`를 사용하면 border가 없다가 생길 때 주변 요소들의 layout에 영향을 주는 문제가 발생할 수 있습니다. - `box-shadow`를 사용하면 border 안쪽으로 테두리를 그려서 이 문제를 해결할 수 있습니다. --- src/components/button/button.jsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/button/button.jsx b/src/components/button/button.jsx index fdfe0a7..b3c2740 100644 --- a/src/components/button/button.jsx +++ b/src/components/button/button.jsx @@ -78,7 +78,7 @@ const StyledPrimaryButton = styled(BaseButton)` &:focus { background-color: var(--color-purple-800); - border: 1px solid var(--color-purple-900); + box-shadow: 0 0 0 1px var(--color-purple-900) inset; } `; @@ -95,28 +95,28 @@ function PrimaryButton({ title, size, ...props }) { const StyledSecondaryButton = styled(BaseButton)` background-color: white; color: var(--color-purple-700); - border: 1px solid var(--color-purple-600); + box-shadow: 0 0 0 1px var(--color-purple-600) inset; &:disabled { background-color: var(--color-gray-300); color: white; - border: none; + box-shadow: none; } &:hover { background-color: var(--color-purple-100); color: var(--color-purple-600); - border: 1px solid var(--color-purple-700); + box-shadow: 0 0 0 1px var(--color-purple-700) inset; } &:active { background-color: var(--color-purple-100); color: var(--color-purple-600); - border: 1px solid var(--color-purple-800); + box-shadow: 0 0 0 1px var(--color-purple-800) inset; } &:focus { - border: 1px solid var(--color-purple-800); + box-shadow: 0 0 0 1px var(--color-purple-800) inset; } `; @@ -133,12 +133,12 @@ function SecondaryButton({ title, size, ...props }) { const StyledOutlinedButton = styled(BaseButton)` background-color: white; color: var(--color-gray-900); - border: 1px solid var(--color-gray-300); + box-shadow: 0 0 0 1px var(--color-gray-300) inset; &:disabled { background-color: var(--color-gray-300); color: white; - border: none; + box-shadow: none; } &:hover { @@ -150,7 +150,7 @@ const StyledOutlinedButton = styled(BaseButton)` } &:focus { - border: 1px solid var(--color-gray-500); + box-shadow: 0 0 0 1px var(--color-gray-500) inset; } `; From 1fd6aea8928f25c30da3124d7ee0c2913159358f Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 9 Aug 2025 22:13:15 +0900 Subject: [PATCH 010/253] =?UTF-8?q?fix=20[#2]=20`ArrowButton`=EC=97=90=20p?= =?UTF-8?q?ointer=20cursor=20=EC=84=A4=EC=A0=95=20=EB=88=84=EB=9D=BD=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/button/arrow-button.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/button/arrow-button.jsx b/src/components/button/arrow-button.jsx index 4e962db..a36d174 100644 --- a/src/components/button/arrow-button.jsx +++ b/src/components/button/arrow-button.jsx @@ -16,6 +16,7 @@ const StyledArrowButton = styled.button` border-radius: 20px; padding: 12px; box-shadow: 0 4px 8px 0px rgba(0, 0, 0, 0.08); + cursor: pointer; img { width: 100%; From 6011c6baa6e94987366e854e32df9963badcdc2e Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 9 Aug 2025 22:20:14 +0900 Subject: [PATCH 011/253] =?UTF-8?q?feat=20[#2]=20Disabled=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=EB=90=9C=20button=20component=EC=9D=98=20cursor?= =?UTF-8?q?=EB=A5=BC=20pointer=EB=A1=9C=20=EC=84=A4=EC=A0=95=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EC=9D=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/button/button.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/button/button.jsx b/src/components/button/button.jsx index b3c2740..13c007e 100644 --- a/src/components/button/button.jsx +++ b/src/components/button/button.jsx @@ -48,7 +48,7 @@ const styles = { const BaseButton = styled.button` border: none; - cursor: pointer; + cursor: ${({ disabled }) => (disabled ? "default" : "pointer")}; padding: ${({ $size }) => styles.padding[$size]}; font-size: ${({ $size }) => styles.fontSize[$size]}; font-weight: ${({ $size }) => styles.fontWeight[$size]}; From e81d2e8dcf56bed6b8b258c15474793c72755fa3 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 9 Aug 2025 22:20:38 +0900 Subject: [PATCH 012/253] =?UTF-8?q?fix=20[#2]=20Disabled=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=EB=90=9C=20button=20component=EC=97=90=20hover,=20act?= =?UTF-8?q?ive=20style=EC=9D=B4=20=EC=A0=81=EC=9A=A9=EB=90=98=EB=8A=94=20?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/button/button.jsx | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/components/button/button.jsx b/src/components/button/button.jsx index 13c007e..aa7504e 100644 --- a/src/components/button/button.jsx +++ b/src/components/button/button.jsx @@ -64,10 +64,6 @@ const StyledPrimaryButton = styled(BaseButton)` background-color: var(--color-purple-600); color: white; - &:disabled { - background-color: var(--color-gray-300); - } - &:hover { background-color: var(--color-purple-700); } @@ -80,6 +76,10 @@ const StyledPrimaryButton = styled(BaseButton)` background-color: var(--color-purple-800); box-shadow: 0 0 0 1px var(--color-purple-900) inset; } + + &:disabled { + background-color: var(--color-gray-300); + } `; function PrimaryButton({ title, size, ...props }) { @@ -97,12 +97,6 @@ const StyledSecondaryButton = styled(BaseButton)` color: var(--color-purple-700); box-shadow: 0 0 0 1px var(--color-purple-600) inset; - &:disabled { - background-color: var(--color-gray-300); - color: white; - box-shadow: none; - } - &:hover { background-color: var(--color-purple-100); color: var(--color-purple-600); @@ -118,6 +112,12 @@ const StyledSecondaryButton = styled(BaseButton)` &:focus { box-shadow: 0 0 0 1px var(--color-purple-800) inset; } + + &:disabled { + background-color: var(--color-gray-300); + color: white; + box-shadow: none; + } `; function SecondaryButton({ title, size, ...props }) { @@ -135,12 +135,6 @@ const StyledOutlinedButton = styled(BaseButton)` color: var(--color-gray-900); box-shadow: 0 0 0 1px var(--color-gray-300) inset; - &:disabled { - background-color: var(--color-gray-300); - color: white; - box-shadow: none; - } - &:hover { background-color: var(--color-gray-100); } @@ -152,6 +146,12 @@ const StyledOutlinedButton = styled(BaseButton)` &:focus { box-shadow: 0 0 0 1px var(--color-gray-500) inset; } + + &:disabled { + background-color: var(--color-gray-300); + color: white; + box-shadow: none; + } `; function OutlinedButton({ title, size, ...props }) { From 89c6b7f695f0fb130e7fa30f7e79e941ca282d14 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 9 Aug 2025 22:28:14 +0900 Subject: [PATCH 013/253] =?UTF-8?q?fix=20[#2]=20`ToggleButton`=EC=9D=98=20?= =?UTF-8?q?click=20event=EA=B0=80=20=EC=84=A0=ED=83=9D=ED=95=9C=20option?= =?UTF-8?q?=EC=9D=98=20text=EB=A7=8C=20=EC=82=AC=EC=9A=A9=ED=95=B4?= =?UTF-8?q?=EC=84=9C=20state=20=EA=B0=B1=EC=8B=A0=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/button/toggle-button.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/button/toggle-button.jsx b/src/components/button/toggle-button.jsx index 82de1a7..a0cfc20 100644 --- a/src/components/button/toggle-button.jsx +++ b/src/components/button/toggle-button.jsx @@ -30,7 +30,7 @@ function ToggleButton({ value, options = [] }) { const [selected, setSelected] = useState(value); const handleOptionClick = (event) => { - setSelected(event.target.innerHTML); + setSelected(event.target.textContent); }; return ( From 119cb07dd8e00c490ab380765dfea0ae9f7e800e Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 9 Aug 2025 22:29:01 +0900 Subject: [PATCH 014/253] =?UTF-8?q?refactor=20[#2]=20`ToggleButton`?= =?UTF-8?q?=EC=97=90=20`value`=EB=A5=BC=20=EC=84=A4=EC=A0=95=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EC=98=88=EC=8B=9C=20=EC=BD=94=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/test-page.jsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index 49d3693..40b985e 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -43,8 +43,16 @@ function TestPage() { -
+
+
); From b042aabf5b16cc2a192469eab4e0c45fa98df596 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 9 Aug 2025 22:35:05 +0900 Subject: [PATCH 015/253] =?UTF-8?q?fix=20[#2]=20`PrimaryButton`=EB=A7=8C?= =?UTF-8?q?=20=EA=B0=80=EB=A1=9C=20=EB=B0=A9=ED=96=A5=20padding=EC=9D=84?= =?UTF-8?q?=2024px=EB=A1=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/button/button.jsx | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/components/button/button.jsx b/src/components/button/button.jsx index aa7504e..0dffa46 100644 --- a/src/components/button/button.jsx +++ b/src/components/button/button.jsx @@ -2,12 +2,6 @@ import styled from "styled-components"; import BUTTON_SIZE from "./button-size"; const styles = { - padding: { - [BUTTON_SIZE.large]: "0 24px", - [BUTTON_SIZE.medium]: "0 16px", - [BUTTON_SIZE.small]: "0 16px", - [BUTTON_SIZE.extraSmall]: "0 16px", - }, minWidth: { [BUTTON_SIZE.large]: "160px", [BUTTON_SIZE.medium]: "90px", @@ -49,7 +43,7 @@ const styles = { const BaseButton = styled.button` border: none; cursor: ${({ disabled }) => (disabled ? "default" : "pointer")}; - padding: ${({ $size }) => styles.padding[$size]}; + padding: 0 16px; font-size: ${({ $size }) => styles.fontSize[$size]}; font-weight: ${({ $size }) => styles.fontWeight[$size]}; line-height: ${({ $size }) => styles.lineHeight[$size]}; @@ -61,6 +55,7 @@ const BaseButton = styled.button` /* Primary Button */ const StyledPrimaryButton = styled(BaseButton)` + padding: 0 24px; background-color: var(--color-purple-600); color: white; From df7da27f199f3136aa5398e364d0e2e8b3e837a0 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 9 Aug 2025 22:35:35 +0900 Subject: [PATCH 016/253] =?UTF-8?q?fix=20[#2]=20Button=20=EC=B5=9C?= =?UTF-8?q?=EC=86=8C=20=EB=84=88=EB=B9=84=EA=B0=80=20button=EC=9D=B4=20?= =?UTF-8?q?=EC=95=84=EB=8B=8C=20text=EC=97=90=20=EC=A0=81=EC=9A=A9?= =?UTF-8?q?=EB=90=98=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/button/button.jsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/button/button.jsx b/src/components/button/button.jsx index 0dffa46..b456e3e 100644 --- a/src/components/button/button.jsx +++ b/src/components/button/button.jsx @@ -49,7 +49,11 @@ const BaseButton = styled.button` line-height: ${({ $size }) => styles.lineHeight[$size]}; border-radius: ${({ $size }) => styles.borderRadius[$size]}; height: ${({ $size }) => styles.height[$size]}; - min-width: ${({ $size }) => styles.minWidth[$size]}; + + span { + display: block; + min-width: ${({ $size }) => styles.minWidth[$size]}; + } `; /* Primary Button */ From 91fe673626bbfe032017ef378429706ef613fa1a Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 9 Aug 2025 22:56:53 +0900 Subject: [PATCH 017/253] =?UTF-8?q?feat=20[#2]=20Icon=EC=9D=B4=20=EB=93=A4?= =?UTF-8?q?=EC=96=B4=EA=B0=84=20`OutlinedButton`=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Icon을 포함하는 disabled 상태의 `OutlinedButton`에서 icon 색상을 white로 변경하는 방법을 찾아서 나중에 추가로 구현할 예정입니다. --- src/assets/ic-face-smile-add.svg | 3 ++ src/components/button/button.jsx | 52 +++++++++++++++++++++++++++----- src/pages/test-page.jsx | 25 ++++++++++++++- 3 files changed, 72 insertions(+), 8 deletions(-) create mode 100644 src/assets/ic-face-smile-add.svg diff --git a/src/assets/ic-face-smile-add.svg b/src/assets/ic-face-smile-add.svg new file mode 100644 index 0000000..be50156 --- /dev/null +++ b/src/assets/ic-face-smile-add.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/button/button.jsx b/src/components/button/button.jsx index b456e3e..747eef7 100644 --- a/src/components/button/button.jsx +++ b/src/components/button/button.jsx @@ -8,12 +8,12 @@ const styles = { [BUTTON_SIZE.small]: "90px", [BUTTON_SIZE.extraSmall]: "90px", }, - height: { + height: (hasIcon) => ({ [BUTTON_SIZE.large]: "56px", [BUTTON_SIZE.medium]: "40px", [BUTTON_SIZE.small]: "36px", - [BUTTON_SIZE.extraSmall]: "28px", - }, + [BUTTON_SIZE.extraSmall]: hasIcon ? "32px" : "28px", + }), fontSize: { [BUTTON_SIZE.large]: "18px", [BUTTON_SIZE.medium]: "16px", @@ -48,7 +48,7 @@ const BaseButton = styled.button` font-weight: ${({ $size }) => styles.fontWeight[$size]}; line-height: ${({ $size }) => styles.lineHeight[$size]}; border-radius: ${({ $size }) => styles.borderRadius[$size]}; - height: ${({ $size }) => styles.height[$size]}; + height: ${({ $size, $icon }) => styles.height($icon)[$size]}; span { display: block; @@ -153,10 +153,48 @@ const StyledOutlinedButton = styled(BaseButton)` } `; -function OutlinedButton({ title, size, ...props }) { +const stylesWithIcon = { + iconSize: { + [BUTTON_SIZE.medium]: "24px", + [BUTTON_SIZE.small]: "24px", + [BUTTON_SIZE.extraSmall]: "20px", + }, + gap: { + [BUTTON_SIZE.medium]: "10px", + [BUTTON_SIZE.small]: "4px", + [BUTTON_SIZE.extraSmall]: "4px", + }, +}; + +const IconTitleContent = styled.div` + display: flex; + align-items: center; + gap: ${({ $size }) => stylesWithIcon.gap[$size]}; + + & > div:first-child { + width: ${({ $size }) => stylesWithIcon.iconSize[$size]}; + height: ${({ $size }) => stylesWithIcon.iconSize[$size]}; + + img { + width: 100%; + height: 100%; + } + } +`; + +function OutlinedButton({ title, icon, size, ...props }) { return ( - - {title} + + {icon && size !== BUTTON_SIZE.large ? ( + +
+ 버튼 아이콘 +
+ {title} +
+ ) : ( + {title} + )}
); } diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index 40b985e..3d7da7e 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -1,3 +1,4 @@ +import smileAddImg from "../assets/ic-face-smile-add.svg"; import ArrowButton from "../components/button/arrow-button"; import ARROW_BUTTON_DIRECTION from "../components/button/arrow-button-direction"; import { @@ -37,7 +38,29 @@ function TestPage() { - + +
+ + + +
From 70662f9b20e7a10d662a567b01fdafc96b1c2cbd Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 9 Aug 2025 23:11:20 +0900 Subject: [PATCH 018/253] =?UTF-8?q?feat=20[#2]=20Icon=EB=A7=8C=20=EC=9E=88?= =?UTF-8?q?=EB=8A=94=20`OutlinedButton`=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/button/button.jsx | 8 ++++++-- src/pages/test-page.jsx | 10 ++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/components/button/button.jsx b/src/components/button/button.jsx index 747eef7..63569fd 100644 --- a/src/components/button/button.jsx +++ b/src/components/button/button.jsx @@ -133,6 +133,9 @@ const StyledOutlinedButton = styled(BaseButton)` background-color: white; color: var(--color-gray-900); box-shadow: 0 0 0 1px var(--color-gray-300) inset; + padding: ${({ $title }) => ($title ? "0 16px" : "0 6px")}; + width: ${({ $icon, $size, $title }) => + $title ? "auto" : styles.height($icon)[$size]}; &:hover { background-color: var(--color-gray-100); @@ -168,6 +171,7 @@ const stylesWithIcon = { const IconTitleContent = styled.div` display: flex; + justify-content: center; align-items: center; gap: ${({ $size }) => stylesWithIcon.gap[$size]}; @@ -184,13 +188,13 @@ const IconTitleContent = styled.div` function OutlinedButton({ title, icon, size, ...props }) { return ( - + {icon && size !== BUTTON_SIZE.large ? (
버튼 아이콘
- {title} + {title &&
{title}
}
) : ( {title} diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index 3d7da7e..5eefb34 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -62,6 +62,16 @@ function TestPage() { icon={smileAddImg} />
+
+ + + + +
From dfc41d21b7c9bc343239f2d6bb3112c5026eaf8f Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sun, 10 Aug 2025 09:51:17 +0900 Subject: [PATCH 019/253] =?UTF-8?q?docs:=20PR=20template=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - '연관된 이슈' 항목은 PR 자체의 issue 연결 기능을 활용할 수 있으므로 제거합니다. - '해결해야 하는 문제', '새로 알게 된 내용' 선택 항목을 추가했습니다. --- .github/pull_request_template.md | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 435f85d..ae8c42a 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,15 +1,23 @@ -## #️⃣연관된 이슈 +## 📝작업 내용 -> ex) #이슈번호, #이슈번호 +> 이번 PR에서 작업한 내용을 간략히 설명해주세요. -## 📝작업 내용 +## 📷 스크린샷 (선택) + +> 이번 PR에서 작업한 내용이 UI를 변경했다면 작업 결과물을 스크린샷으로 첨부해주세요. +> 스크린샷으로 작업한 결과물을 잘 보여주면 리뷰어가 프로젝트를 직접 실행해서 결과를 확인해야하는 수고를 줄여줄 수도 있습니다. + +## 🧐 해결해야 하는 문제 (선택) + +> 이번 PR에서 구현하지 못했거나 개발하면서 어려움을 겪은 내용을 공유해주세요. +> 리뷰어와 겪은 문제를 공유하면 혼자 고민하는 것 보다 빠르게 문제를 해결할 수도 있습니다. -> 이번 PR에서 작업한 내용을 간략히 설명해주세요(이미지 첨부 가능) +## 👀 새로 알게 된 내용 (선택) -### 스크린샷 (선택) +> 이번 PR을 작업하면서 새로 알게 된 내용을 간략하게 리뷰어와 공유해주세요. +> 리뷰어도 몰랐던 내용이라면 도움이 될 수 있고, 글로 작성하는 과정을 통해 기억에 더 오래 남길 수 있습니다. -## 💬리뷰 요구사항(선택) +## 💬리뷰 요구사항 (선택) > 리뷰어가 특별히 봐주었으면 하는 부분이 있다면 작성해주세요 -> > ex) 메서드 XXX의 이름을 더 잘 짓고 싶은데 혹시 좋은 명칭이 있을까요? From 4acaace410b304a9b87b8461c43f3357eda887e8 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sun, 10 Aug 2025 10:29:44 +0900 Subject: [PATCH 020/253] =?UTF-8?q?feat=20[#2]=20`OutlinedButton`=EC=9D=B4?= =?UTF-8?q?=20disabled=20=EC=83=81=ED=83=9C=EC=9D=BC=20=EB=95=8C=20icon=20?= =?UTF-8?q?=EC=83=89=EC=83=81=EB=8F=84=20=ED=9D=B0=EC=83=89=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/button/button.jsx | 23 ++++++++++++++--------- src/pages/test-page.jsx | 1 + 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/components/button/button.jsx b/src/components/button/button.jsx index 63569fd..7b7a36f 100644 --- a/src/components/button/button.jsx +++ b/src/components/button/button.jsx @@ -174,15 +174,20 @@ const IconTitleContent = styled.div` justify-content: center; align-items: center; gap: ${({ $size }) => stylesWithIcon.gap[$size]}; +`; + +const Icon = styled.div` + width: ${({ $size }) => stylesWithIcon.iconSize[$size]}; + height: ${({ $size }) => stylesWithIcon.iconSize[$size]}; - & > div:first-child { - width: ${({ $size }) => stylesWithIcon.iconSize[$size]}; - height: ${({ $size }) => stylesWithIcon.iconSize[$size]}; + img { + width: 100%; + height: 100%; - img { - width: 100%; - height: 100%; - } + ${({ $disabled }) => + $disabled + ? "filter: invert(100%) sepia(0%) saturate(1%) hue-rotate(5deg) brightness(105%) contrast(101%);" + : ""} } `; @@ -191,9 +196,9 @@ function OutlinedButton({ title, icon, size, ...props }) { {icon && size !== BUTTON_SIZE.large ? ( -
+ 버튼 아이콘 -
+ {title &&
{title}
}
) : ( diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index 5eefb34..18ecfde 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -38,6 +38,7 @@ function TestPage() { +
Date: Mon, 11 Aug 2025 15:32:23 +0900 Subject: [PATCH 021/253] =?UTF-8?q?docs:=20PR=20temploate=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/pull_request_template.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index ae8c42a..82a02d5 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,4 +1,4 @@ -## 📝작업 내용 +## 📝 작업 내용 > 이번 PR에서 작업한 내용을 간략히 설명해주세요. @@ -17,7 +17,9 @@ > 이번 PR을 작업하면서 새로 알게 된 내용을 간략하게 리뷰어와 공유해주세요. > 리뷰어도 몰랐던 내용이라면 도움이 될 수 있고, 글로 작성하는 과정을 통해 기억에 더 오래 남길 수 있습니다. -## 💬리뷰 요구사항 (선택) +## 💬 리뷰어에게 남길 말 (선택) -> 리뷰어가 특별히 봐주었으면 하는 부분이 있다면 작성해주세요 +> 리뷰어가 특별히 봐주었으면 하는 부분이 있다면 작성해주세요. +> 위 4가지 항목 어디에도 해당되지 않는 애매한 내용은 여기에 작성해주세요. +> > ex) 메서드 XXX의 이름을 더 잘 짓고 싶은데 혹시 좋은 명칭이 있을까요? From dcb4588ad2ac8c780c6136562b97934d3758820d Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sun, 10 Aug 2025 14:09:25 +0900 Subject: [PATCH 022/253] =?UTF-8?q?feat=20[#3]=20`Badge`=20component=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/badge/badge-type.js | 8 ++++++ src/components/badge/badge.jsx | 44 ++++++++++++++++++++++++++++++ src/pages/test-page.jsx | 8 ++++++ 3 files changed, 60 insertions(+) create mode 100644 src/components/badge/badge-type.js create mode 100644 src/components/badge/badge.jsx diff --git a/src/components/badge/badge-type.js b/src/components/badge/badge-type.js new file mode 100644 index 0000000..6c9b086 --- /dev/null +++ b/src/components/badge/badge-type.js @@ -0,0 +1,8 @@ +const BADGE_TYPE = Object.freeze({ + acquaintance: "acquaintance", + coworker: "coworker", + family: "family", + friend: "friend", +}); + +export default BADGE_TYPE; diff --git a/src/components/badge/badge.jsx b/src/components/badge/badge.jsx new file mode 100644 index 0000000..41d1645 --- /dev/null +++ b/src/components/badge/badge.jsx @@ -0,0 +1,44 @@ +import styled from "styled-components"; +import BADGE_TYPE from "./badge-type"; + +const styles = { + [BADGE_TYPE.acquaintance]: { + backgroundColor: "var(--color-beige-100)", + color: "var(--color-beige-500)", + }, + [BADGE_TYPE.coworker]: { + backgroundColor: "var(--color-purple-100)", + color: "var(--color-purple-600)", + }, + [BADGE_TYPE.family]: { + backgroundColor: "var(--color-green-100)", + color: "var(--color-green-500)", + }, + [BADGE_TYPE.friend]: { + backgroundColor: "var(--color-blue-100)", + color: "var(--color-blue-500)", + }, +}; + +const title = { + [BADGE_TYPE.acquaintance]: "지인", + [BADGE_TYPE.coworker]: "동료", + [BADGE_TYPE.family]: "가족", + [BADGE_TYPE.friend]: "친구", +}; + +const StyledBadge = styled.div` + background-color: ${({ $type }) => styles[$type].backgroundColor}; + color: ${({ $type }) => styles[$type].color}; + border-radius: 4px; + padding: 0 8px; + font-size: 14px; + font-weight: 400; + line-height: 20px; +`; + +function Badge({ type }) { + return {title[type]}; +} + +export default Badge; diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index 18ecfde..8342b44 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -1,4 +1,6 @@ import smileAddImg from "../assets/ic-face-smile-add.svg"; +import Badge from "../components/badge/badge"; +import BADGE_TYPE from "../components/badge/badge-type"; import ArrowButton from "../components/button/arrow-button"; import ARROW_BUTTON_DIRECTION from "../components/button/arrow-button-direction"; import { @@ -88,6 +90,12 @@ function TestPage() {
+
+ + + + +
); } From b0c4826e71a3531c27b11179738dd1b9d6914282 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sun, 10 Aug 2025 14:30:55 +0900 Subject: [PATCH 023/253] =?UTF-8?q?feat=20[#3]=20`EmojiBadge`=20component?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/badge/emoji-badge.jsx | 29 ++++++++++++++++++++++++++++ src/pages/test-page.jsx | 7 +++++++ 2 files changed, 36 insertions(+) create mode 100644 src/components/badge/emoji-badge.jsx diff --git a/src/components/badge/emoji-badge.jsx b/src/components/badge/emoji-badge.jsx new file mode 100644 index 0000000..a674b72 --- /dev/null +++ b/src/components/badge/emoji-badge.jsx @@ -0,0 +1,29 @@ +import styled from "styled-components"; + +const StyledEmojiBadge = styled.div` + background-color: rgba(0, 0, 0, 0.54); + color: white; + font-size: 16px; + font-weight: 400; + line-height: 20px; + padding: 8px 12px; + border-radius: 32px; +`; + +const Content = styled.div` + display: flex; + gap: 4px; +`; + +function EmojiBadge({ emoji, count }) { + return ( + + + {emoji} + {count} + + + ); +} + +export default EmojiBadge; diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index 8342b44..705a521 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -1,6 +1,7 @@ import smileAddImg from "../assets/ic-face-smile-add.svg"; import Badge from "../components/badge/badge"; import BADGE_TYPE from "../components/badge/badge-type"; +import EmojiBadge from "../components/badge/emoji-badge"; import ArrowButton from "../components/button/arrow-button"; import ARROW_BUTTON_DIRECTION from "../components/button/arrow-button-direction"; import { @@ -96,6 +97,12 @@ function TestPage() { +
+ + + + +
); } From 15f296e011a422c95ed7abece4eef8c6f9ea4e86 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Mon, 11 Aug 2025 15:37:26 +0900 Subject: [PATCH 024/253] =?UTF-8?q?config:=20GitHub=20auto=20assign=20revi?= =?UTF-8?q?ewers=20=EB=AA=A9=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/auto_assign.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/auto_assign.yml b/.github/auto_assign.yml index 1acf262..d95e8fd 100644 --- a/.github/auto_assign.yml +++ b/.github/auto_assign.yml @@ -8,7 +8,6 @@ addAssignees: author reviewers: - cskime - gummmmmy0v0 - - KIMJUNHYEOK169 - nidor022 - onesiin From 0b5cf85325fffcd84b03f1f18409babfc7edcff8 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sun, 10 Aug 2025 15:04:41 +0900 Subject: [PATCH 025/253] =?UTF-8?q?feat=20[#1]=20Color=20CSS=20=EB=B3=80?= =?UTF-8?q?=EC=88=98=EB=A5=BC=20JavaScript=20=EB=AC=B8=EC=9E=90=EC=97=B4?= =?UTF-8?q?=EB=A1=9C=20=EC=82=AC=EC=9A=A9=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EB=8A=94=20=EA=B0=9D=EC=B2=B4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/color/colors.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/components/color/colors.js diff --git a/src/components/color/colors.js b/src/components/color/colors.js new file mode 100644 index 0000000..4c876bc --- /dev/null +++ b/src/components/color/colors.js @@ -0,0 +1,25 @@ +const shade = ({ min = 100, max = 900, value }) => { + return Math.min(Math.max(min, value), max); +}; + +const Colors = { + purple: function (value) { + return `var(--color-purple-${shade({ value })})`; + }, + beige: function (value) { + return `var(--color-beige-${shade({ max: 500, value })})`; + }, + blue: function (value) { + return `var(--color-blue-${shade({ max: 500, value })})`; + }, + green: function (value) { + return `var(--color-green-${shade({ max: 500, value })})`; + }, + gray: function (value) { + return `var(--color-gray-${shade({ value })})`; + }, + error: "var(--color-error)", + surface: "var(--color-surface)", +}; + +export default Colors; From 40b903bf7a8a3905cbf8fe3f6ffc5f4a990ceb87 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sun, 10 Aug 2025 15:04:57 +0900 Subject: [PATCH 026/253] =?UTF-8?q?refactor=20[#1]=20`Badge`=EC=97=90=20`C?= =?UTF-8?q?olors`=20=EA=B0=9D=EC=B2=B4=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/badge/badge.jsx | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/components/badge/badge.jsx b/src/components/badge/badge.jsx index 41d1645..9bc69ef 100644 --- a/src/components/badge/badge.jsx +++ b/src/components/badge/badge.jsx @@ -1,22 +1,23 @@ import styled from "styled-components"; +import Colors from "../color/colors"; import BADGE_TYPE from "./badge-type"; const styles = { [BADGE_TYPE.acquaintance]: { - backgroundColor: "var(--color-beige-100)", - color: "var(--color-beige-500)", + backgroundColor: Colors.beige(100), + color: Colors.beige(500), }, [BADGE_TYPE.coworker]: { - backgroundColor: "var(--color-purple-100)", - color: "var(--color-purple-600)", + backgroundColor: Colors.purple(100), + color: Colors.purple(600), }, [BADGE_TYPE.family]: { - backgroundColor: "var(--color-green-100)", - color: "var(--color-green-500)", + backgroundColor: Colors.green(100), + color: Colors.green(500), }, [BADGE_TYPE.friend]: { - backgroundColor: "var(--color-blue-100)", - color: "var(--color-blue-500)", + backgroundColor: Colors.blue(100), + color: Colors.blue(500), }, }; From 0893bf0602d78bdf07671fca445c8942159e0833 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sun, 10 Aug 2025 15:06:05 +0900 Subject: [PATCH 027/253] =?UTF-8?q?refactor=20[#1]=20`ArrowButton`?= =?UTF-8?q?=EC=97=90=20`Colors`=20=EA=B0=9D=EC=B2=B4=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/button/arrow-button.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/button/arrow-button.jsx b/src/components/button/arrow-button.jsx index a36d174..b1a53c9 100644 --- a/src/components/button/arrow-button.jsx +++ b/src/components/button/arrow-button.jsx @@ -1,6 +1,7 @@ import styled from "styled-components"; import arrowLeftImg from "../../assets/ic-chevron-left.svg"; import arrowRightImg from "../../assets/ic-chevron-right.svg"; +import Colors from "../color/colors"; import ARROW_BUTTON_DIRECTION from "./arrow-button-direction"; const arrowImg = { @@ -10,7 +11,7 @@ const arrowImg = { const StyledArrowButton = styled.button` background: none; - border: 1px solid var(--color-gray-300); + border: 1px solid ${Colors.gray(300)}; width: 40px; height: 40px; border-radius: 20px; From 9960df4a4a984ef9603ad845f1c87c43b8de728f Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sun, 10 Aug 2025 15:11:13 +0900 Subject: [PATCH 028/253] =?UTF-8?q?refactor=20[#1]=20`Primary/Secondary/Ou?= =?UTF-8?q?tlinedButton`=EC=97=90=20`Colors`=20=EA=B0=9D=EC=B2=B4=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/button/button.jsx | 45 ++++++++++++++++---------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/src/components/button/button.jsx b/src/components/button/button.jsx index 7b7a36f..283cf4f 100644 --- a/src/components/button/button.jsx +++ b/src/components/button/button.jsx @@ -1,4 +1,5 @@ import styled from "styled-components"; +import Colors from "../color/colors"; import BUTTON_SIZE from "./button-size"; const styles = { @@ -60,24 +61,24 @@ const BaseButton = styled.button` const StyledPrimaryButton = styled(BaseButton)` padding: 0 24px; - background-color: var(--color-purple-600); + background-color: ${Colors.purple(600)}; color: white; &:hover { - background-color: var(--color-purple-700); + background-color: ${Colors.purple(700)}; } &:active { - background-color: var(--color-purple-800); + background-color: ${Colors.purple(800)}; } &:focus { - background-color: var(--color-purple-800); - box-shadow: 0 0 0 1px var(--color-purple-900) inset; + background-color: ${Colors.purple(800)}; + box-shadow: 0 0 0 1px ${Colors.purple(900)} inset; } &:disabled { - background-color: var(--color-gray-300); + background-color: ${Colors.gray(300)}; } `; @@ -93,27 +94,27 @@ function PrimaryButton({ title, size, ...props }) { const StyledSecondaryButton = styled(BaseButton)` background-color: white; - color: var(--color-purple-700); - box-shadow: 0 0 0 1px var(--color-purple-600) inset; + color: ${Colors.purple(700)}; + box-shadow: 0 0 0 1px ${Colors.purple(600)} inset; &:hover { - background-color: var(--color-purple-100); - color: var(--color-purple-600); - box-shadow: 0 0 0 1px var(--color-purple-700) inset; + background-color: ${Colors.purple(100)}; + color: ${Colors.purple(600)}; + box-shadow: 0 0 0 1px ${Colors.purple(700)} inset; } &:active { - background-color: var(--color-purple-100); - color: var(--color-purple-600); - box-shadow: 0 0 0 1px var(--color-purple-800) inset; + background-color: ${Colors.purple(100)}; + color: ${Colors.purple(600)}; + box-shadow: 0 0 0 1px ${Colors.purple(800)} inset; } &:focus { - box-shadow: 0 0 0 1px var(--color-purple-800) inset; + box-shadow: 0 0 0 1px ${Colors.purple(800)} inset; } &:disabled { - background-color: var(--color-gray-300); + background-color: ${Colors.gray(300)}; color: white; box-shadow: none; } @@ -131,26 +132,26 @@ function SecondaryButton({ title, size, ...props }) { const StyledOutlinedButton = styled(BaseButton)` background-color: white; - color: var(--color-gray-900); - box-shadow: 0 0 0 1px var(--color-gray-300) inset; + color: ${Colors.gray(900)}; + box-shadow: 0 0 0 1px ${Colors.gray(300)} inset; padding: ${({ $title }) => ($title ? "0 16px" : "0 6px")}; width: ${({ $icon, $size, $title }) => $title ? "auto" : styles.height($icon)[$size]}; &:hover { - background-color: var(--color-gray-100); + background-color: ${Colors.gray(100)}; } &:active { - background-color: var(--color-gray-100); + background-color: ${Colors.gray(100)}; } &:focus { - box-shadow: 0 0 0 1px var(--color-gray-500) inset; + box-shadow: 0 0 0 1px ${Colors.gray(500)} inset; } &:disabled { - background-color: var(--color-gray-300); + background-color: ${Colors.gray(300)}; color: white; box-shadow: none; } From 655727e8470842c888f195377ffe97c67ef25be6 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sun, 10 Aug 2025 15:13:31 +0900 Subject: [PATCH 029/253] =?UTF-8?q?refactor=20[#1]=20`ToggleButton`?= =?UTF-8?q?=EC=97=90=20`Colors`=20=EA=B0=9D=EC=B2=B4=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/button/toggle-button.jsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/button/toggle-button.jsx b/src/components/button/toggle-button.jsx index a0cfc20..03a6643 100644 --- a/src/components/button/toggle-button.jsx +++ b/src/components/button/toggle-button.jsx @@ -1,8 +1,9 @@ import { useState } from "react"; import styled from "styled-components"; +import Colors from "../color/colors"; const StyledToggleButton = styled.div` - background-color: var(--color-gray-100); + background-color: ${Colors.gray(100)}; border-radius: 6px; `; @@ -10,9 +11,9 @@ const ToggleItem = styled.button` background: ${({ $selected }) => ($selected ? "white" : "none")}; border: none; color: ${({ $selected }) => - $selected ? "var(--color-purple-700)" : "var(--color-gray-900)"}; + $selected ? Colors.purple(700) : Colors.gray(900)}; box-shadow: ${({ $selected }) => - $selected ? "0 0 0 2px var(--color-purple-600) inset" : "none"}; + $selected ? `0 0 0 2px ${Colors.purple(600)} inset` : "none"}; border-radius: 6px; padding: 0 16px; height: 40px; From c87ad1642692e55039006fb5217fc55ec184811e Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Mon, 11 Aug 2025 12:47:09 +0900 Subject: [PATCH 030/253] =?UTF-8?q?feat=20[#5]=20`TextField`=20component?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84=20(text=20input)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `TextField`는 `TEXT_FIELD_TYPE`을 설정해서 text input 방식 또는 dropdown select 방식 중 하나로 사용 가능 --- src/components/text-field/dropdown-input.jsx | 3 ++ src/components/text-field/input-styles.js | 27 ++++++++++++ src/components/text-field/text-field-type.js | 6 +++ src/components/text-field/text-field.jsx | 34 +++++++++++++++ src/components/text-field/text-input.jsx | 45 ++++++++++++++++++++ src/pages/test-page.jsx | 16 +++++++ 6 files changed, 131 insertions(+) create mode 100644 src/components/text-field/dropdown-input.jsx create mode 100644 src/components/text-field/input-styles.js create mode 100644 src/components/text-field/text-field-type.js create mode 100644 src/components/text-field/text-field.jsx create mode 100644 src/components/text-field/text-input.jsx diff --git a/src/components/text-field/dropdown-input.jsx b/src/components/text-field/dropdown-input.jsx new file mode 100644 index 0000000..40d7f53 --- /dev/null +++ b/src/components/text-field/dropdown-input.jsx @@ -0,0 +1,3 @@ +function DropdownInput() {} + +export default DropdownInput; diff --git a/src/components/text-field/input-styles.js b/src/components/text-field/input-styles.js new file mode 100644 index 0000000..24b7b4c --- /dev/null +++ b/src/components/text-field/input-styles.js @@ -0,0 +1,27 @@ +import { css } from "styled-components"; +import Colors from "../color/colors"; + +const INPUT_STYLES = Object.freeze({ + font: css` + font-size: 16px; + font-weight: 400; + line-height: 26px; + `, + borderColor: { + normal: (error) => (error ? Colors.error : Colors.gray(300)), + hover: (error) => (error ? Colors.error : Colors.gray(500)), + active: (error) => (error ? Colors.error : Colors.gray(700)), + focus: (error) => (error ? Colors.error : Colors.gray(500)), + disabled: Colors.gray(300), + }, + textColor: { + normal: Colors.gray(900), + placeholder: Colors.gray(500), + }, + backgroundColor: { + normal: "#ffffff", + disabled: Colors.gray(100), + }, +}); + +export default INPUT_STYLES; diff --git a/src/components/text-field/text-field-type.js b/src/components/text-field/text-field-type.js new file mode 100644 index 0000000..80da361 --- /dev/null +++ b/src/components/text-field/text-field-type.js @@ -0,0 +1,6 @@ +const TEXT_FIELD_TYPE = Object.freeze({ + input: "input", + dropdown: "dropdown", +}); + +export default TEXT_FIELD_TYPE; diff --git a/src/components/text-field/text-field.jsx b/src/components/text-field/text-field.jsx new file mode 100644 index 0000000..d36375f --- /dev/null +++ b/src/components/text-field/text-field.jsx @@ -0,0 +1,34 @@ +import styled from "styled-components"; +import Colors from "../color/colors"; +import DropdownInput from "./dropdown-input"; +import TEXT_FIELD_TYPE from "./text-field-type"; +import TextInput from "./text-input"; + +const StyledInputTextField = styled.div` + display: flex; + flex-direction: column; + gap: 4px; +`; + +const ErrorMessage = styled.p` + margin: 0; + font-size: 12px; + font-weight: 400; + line-height: 18px; + color: ${Colors.error}; +`; + +function InputTextField({ type, error, ...props }) { + return ( + + {type === TEXT_FIELD_TYPE.input ? ( + + ) : ( + + )} + {error && {error}} + + ); +} + +export default InputTextField; diff --git a/src/components/text-field/text-input.jsx b/src/components/text-field/text-input.jsx new file mode 100644 index 0000000..c02badd --- /dev/null +++ b/src/components/text-field/text-input.jsx @@ -0,0 +1,45 @@ +import styled from "styled-components"; +import INPUT_STYLES from "./input-styles"; + +const StyledTextInput = styled.input` + background-color: ${INPUT_STYLES.backgroundColor.normal}; + outline: none; + border: none; + border-radius: 8px; + box-shadow: 0 0 0 1px + ${({ $error }) => INPUT_STYLES.borderColor.normal($error)} inset; + padding: 12px 16px; + ${INPUT_STYLES.font} + color: ${INPUT_STYLES.textColor.normal}; + + &::placeholder { + ${INPUT_STYLES.font} + color: ${INPUT_STYLES.textColor.placeholder}; + } + + &:hover { + box-shadow: 0 0 0 1px + ${({ $error }) => INPUT_STYLES.borderColor.hover($error)} inset; + } + + &:active { + box-shadow: 0 0 0 2px + ${({ $error }) => INPUT_STYLES.borderColor.active($error)} inset; + } + + &:focus { + box-shadow: 0 0 0 2px + ${({ $error }) => INPUT_STYLES.borderColor.focus($error)} inset; + } + + &:disabled { + background-color: ${INPUT_STYLES.backgroundColor.disabled}; + box-shadow: 0 0 0 1px ${INPUT_STYLES.borderColor.disabled} inset; + } +`; + +function TextInput({ error, ...props }) { + return ; +} + +export default TextInput; diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index 705a521..cdc1c56 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -11,6 +11,8 @@ import { } from "../components/button/button"; import BUTTON_SIZE from "../components/button/button-size"; import ToggleButton from "../components/button/toggle-button"; +import TextField from "../components/text-field/text-field"; +import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; function TestPage() { return ( @@ -103,6 +105,20 @@ function TestPage() { +
+ + + +
); } From f44f7b0c1746654af8c276fb6e820f62aa4b9685 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Mon, 11 Aug 2025 13:04:39 +0900 Subject: [PATCH 031/253] =?UTF-8?q?feat=20[#5]=20`TextField`=20component?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84=20(dropdown=20input)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/ic-chevron-down.svg | 3 + src/assets/ic-chevron-up.svg | 3 + src/components/text-field/dropdown-input.jsx | 79 +++++++++++++++++++- src/components/text-field/text-field.jsx | 2 +- src/pages/test-page.jsx | 14 ++++ 5 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 src/assets/ic-chevron-down.svg create mode 100644 src/assets/ic-chevron-up.svg diff --git a/src/assets/ic-chevron-down.svg b/src/assets/ic-chevron-down.svg new file mode 100644 index 0000000..412d030 --- /dev/null +++ b/src/assets/ic-chevron-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/ic-chevron-up.svg b/src/assets/ic-chevron-up.svg new file mode 100644 index 0000000..536315f --- /dev/null +++ b/src/assets/ic-chevron-up.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/text-field/dropdown-input.jsx b/src/components/text-field/dropdown-input.jsx index 40d7f53..e0f1d13 100644 --- a/src/components/text-field/dropdown-input.jsx +++ b/src/components/text-field/dropdown-input.jsx @@ -1,3 +1,80 @@ -function DropdownInput() {} +import styled from "styled-components"; +import arrowDownImg from "../../assets/ic-chevron-down.svg"; +import INPUT_STYLES from "./input-styles"; + +const StyledDropdownInput = styled.button` + background-color: ${INPUT_STYLES.backgroundColor.normal}; + outline: none; + border: none; + border-radius: 8px; + box-shadow: 0 0 0 1px + ${({ $error }) => INPUT_STYLES.borderColor.normal($error)} inset; + padding: 12px 16px; + min-width: 320px; + display: flex; + align-items: center; + gap: 8px; + cursor: pointer; + + &:hover { + box-shadow: 0 0 0 1px + ${({ $error }) => INPUT_STYLES.borderColor.hover($error)} inset; + } + + &:active { + box-shadow: 0 0 0 2px + ${({ $error }) => INPUT_STYLES.borderColor.active($error)} inset; + } + + &:focus { + box-shadow: 0 0 0 2px + ${({ $error }) => INPUT_STYLES.borderColor.focus($error)} inset; + } + + &:disabled { + background-color: ${INPUT_STYLES.backgroundColor.disabled}; + box-shadow: 0 0 0 1px ${INPUT_STYLES.borderColor.disabled} inset; + cursor: default; + } +`; + +const PlaceholderText = styled.span` + ${INPUT_STYLES.font} + color: ${INPUT_STYLES.textColor.placeholder}; + flex-grow: 1; + text-align: left; +`; + +const InputText = styled.span` + ${INPUT_STYLES.font} + color: ${INPUT_STYLES.textColor.normal}; + flex-grow: 1; + text-align: left; +`; + +const Icon = styled.div` + width: 16px; + height: 16px; + + img { + width: 100%; + height: 100%; + } +`; + +function DropdownInput({ error, placeholder, value, disabled }) { + return ( + + {value ? ( + {value} + ) : ( + {placeholder} + )} + + Dropdown 화살표 + + + ); +} export default DropdownInput; diff --git a/src/components/text-field/text-field.jsx b/src/components/text-field/text-field.jsx index d36375f..831214c 100644 --- a/src/components/text-field/text-field.jsx +++ b/src/components/text-field/text-field.jsx @@ -24,7 +24,7 @@ function InputTextField({ type, error, ...props }) { {type === TEXT_FIELD_TYPE.input ? ( ) : ( - + )} {error && {error}} diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index cdc1c56..258c0b4 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -119,6 +119,20 @@ function TestPage() { error="Error Message" /> +
+ + + +
); } From baa8f6d3d02352a094e57b89d2008fd9e5c8cc65 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Mon, 11 Aug 2025 13:45:16 +0900 Subject: [PATCH 032/253] =?UTF-8?q?feat=20[#5]=20Dropdown=20text=20field?= =?UTF-8?q?=EC=97=90=20interaction=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Dropdown type의 `TextField`를 선택하면 dropdown 표시 - Dropdown의 option 1개를 클릭하면 해당 `TextField`의 `value`가 선택된 값으로 교체 --- src/components/text-field/dropdown-input.jsx | 86 +++++++++++++++++--- src/pages/test-page.jsx | 26 +++++- 2 files changed, 98 insertions(+), 14 deletions(-) diff --git a/src/components/text-field/dropdown-input.jsx b/src/components/text-field/dropdown-input.jsx index e0f1d13..7b8fae8 100644 --- a/src/components/text-field/dropdown-input.jsx +++ b/src/components/text-field/dropdown-input.jsx @@ -1,10 +1,11 @@ +import { useState } from "react"; import styled from "styled-components"; import arrowDownImg from "../../assets/ic-chevron-down.svg"; +import Colors from "../color/colors"; import INPUT_STYLES from "./input-styles"; const StyledDropdownInput = styled.button` background-color: ${INPUT_STYLES.backgroundColor.normal}; - outline: none; border: none; border-radius: 8px; box-shadow: 0 0 0 1px @@ -15,6 +16,7 @@ const StyledDropdownInput = styled.button` align-items: center; gap: 8px; cursor: pointer; + position: relative; &:hover { box-shadow: 0 0 0 1px @@ -62,18 +64,78 @@ const Icon = styled.div` } `; -function DropdownInput({ error, placeholder, value, disabled }) { +const Dropdown = styled.div` + background-color: white; + box-shadow: 0 0 0 1px ${Colors.gray(300)} inset, + 0 2px 12px 0 rgba(0, 0, 0, 0.08); + border-radius: 8px; + display: flex; + flex-direction: column; + align-items: center; + padding: 10px 0; + position: absolute; + top: calc(100% + 8px); + left: 0; + right: 0; +`; + +const DropdownOption = styled.div` + width: calc(100% - 2px); + border: none; + background: none; + padding: 12px 16px; + font-size: 16px; + font-weight: 400; + line-height: 26px; + color: ${Colors.gray(900)}; + cursor: pointer; + + &:hover { + background-color: ${Colors.gray(100)}; + } +`; + +function DropdownInput({ + error, + placeholder, + value, + options, + disabled, + onSelect, +}) { + const [isOpen, setIsOpen] = useState(false); + + const handleInputClick = (event) => { + setIsOpen(!isOpen); + onSelect(event.target.textContent); + }; + return ( - - {value ? ( - {value} - ) : ( - {placeholder} - )} - - Dropdown 화살표 - - + <> + + {value ? ( + {value} + ) : ( + {placeholder} + )} + + Dropdown 화살표 + + {isOpen && ( + + {options.map((option, index) => ( + + {option} + + ))} + + )} + + ); } diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index 258c0b4..0300ce8 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -1,3 +1,4 @@ +import { useState } from "react"; import smileAddImg from "../assets/ic-face-smile-add.svg"; import Badge from "../components/badge/badge"; import BADGE_TYPE from "../components/badge/badge-type"; @@ -15,6 +16,17 @@ import TextField from "../components/text-field/text-field"; import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; function TestPage() { + const [option1, setOption1] = useState(); + const [option2, setOption2] = useState(); + const [dropdown2Error, setDropdown2Error] = useState("Error Message"); + const handleDropdownSelect1 = (option) => { + setOption1(option); + }; + const handleDropdownSelect2 = (option) => { + setOption2(option); + setDropdown2Error(null); + }; + return (
- +
From d2fa0106a92bdefd82f45c06233ce3e774f5d1f8 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Mon, 11 Aug 2025 13:46:14 +0900 Subject: [PATCH 033/253] =?UTF-8?q?feat=20[#5]=20Dropdown=EC=9D=B4=20?= =?UTF-8?q?=EC=97=B4=EB=A0=B8=EC=9D=84=20=EB=95=8C=20=ED=99=94=EC=82=B4?= =?UTF-8?q?=ED=91=9C=20=EB=B0=A9=ED=96=A5=20=ED=9A=8C=EC=A0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/text-field/dropdown-input.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/text-field/dropdown-input.jsx b/src/components/text-field/dropdown-input.jsx index 7b8fae8..f706308 100644 --- a/src/components/text-field/dropdown-input.jsx +++ b/src/components/text-field/dropdown-input.jsx @@ -1,6 +1,7 @@ import { useState } from "react"; import styled from "styled-components"; import arrowDownImg from "../../assets/ic-chevron-down.svg"; +import arrowUpImg from "../../assets/ic-chevron-up.svg"; import Colors from "../color/colors"; import INPUT_STYLES from "./input-styles"; @@ -123,7 +124,7 @@ function DropdownInput({ {placeholder} )} - Dropdown 화살표 + Dropdown 화살표 {isOpen && ( From 2e6cf98f0283280097035584515d7e4136d6b095 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Mon, 11 Aug 2025 13:48:19 +0900 Subject: [PATCH 034/253] =?UTF-8?q?refactor=20[#5]=20`DropdownInput`?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EA=B8=B0=EB=B3=B8=20props=EB=8A=94=20spre?= =?UTF-8?q?ad=20=EB=AC=B8=EB=B2=95=EC=9C=BC=EB=A1=9C=20=EC=A7=81=EC=A0=91?= =?UTF-8?q?=20=EC=A0=84=EB=8B=AC=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/text-field/dropdown-input.jsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/components/text-field/dropdown-input.jsx b/src/components/text-field/dropdown-input.jsx index f706308..7d69d91 100644 --- a/src/components/text-field/dropdown-input.jsx +++ b/src/components/text-field/dropdown-input.jsx @@ -101,8 +101,8 @@ function DropdownInput({ placeholder, value, options, - disabled, onSelect, + ...props }) { const [isOpen, setIsOpen] = useState(false); @@ -113,11 +113,7 @@ function DropdownInput({ return ( <> - + {value ? ( {value} ) : ( From 441d45415c60e1562d8914cdf7d68fcc08c6ed5c Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Mon, 11 Aug 2025 19:20:20 +0900 Subject: [PATCH 035/253] =?UTF-8?q?fix=20[#5]=20`TextInput`=EC=9D=84=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=A0=20=EB=95=8C=20=EC=B5=9C=EC=86=8C=20?= =?UTF-8?q?=EB=84=88=EB=B9=84=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/text-field/text-input.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/text-field/text-input.jsx b/src/components/text-field/text-input.jsx index c02badd..be94af4 100644 --- a/src/components/text-field/text-input.jsx +++ b/src/components/text-field/text-input.jsx @@ -11,6 +11,7 @@ const StyledTextInput = styled.input` padding: 12px 16px; ${INPUT_STYLES.font} color: ${INPUT_STYLES.textColor.normal}; + min-width: 320px; &::placeholder { ${INPUT_STYLES.font} From 165f79dffcc887ba936a318425f488f106d0491c Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 12 Aug 2025 10:29:04 +0900 Subject: [PATCH 036/253] =?UTF-8?q?feat=20[#5]=20Dropdown=20text=20field?= =?UTF-8?q?=EC=97=90=EC=84=9C=20dropdown=20=EB=B0=94=EA=B9=A5=EC=9D=84=20?= =?UTF-8?q?=ED=81=B4=EB=A6=AD=ED=95=B4=EC=84=9C=20dropdown=20=EB=8B=AB?= =?UTF-8?q?=EA=B8=B0=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit React의 portal 개념을 활용해서 구현합니다. --- index.html | 1 + src/app.jsx | 7 +- .../dropdown-input/dropdown-context.js | 5 + .../{ => dropdown-input}/dropdown-input.jsx | 152 +++++++++--------- .../dropdown-input/dropdown-option.jsx | 20 +++ .../dropdown-input/dropdown-provider.jsx | 10 ++ .../text-field/dropdown-input/dropdown.jsx | 66 ++++++++ src/components/text-field/text-field.jsx | 8 +- .../{ => text-input}/text-input.jsx | 2 +- src/hooks/dropdown/use-dropdown.jsx | 54 +++++++ src/pages/test-page.jsx | 3 + 11 files changed, 249 insertions(+), 79 deletions(-) create mode 100644 src/components/text-field/dropdown-input/dropdown-context.js rename src/components/text-field/{ => dropdown-input}/dropdown-input.jsx (53%) create mode 100644 src/components/text-field/dropdown-input/dropdown-option.jsx create mode 100644 src/components/text-field/dropdown-input/dropdown-provider.jsx create mode 100644 src/components/text-field/dropdown-input/dropdown.jsx rename src/components/text-field/{ => text-input}/text-input.jsx (96%) create mode 100644 src/hooks/dropdown/use-dropdown.jsx diff --git a/index.html b/index.html index 3c20db6..e57d567 100644 --- a/index.html +++ b/index.html @@ -15,6 +15,7 @@
+ diff --git a/src/app.jsx b/src/app.jsx index c2cf85c..81ae363 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -1,7 +1,12 @@ +import DropdownProvider from "./components/text-field/dropdown-input/dropdown-provider"; import TestPage from "./pages/test-page"; function App() { - return ; + return ( + + + + ); } export default App; diff --git a/src/components/text-field/dropdown-input/dropdown-context.js b/src/components/text-field/dropdown-input/dropdown-context.js new file mode 100644 index 0000000..34a3d95 --- /dev/null +++ b/src/components/text-field/dropdown-input/dropdown-context.js @@ -0,0 +1,5 @@ +import { createContext } from "react"; + +const DropdownContext = createContext(null); + +export default DropdownContext; diff --git a/src/components/text-field/dropdown-input.jsx b/src/components/text-field/dropdown-input/dropdown-input.jsx similarity index 53% rename from src/components/text-field/dropdown-input.jsx rename to src/components/text-field/dropdown-input/dropdown-input.jsx index 7d69d91..09c937b 100644 --- a/src/components/text-field/dropdown-input.jsx +++ b/src/components/text-field/dropdown-input/dropdown-input.jsx @@ -1,9 +1,42 @@ -import { useState } from "react"; import styled from "styled-components"; -import arrowDownImg from "../../assets/ic-chevron-down.svg"; -import arrowUpImg from "../../assets/ic-chevron-up.svg"; -import Colors from "../color/colors"; -import INPUT_STYLES from "./input-styles"; +import arrowDownImg from "../../../assets/ic-chevron-down.svg"; +import arrowUpImg from "../../../assets/ic-chevron-up.svg"; +import { useDropdown } from "../../../hooks/dropdown/use-dropdown"; +import INPUT_STYLES from "../input-styles"; +import Dropdown from "./dropdown"; +import DropdownOption from "./dropdown-option"; + +const PlaceholderText = styled.span` + ${INPUT_STYLES.font} + color: ${INPUT_STYLES.textColor.placeholder}; + flex-grow: 1; + text-align: left; +`; + +const InputText = styled.span` + ${INPUT_STYLES.font} + color: ${INPUT_STYLES.textColor.normal}; + flex-grow: 1; + text-align: left; +`; + +function Text({ value, placeholder }) { + return value ? ( + {value} + ) : ( + {placeholder} + ); +} + +const Icon = styled.div` + width: 16px; + height: 16px; + + img { + width: 100%; + height: 100%; + } +`; const StyledDropdownInput = styled.button` background-color: ${INPUT_STYLES.backgroundColor.normal}; @@ -41,62 +74,8 @@ const StyledDropdownInput = styled.button` } `; -const PlaceholderText = styled.span` - ${INPUT_STYLES.font} - color: ${INPUT_STYLES.textColor.placeholder}; - flex-grow: 1; - text-align: left; -`; - -const InputText = styled.span` - ${INPUT_STYLES.font} - color: ${INPUT_STYLES.textColor.normal}; - flex-grow: 1; - text-align: left; -`; - -const Icon = styled.div` - width: 16px; - height: 16px; - - img { - width: 100%; - height: 100%; - } -`; - -const Dropdown = styled.div` - background-color: white; - box-shadow: 0 0 0 1px ${Colors.gray(300)} inset, - 0 2px 12px 0 rgba(0, 0, 0, 0.08); - border-radius: 8px; - display: flex; - flex-direction: column; - align-items: center; - padding: 10px 0; - position: absolute; - top: calc(100% + 8px); - left: 0; - right: 0; -`; - -const DropdownOption = styled.div` - width: calc(100% - 2px); - border: none; - background: none; - padding: 12px 16px; - font-size: 16px; - font-weight: 400; - line-height: 26px; - color: ${Colors.gray(900)}; - cursor: pointer; - - &:hover { - background-color: ${Colors.gray(100)}; - } -`; - function DropdownInput({ + dropdownId, error, placeholder, value, @@ -104,28 +83,55 @@ function DropdownInput({ onSelect, ...props }) { - const [isOpen, setIsOpen] = useState(false); + const { + targetRef, + dropdownRect, + showsDropdown, + setShowsDropdown, + handleTargetClick, + } = useDropdown({ + id: dropdownId, + type: "dropdown-input", + }); + + const handleInputClick = () => { + handleTargetClick(!showsDropdown); + }; - const handleInputClick = (event) => { - setIsOpen(!isOpen); + const handleOptionClick = (event) => { onSelect(event.target.textContent); }; + const handleDropdownClose = () => { + setShowsDropdown(false); + }; + return ( <> - - {value ? ( - {value} - ) : ( - {placeholder} - )} + + - Dropdown 화살표 + Dropdown 화살표 - {isOpen && ( - + {showsDropdown && ( + {options.map((option, index) => ( - + {option} ))} diff --git a/src/components/text-field/dropdown-input/dropdown-option.jsx b/src/components/text-field/dropdown-input/dropdown-option.jsx new file mode 100644 index 0000000..6619019 --- /dev/null +++ b/src/components/text-field/dropdown-input/dropdown-option.jsx @@ -0,0 +1,20 @@ +import styled from "styled-components"; +import Colors from "../../color/colors"; + +const DropdownOption = styled.div` + width: calc(100% - 2px); + border: none; + background: none; + padding: 12px 16px; + font-size: 16px; + font-weight: 400; + line-height: 26px; + color: ${Colors.gray(900)}; + cursor: pointer; + + &:hover { + background-color: ${Colors.gray(100)}; + } +`; + +export default DropdownOption; diff --git a/src/components/text-field/dropdown-input/dropdown-provider.jsx b/src/components/text-field/dropdown-input/dropdown-provider.jsx new file mode 100644 index 0000000..f74b577 --- /dev/null +++ b/src/components/text-field/dropdown-input/dropdown-provider.jsx @@ -0,0 +1,10 @@ +import { useState } from "react"; +import DropdownContext from "./dropdown-context"; + +function DropdownProvider({ children }) { + const [dropdownState, setDropdownState] = useState({}); + const value = { dropdownState, setDropdownState }; + return {children}; +} + +export default DropdownProvider; diff --git a/src/components/text-field/dropdown-input/dropdown.jsx b/src/components/text-field/dropdown-input/dropdown.jsx new file mode 100644 index 0000000..188df8a --- /dev/null +++ b/src/components/text-field/dropdown-input/dropdown.jsx @@ -0,0 +1,66 @@ +import { createPortal } from "react-dom"; +import styled from "styled-components"; +import Colors from "../../color/colors"; + +const BACKDROP_CLASS_NAME = "dropdown-backdrop"; + +const DropdownContainer = styled.div` + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 111; + + & > *:not(.${BACKDROP_CLASS_NAME}) { + z-index: 114; + } +`; + +const DropdownBackdrop = styled(DropdownContainer)` + z-index: 112; + position: fixed; +`; + +const DropdownContent = styled(DropdownContainer)` + z-index: 113; + position: relative; + height: 100%; +`; + +const StyledDropdown = styled.div` + background-color: white; + box-shadow: 0 0 0 1px ${Colors.gray(300)} inset, + 0 2px 12px 0 rgba(0, 0, 0, 0.08); + border-radius: 8px; + display: flex; + flex-direction: column; + align-items: center; + padding: 10px 0; + position: absolute; + top: ${({ $origin }) => $origin.y}px; + left: ${({ $origin }) => $origin.x}px; + width: ${({ $size }) => $size.width}px; +`; + +function Dropdown({ children, origin, size, onClose }) { + const DropdownPortal = ({ children }) => { + return createPortal(children, document.getElementById("dropdown")); + }; + + return ( + + + + + + {children} + + + + + + ); +} + +export default Dropdown; diff --git a/src/components/text-field/text-field.jsx b/src/components/text-field/text-field.jsx index 831214c..c97832d 100644 --- a/src/components/text-field/text-field.jsx +++ b/src/components/text-field/text-field.jsx @@ -1,8 +1,8 @@ import styled from "styled-components"; import Colors from "../color/colors"; -import DropdownInput from "./dropdown-input"; +import DropdownInput from "./dropdown-input/dropdown-input"; import TEXT_FIELD_TYPE from "./text-field-type"; -import TextInput from "./text-input"; +import TextInput from "./text-input/text-input"; const StyledInputTextField = styled.div` display: flex; @@ -18,13 +18,13 @@ const ErrorMessage = styled.p` color: ${Colors.error}; `; -function InputTextField({ type, error, ...props }) { +function InputTextField({ type, error, dropdownId, ...props }) { return ( {type === TEXT_FIELD_TYPE.input ? ( ) : ( - + )} {error && {error}} diff --git a/src/components/text-field/text-input.jsx b/src/components/text-field/text-input/text-input.jsx similarity index 96% rename from src/components/text-field/text-input.jsx rename to src/components/text-field/text-input/text-input.jsx index be94af4..5687c6e 100644 --- a/src/components/text-field/text-input.jsx +++ b/src/components/text-field/text-input/text-input.jsx @@ -1,5 +1,5 @@ import styled from "styled-components"; -import INPUT_STYLES from "./input-styles"; +import INPUT_STYLES from "../input-styles"; const StyledTextInput = styled.input` background-color: ${INPUT_STYLES.backgroundColor.normal}; diff --git a/src/hooks/dropdown/use-dropdown.jsx b/src/hooks/dropdown/use-dropdown.jsx new file mode 100644 index 0000000..cdc06af --- /dev/null +++ b/src/hooks/dropdown/use-dropdown.jsx @@ -0,0 +1,54 @@ +import { useContext, useRef, useState } from "react"; +import DropdownContext from "../../components/text-field/dropdown-input/dropdown-context"; + +function makeRect({ x, y, width } = { x: 0, y: 0, width: 0 }) { + return { + origin: { x, y }, + size: { width }, + }; +} + +function calculateDropdownRect(target) { + if (!target) { + return makeRect(); + } + + const targetRect = target.getBoundingClientRect(); + const dropdownRect = makeRect({ + x: targetRect.left, + y: targetRect.bottom + 8, + width: targetRect.width, + }); + + return dropdownRect; +} + +function useDropdown({ id, type }) { + const { dropdownState, setDropdownState } = useContext(DropdownContext); + const [dropdownRect, setDropdownRect] = useState(); + + const targetRef = useRef(); + + const key = `${type}_${id}`; + const showsDropdown = dropdownState[key] ?? false; + + const setShowsDropdown = (shows) => { + setDropdownState((prev) => ({ ...prev, [key]: shows })); + }; + + const handleTargetClick = (shows) => { + const rect = calculateDropdownRect(targetRef.current); + setShowsDropdown(shows); + setDropdownRect(rect); + }; + + return { + targetRef, + dropdownRect, + showsDropdown, + setShowsDropdown, + handleTargetClick, + }; +} + +export { useDropdown }; diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index 0300ce8..0d34eee 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -134,6 +134,7 @@ function TestPage() {
Date: Mon, 11 Aug 2025 20:58:14 +0900 Subject: [PATCH 037/253] =?UTF-8?q?[#12]=20=EB=AD=90=EC=95=BC=20=EB=8B=A4?= =?UTF-8?q?=EC=8B=9C=20=EA=B3=B5=ED=86=B5=20api=ED=8F=B4=EB=8D=94=20src?= =?UTF-8?q?=EC=95=84=EB=9E=98=EC=97=90=20=EB=A7=8C=EB=93=A4=EC=96=B4?= =?UTF-8?q?=EC=84=9C=20=EA=B7=B8=EC=95=88=EC=97=90=20axios=EC=9A=A9=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=83=9D=EC=84=B1=ED=95=B4=EC=84=9C=20?= =?UTF-8?q?=EC=9D=B8=EC=8A=A4=ED=84=B4=EC=8A=A4=ED=99=94=20=EC=8B=9C?= =?UTF-8?q?=EC=BC=B0=EC=8A=B5=EB=8B=88=EB=8B=A4.=20pages=EC=95=84=EB=9E=98?= =?UTF-8?q?=EC=97=90=20MessageList.jsx=ED=8C=8C=EC=9D=BC=20=EC=95=88?= =?UTF-8?q?=EC=97=90=20=EC=98=88=EC=8B=9C=EC=9A=A9=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=A0=81=EC=96=B4=EB=86=93=EC=95=98=EC=8A=B5=EB=8B=88=EB=8B=A4?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 280 ++++++++++++++++++++++++++++++++++++++ package.json | 1 + src/api/axiosInstance.js | 9 ++ src/app.jsx | 6 +- src/pages/MessageList.jsx | 35 +++++ src/pages/test-page.jsx | 1 + 6 files changed, 330 insertions(+), 2 deletions(-) create mode 100644 src/api/axiosInstance.js create mode 100644 src/pages/MessageList.jsx diff --git a/package-lock.json b/package-lock.json index 6237549..74a5db7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "rolling", "version": "0.0.0", "dependencies": { + "axios": "^1.11.0", "react": "^19.1.1", "react-dom": "^19.1.1", "styled-components": "^6.1.19" @@ -1498,6 +1499,23 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz", + "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1549,6 +1567,19 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1626,6 +1657,18 @@ "dev": true, "license": "MIT" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1706,6 +1749,29 @@ "dev": true, "license": "MIT" }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/electron-to-chromium": { "version": "1.5.199", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.199.tgz", @@ -1713,6 +1779,51 @@ "dev": true, "license": "ISC" }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/esbuild": { "version": "0.25.8", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.8.tgz", @@ -2043,6 +2154,42 @@ "dev": true, "license": "ISC" }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -2058,6 +2205,15 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -2068,6 +2224,43 @@ "node": ">=6.9.0" } }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -2094,6 +2287,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2104,6 +2309,45 @@ "node": ">=8" } }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -2295,6 +2539,36 @@ "yallist": "^3.0.2" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -2494,6 +2768,12 @@ "node": ">= 0.8.0" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", diff --git a/package.json b/package.json index c3553fb..812f44f 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "preview": "vite preview" }, "dependencies": { + "axios": "^1.11.0", "react": "^19.1.1", "react-dom": "^19.1.1", "styled-components": "^6.1.19" diff --git a/src/api/axiosInstance.js b/src/api/axiosInstance.js new file mode 100644 index 0000000..afee3af --- /dev/null +++ b/src/api/axiosInstance.js @@ -0,0 +1,9 @@ +import axios from 'axios'; + +const axiosInstance = axios.create({ + baseURL: 'https://rolling-api.vercel.app/', + timeout: 5000, + headers: { 'Content-Type': 'application/json' }, +}); + +export default axiosInstance; \ No newline at end of file diff --git a/src/app.jsx b/src/app.jsx index c2cf85c..4a5c1fb 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -1,7 +1,9 @@ -import TestPage from "./pages/test-page"; +// import TestPage from "./pages/test-page"; +import MessagePage from "./pages/MessageList"; function App() { - return ; + // return ; + return ; } export default App; diff --git a/src/pages/MessageList.jsx b/src/pages/MessageList.jsx new file mode 100644 index 0000000..4f4b32e --- /dev/null +++ b/src/pages/MessageList.jsx @@ -0,0 +1,35 @@ +import ArrowButton from "../components/button/arrow-button"; +import ARROW_BUTTON_DIRECTION from "../components/button/arrow-button-direction"; +import { +OutlinedButton, +PrimaryButton, +SecondaryButton, +} from "../components/button/button"; +import BUTTON_SIZE from "../components/button/button-size"; +import ToggleButton from "../components/button/toggle-button"; + +import React, { useEffect, useState } from "react"; +import axiosInstance from '../api/axiosInstance'; + +function StartTest() { + const [imageUrl, setImageUrl] = useState(null); + + /* axios 사용용 예시코드 */ + useEffect(() => { + axiosInstance.get('/background-images/') + .then(res => { + if (res.data && res.data.imageUrls && res.data.imageUrls.length > 0) { + setImageUrl(res.data.imageUrls[0]); + } + }) + .catch(console.error); + }, []); + + return ( +
+ {imageUrl ? (background) : (

이미지를 불러오는 중입니다...

)} +
+ ); +} + +export default StartTest; diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index 705a521..d17b7f1 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -22,6 +22,7 @@ function TestPage() { margin: 16, }} > +

🤯

From c7987d90837dc5f70a77d84d51bd2bbc0a970136 Mon Sep 17 00:00:00 2001 From: luli Date: Tue, 12 Aug 2025 12:28:17 +0900 Subject: [PATCH 038/253] =?UTF-8?q?=ED=8C=8C=EC=9D=BC=EB=AA=85=20kebab-cas?= =?UTF-8?q?e=EB=A1=9C=20=EC=88=98=EC=A0=95,=20prettier=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/axios-instance.js | 9 +++++++++ src/api/axiosInstance.js | 9 --------- src/pages/MessageList.jsx | 35 --------------------------------- src/pages/message-list.jsx | 40 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 44 deletions(-) create mode 100644 src/api/axios-instance.js delete mode 100644 src/api/axiosInstance.js delete mode 100644 src/pages/MessageList.jsx create mode 100644 src/pages/message-list.jsx diff --git a/src/api/axios-instance.js b/src/api/axios-instance.js new file mode 100644 index 0000000..217889d --- /dev/null +++ b/src/api/axios-instance.js @@ -0,0 +1,9 @@ +import axios from "axios"; + +const axiosInstance = axios.create({ + baseURL: "https://rolling-api.vercel.app/", + timeout: 5000, + headers: { "Content-Type": "application/json" }, +}); + +export default axiosInstance; diff --git a/src/api/axiosInstance.js b/src/api/axiosInstance.js deleted file mode 100644 index afee3af..0000000 --- a/src/api/axiosInstance.js +++ /dev/null @@ -1,9 +0,0 @@ -import axios from 'axios'; - -const axiosInstance = axios.create({ - baseURL: 'https://rolling-api.vercel.app/', - timeout: 5000, - headers: { 'Content-Type': 'application/json' }, -}); - -export default axiosInstance; \ No newline at end of file diff --git a/src/pages/MessageList.jsx b/src/pages/MessageList.jsx deleted file mode 100644 index 4f4b32e..0000000 --- a/src/pages/MessageList.jsx +++ /dev/null @@ -1,35 +0,0 @@ -import ArrowButton from "../components/button/arrow-button"; -import ARROW_BUTTON_DIRECTION from "../components/button/arrow-button-direction"; -import { -OutlinedButton, -PrimaryButton, -SecondaryButton, -} from "../components/button/button"; -import BUTTON_SIZE from "../components/button/button-size"; -import ToggleButton from "../components/button/toggle-button"; - -import React, { useEffect, useState } from "react"; -import axiosInstance from '../api/axiosInstance'; - -function StartTest() { - const [imageUrl, setImageUrl] = useState(null); - - /* axios 사용용 예시코드 */ - useEffect(() => { - axiosInstance.get('/background-images/') - .then(res => { - if (res.data && res.data.imageUrls && res.data.imageUrls.length > 0) { - setImageUrl(res.data.imageUrls[0]); - } - }) - .catch(console.error); - }, []); - - return ( -
- {imageUrl ? (background) : (

이미지를 불러오는 중입니다...

)} -
- ); -} - -export default StartTest; diff --git a/src/pages/message-list.jsx b/src/pages/message-list.jsx new file mode 100644 index 0000000..006d869 --- /dev/null +++ b/src/pages/message-list.jsx @@ -0,0 +1,40 @@ +import ArrowButton from "../components/button/arrow-button"; +import ARROW_BUTTON_DIRECTION from "../components/button/arrow-button-direction"; +import { + OutlinedButton, + PrimaryButton, + SecondaryButton, +} from "../components/button/button"; +import BUTTON_SIZE from "../components/button/button-size"; +import ToggleButton from "../components/button/toggle-button"; + +import React, { useEffect, useState } from "react"; +import axiosInstance from "../api/axios-instance"; + +function ShowMessageList() { + const [imageUrl, setImageUrl] = useState(null); + + /* axios 사용용 예시코드 */ + useEffect(() => { + axiosInstance + .get("/background-images/") + .then((res) => { + if (res.data && res.data.imageUrls && res.data.imageUrls.length > 0) { + setImageUrl(res.data.imageUrls[0]); + } + }) + .catch(console.error); + }, []); + + return ( +
+ {imageUrl ? ( + background + ) : ( +

이미지를 불러오는 중입니다...

+ )} +
+ ); +} + +export default ShowMessageList; From 8ab9c996fcfd87787d54b005e48ec1462ac68b1b Mon Sep 17 00:00:00 2001 From: luli Date: Tue, 12 Aug 2025 15:09:31 +0900 Subject: [PATCH 039/253] =?UTF-8?q?#12:=20=ED=8C=8C=EC=9D=BC=EB=AA=85=20ke?= =?UTF-8?q?bab-case=EB=A1=9C=20=EC=88=98=EC=A0=95,=20prettier=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 그외에 제가 만든 페이지 코드가 좀 섞여있긴한데 완성된게 아니라서 신경안쓰셔도됩니다 😢 --- src/app.jsx | 2 +- src/pages/message-list.jsx | 97 ++++++++++++++++++++++++++++++++++++++ src/pages/test-data.js | 19 ++++++++ src/pages/test-page.jsx | 1 - 4 files changed, 117 insertions(+), 2 deletions(-) create mode 100644 src/pages/test-data.js diff --git a/src/app.jsx b/src/app.jsx index 4a5c1fb..ee2bf95 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -1,5 +1,5 @@ // import TestPage from "./pages/test-page"; -import MessagePage from "./pages/MessageList"; +import MessagePage from "./pages/message-list"; function App() { // return ; diff --git a/src/pages/message-list.jsx b/src/pages/message-list.jsx index 006d869..a65e304 100644 --- a/src/pages/message-list.jsx +++ b/src/pages/message-list.jsx @@ -14,6 +14,103 @@ import axiosInstance from "../api/axios-instance"; function ShowMessageList() { const [imageUrl, setImageUrl] = useState(null); + // const cardConStyle = { + // border: "1px solid red", + // display: "grid", + // gridTemplateColumns: "275px 275px 275px 275px", + // gap: "20px", + // width: "fit-content", + + // position: "relative", // <-- 중요: 화살표를 absolute로 겹치게 하기 위해 + // overflow: "visible", // 부모가 overflow:hidden 이면 겹치지 않음 + // }; + + // const cardStyle = { + // width: "275px", + // height: "260px", + // border: "1px solid red", + // }; + + // const testStyle = { + // textAlign: "center", + // }; + + // const sectionStyle = { + // justifySelf: "center", + // }; + + // const buttonStyle = { + // marginTop: "64px", + // fontWeight: "400", + // padding: "14px 60px", + // }; + + // const htStyle = { + // textAlign: "left", + // }; + + // const rButton = { + // position: "absolute", + // right: -20, // 필요시 조정 + // top: "50%", + // transform: "translateY(-50%)", + // zIndex: 20, + // }; + + // const lButton = { + // position: "absolute", + // left: -20, // 필요시 조정 + // top: "50%", + // transform: "translateY(-50%)", + // zIndex: 20, + // }; + + // useEffect(() => { + // axiosInstance + // .get("/18-3/recipients/?limit=5&offset=20") + // .then((res) => { + // console.log(res.data); + // }) + // .catch(console.error); + // }, []); + + // return ( + //
+ // /* navi 들어갈 자리 */ + //
+ //
+ //

인기 롤링 페이퍼 🔥

+ //
+ //
+ //
+ //
+ //
+ //
+ // + //
+ //
+ //
+ //
+ //

최근에 만든 롤링 페이퍼 ⭐

+ //
+ //
+ //
+ //
+ //
+ //
+ // + //
+ //
+ //
+ //
+ // + //
+ // ); + /* axios 사용용 예시코드 */ useEffect(() => { axiosInstance diff --git a/src/pages/test-data.js b/src/pages/test-data.js new file mode 100644 index 0000000..7780d29 --- /dev/null +++ b/src/pages/test-data.js @@ -0,0 +1,19 @@ +const testData = { + count: 0, + next: null, + previous: "https://rolling-api.vercel.app/18-3/recipients/?limit=5&offset=15", + results: + [ Recipient: { + id: 1111, + team: '18-3', + name: '' + backgroundColor* BackgroundColor[...] + backgroundImageURL BackgroundImageURL[...] + createdAt CreatedAt[...] + messageCount Messagecount[...] + recentMessages Recentmessages[...] + reactionCount Reactioncount[...] + topReactions Topreactions[...] + } + ] +} \ No newline at end of file diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index d17b7f1..705a521 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -22,7 +22,6 @@ function TestPage() { margin: 16, }} > -

🤯

From 9c08080b658166a8861ed4b3b26e3057544160b0 Mon Sep 17 00:00:00 2001 From: luli Date: Tue, 12 Aug 2025 15:27:09 +0900 Subject: [PATCH 040/253] =?UTF-8?q?[#12]=20Axios=20=EC=9D=B8=EC=8A=A4?= =?UTF-8?q?=ED=84=B4=EC=8A=A4=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 공통 api폴더 src아래에 만들어서 그안에 axios용 파일 생성해서 인스턴스화 시켰습니다. pages아래에 MessageList.jsx파일 안에 예시용 코드 적어놓았습니다. --- src/api/axiosInstance.js | 9 +++++++++ src/pages/MessageList.jsx | 35 +++++++++++++++++++++++++++++++++++ src/pages/test-page.jsx | 1 + 3 files changed, 45 insertions(+) create mode 100644 src/api/axiosInstance.js create mode 100644 src/pages/MessageList.jsx diff --git a/src/api/axiosInstance.js b/src/api/axiosInstance.js new file mode 100644 index 0000000..afee3af --- /dev/null +++ b/src/api/axiosInstance.js @@ -0,0 +1,9 @@ +import axios from 'axios'; + +const axiosInstance = axios.create({ + baseURL: 'https://rolling-api.vercel.app/', + timeout: 5000, + headers: { 'Content-Type': 'application/json' }, +}); + +export default axiosInstance; \ No newline at end of file diff --git a/src/pages/MessageList.jsx b/src/pages/MessageList.jsx new file mode 100644 index 0000000..4f4b32e --- /dev/null +++ b/src/pages/MessageList.jsx @@ -0,0 +1,35 @@ +import ArrowButton from "../components/button/arrow-button"; +import ARROW_BUTTON_DIRECTION from "../components/button/arrow-button-direction"; +import { +OutlinedButton, +PrimaryButton, +SecondaryButton, +} from "../components/button/button"; +import BUTTON_SIZE from "../components/button/button-size"; +import ToggleButton from "../components/button/toggle-button"; + +import React, { useEffect, useState } from "react"; +import axiosInstance from '../api/axiosInstance'; + +function StartTest() { + const [imageUrl, setImageUrl] = useState(null); + + /* axios 사용용 예시코드 */ + useEffect(() => { + axiosInstance.get('/background-images/') + .then(res => { + if (res.data && res.data.imageUrls && res.data.imageUrls.length > 0) { + setImageUrl(res.data.imageUrls[0]); + } + }) + .catch(console.error); + }, []); + + return ( +
+ {imageUrl ? (background) : (

이미지를 불러오는 중입니다...

)} +
+ ); +} + +export default StartTest; diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index 705a521..d17b7f1 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -22,6 +22,7 @@ function TestPage() { margin: 16, }} > +

🤯

From 3e28d20be8bc64bb44ba529bf078a507dc963acb Mon Sep 17 00:00:00 2001 From: luli Date: Tue, 12 Aug 2025 16:10:23 +0900 Subject: [PATCH 041/253] =?UTF-8?q?=EC=A4=91=EB=B3=B5=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit message-list.jsx, axios-instance.js 파일이 중복되어있어서 삭제했습니다 --- src/api/axiosInstance.js | 9 -- src/pages/MessageList.jsx | 35 ------ src/pages/message-list.jsx | 218 ++++++++++++++++++------------------- src/pages/test-data.js | 19 ---- 4 files changed, 109 insertions(+), 172 deletions(-) delete mode 100644 src/api/axiosInstance.js delete mode 100644 src/pages/MessageList.jsx delete mode 100644 src/pages/test-data.js diff --git a/src/api/axiosInstance.js b/src/api/axiosInstance.js deleted file mode 100644 index afee3af..0000000 --- a/src/api/axiosInstance.js +++ /dev/null @@ -1,9 +0,0 @@ -import axios from 'axios'; - -const axiosInstance = axios.create({ - baseURL: 'https://rolling-api.vercel.app/', - timeout: 5000, - headers: { 'Content-Type': 'application/json' }, -}); - -export default axiosInstance; \ No newline at end of file diff --git a/src/pages/MessageList.jsx b/src/pages/MessageList.jsx deleted file mode 100644 index 4f4b32e..0000000 --- a/src/pages/MessageList.jsx +++ /dev/null @@ -1,35 +0,0 @@ -import ArrowButton from "../components/button/arrow-button"; -import ARROW_BUTTON_DIRECTION from "../components/button/arrow-button-direction"; -import { -OutlinedButton, -PrimaryButton, -SecondaryButton, -} from "../components/button/button"; -import BUTTON_SIZE from "../components/button/button-size"; -import ToggleButton from "../components/button/toggle-button"; - -import React, { useEffect, useState } from "react"; -import axiosInstance from '../api/axiosInstance'; - -function StartTest() { - const [imageUrl, setImageUrl] = useState(null); - - /* axios 사용용 예시코드 */ - useEffect(() => { - axiosInstance.get('/background-images/') - .then(res => { - if (res.data && res.data.imageUrls && res.data.imageUrls.length > 0) { - setImageUrl(res.data.imageUrls[0]); - } - }) - .catch(console.error); - }, []); - - return ( -
- {imageUrl ? (background) : (

이미지를 불러오는 중입니다...

)} -
- ); -} - -export default StartTest; diff --git a/src/pages/message-list.jsx b/src/pages/message-list.jsx index a65e304..6cc97b3 100644 --- a/src/pages/message-list.jsx +++ b/src/pages/message-list.jsx @@ -12,126 +12,126 @@ import React, { useEffect, useState } from "react"; import axiosInstance from "../api/axios-instance"; function ShowMessageList() { - const [imageUrl, setImageUrl] = useState(null); - - // const cardConStyle = { - // border: "1px solid red", - // display: "grid", - // gridTemplateColumns: "275px 275px 275px 275px", - // gap: "20px", - // width: "fit-content", - - // position: "relative", // <-- 중요: 화살표를 absolute로 겹치게 하기 위해 - // overflow: "visible", // 부모가 overflow:hidden 이면 겹치지 않음 - // }; - - // const cardStyle = { - // width: "275px", - // height: "260px", - // border: "1px solid red", - // }; - - // const testStyle = { - // textAlign: "center", - // }; - - // const sectionStyle = { - // justifySelf: "center", - // }; - - // const buttonStyle = { - // marginTop: "64px", - // fontWeight: "400", - // padding: "14px 60px", - // }; - - // const htStyle = { - // textAlign: "left", - // }; - - // const rButton = { - // position: "absolute", - // right: -20, // 필요시 조정 - // top: "50%", - // transform: "translateY(-50%)", - // zIndex: 20, - // }; - - // const lButton = { - // position: "absolute", - // left: -20, // 필요시 조정 - // top: "50%", - // transform: "translateY(-50%)", - // zIndex: 20, - // }; + // const [imageUrl, setImageUrl] = useState(null); + + const cardConStyle = { + border: "1px solid red", + display: "grid", + gridTemplateColumns: "275px 275px 275px 275px", + gap: "20px", + width: "fit-content", + + position: "relative", + overflow: "visible", + }; + + const cardStyle = { + width: "275px", + height: "260px", + border: "1px solid red", + }; + + const testStyle = { + textAlign: "center", + }; + + const sectionStyle = { + justifySelf: "center", + }; + + const buttonStyle = { + marginTop: "64px", + fontWeight: "400", + padding: "14px 60px", + }; + + const htStyle = { + textAlign: "left", + }; + + const rButton = { + position: "absolute", + right: -20, // 필요시 조정 + top: "50%", + transform: "translateY(-50%)", + zIndex: 20, + }; + + const lButton = { + position: "absolute", + left: -20, // 필요시 조정 + top: "50%", + transform: "translateY(-50%)", + zIndex: 20, + }; - // useEffect(() => { - // axiosInstance - // .get("/18-3/recipients/?limit=5&offset=20") - // .then((res) => { - // console.log(res.data); - // }) - // .catch(console.error); - // }, []); - - // return ( - //
- // /* navi 들어갈 자리 */ - //
- //
- //

인기 롤링 페이퍼 🔥

- //
- //
- //
- //
- //
- //
- // - //
- //
- //
- //
- //

최근에 만든 롤링 페이퍼 ⭐

- //
- //
- //
- //
- //
- //
- // - //
- //
- //
- //
- // - //
- // ); - - /* axios 사용용 예시코드 */ useEffect(() => { axiosInstance - .get("/background-images/") + .get("/18-3/recipients/?limit=5&offset=20") .then((res) => { - if (res.data && res.data.imageUrls && res.data.imageUrls.length > 0) { - setImageUrl(res.data.imageUrls[0]); - } + console.log(res.data); }) .catch(console.error); }, []); return ( -
- {imageUrl ? ( - background - ) : ( -

이미지를 불러오는 중입니다...

- )} +
+ /* navi 들어갈 자리 */ +
+
+

인기 롤링 페이퍼 🔥

+
+
+
+
+
+
+ +
+
+
+
+

최근에 만든 롤링 페이퍼 ⭐

+
+
+
+
+
+
+ +
+
+
+
+
); + + /* axios 사용 예시코드 */ + // useEffect(() => { + // axiosInstance + // .get("/background-images/") + // .then((res) => { + // if (res.data && res.data.imageUrls && res.data.imageUrls.length > 0) { + // setImageUrl(res.data.imageUrls[0]); + // } + // }) + // .catch(console.error); + // }, []); + + // return ( + //
+ // {imageUrl ? ( + // background + // ) : ( + //

이미지를 불러오는 중입니다...

+ // )} + //
+ // ); } export default ShowMessageList; diff --git a/src/pages/test-data.js b/src/pages/test-data.js deleted file mode 100644 index 7780d29..0000000 --- a/src/pages/test-data.js +++ /dev/null @@ -1,19 +0,0 @@ -const testData = { - count: 0, - next: null, - previous: "https://rolling-api.vercel.app/18-3/recipients/?limit=5&offset=15", - results: - [ Recipient: { - id: 1111, - team: '18-3', - name: '' - backgroundColor* BackgroundColor[...] - backgroundImageURL BackgroundImageURL[...] - createdAt CreatedAt[...] - messageCount Messagecount[...] - recentMessages Recentmessages[...] - reactionCount Reactioncount[...] - topReactions Topreactions[...] - } - ] -} \ No newline at end of file From c69390fb5882c70a1ccfc79f0ea2f908f6238a85 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 12 Aug 2025 16:35:43 +0900 Subject: [PATCH 042/253] =?UTF-8?q?fix=20[]=20React=20router=20package=20?= =?UTF-8?q?=EC=84=A4=EC=B9=98=20/=20TestPage=EC=99=80=20MessagePage=20rout?= =?UTF-8?q?e=20=EB=B6=84=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #12 작업내용 merge 및 conflict 수정 --- package-lock.json | 318 +++++++++++++++++++++++++++++++++++++ package.json | 2 + src/api/axios-instance.js | 9 ++ src/app.jsx | 8 +- src/pages/message-list.jsx | 137 ++++++++++++++++ src/pages/test-page.jsx | 1 + 6 files changed, 474 insertions(+), 1 deletion(-) create mode 100644 src/api/axios-instance.js create mode 100644 src/pages/message-list.jsx diff --git a/package-lock.json b/package-lock.json index 6237549..a13efef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,8 +8,10 @@ "name": "rolling", "version": "0.0.0", "dependencies": { + "axios": "^1.11.0", "react": "^19.1.1", "react-dom": "^19.1.1", + "react-router": "^7.8.0", "styled-components": "^6.1.19" }, "devDependencies": { @@ -1498,6 +1500,23 @@ "dev": true, "license": "Python-2.0" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz", + "integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1549,6 +1568,19 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1626,6 +1658,18 @@ "dev": true, "license": "MIT" }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1640,6 +1684,15 @@ "dev": true, "license": "MIT" }, + "node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -1706,6 +1759,29 @@ "dev": true, "license": "MIT" }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/electron-to-chromium": { "version": "1.5.199", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.199.tgz", @@ -1713,6 +1789,51 @@ "dev": true, "license": "ISC" }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/esbuild": { "version": "0.25.8", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.8.tgz", @@ -2043,6 +2164,42 @@ "dev": true, "license": "ISC" }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -2058,6 +2215,15 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -2068,6 +2234,43 @@ "node": ">=6.9.0" } }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -2094,6 +2297,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -2104,6 +2319,45 @@ "node": ">=8" } }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -2295,6 +2549,36 @@ "yallist": "^3.0.2" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -2494,6 +2778,12 @@ "node": ">= 0.8.0" } }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -2535,6 +2825,28 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.8.0.tgz", + "integrity": "sha512-r15M3+LHKgM4SOapNmsH3smAizWds1vJ0Z9C4mWaKnT9/wD7+d/0jYcj6LmOvonkrO4Rgdyp4KQ/29gWN2i1eg==", + "license": "MIT", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -2601,6 +2913,12 @@ "semver": "bin/semver.js" } }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "license": "MIT" + }, "node_modules/shallowequal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", diff --git a/package.json b/package.json index c3553fb..72906b1 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,10 @@ "preview": "vite preview" }, "dependencies": { + "axios": "^1.11.0", "react": "^19.1.1", "react-dom": "^19.1.1", + "react-router": "^7.8.0", "styled-components": "^6.1.19" }, "devDependencies": { diff --git a/src/api/axios-instance.js b/src/api/axios-instance.js new file mode 100644 index 0000000..217889d --- /dev/null +++ b/src/api/axios-instance.js @@ -0,0 +1,9 @@ +import axios from "axios"; + +const axiosInstance = axios.create({ + baseURL: "https://rolling-api.vercel.app/", + timeout: 5000, + headers: { "Content-Type": "application/json" }, +}); + +export default axiosInstance; diff --git a/src/app.jsx b/src/app.jsx index 81ae363..745c6e7 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -1,10 +1,16 @@ +import { BrowserRouter, Route, Routes } from "react-router"; import DropdownProvider from "./components/text-field/dropdown-input/dropdown-provider"; import TestPage from "./pages/test-page"; function App() { return ( - + + + } /> + } /> + + ); } diff --git a/src/pages/message-list.jsx b/src/pages/message-list.jsx new file mode 100644 index 0000000..6cc97b3 --- /dev/null +++ b/src/pages/message-list.jsx @@ -0,0 +1,137 @@ +import ArrowButton from "../components/button/arrow-button"; +import ARROW_BUTTON_DIRECTION from "../components/button/arrow-button-direction"; +import { + OutlinedButton, + PrimaryButton, + SecondaryButton, +} from "../components/button/button"; +import BUTTON_SIZE from "../components/button/button-size"; +import ToggleButton from "../components/button/toggle-button"; + +import React, { useEffect, useState } from "react"; +import axiosInstance from "../api/axios-instance"; + +function ShowMessageList() { + // const [imageUrl, setImageUrl] = useState(null); + + const cardConStyle = { + border: "1px solid red", + display: "grid", + gridTemplateColumns: "275px 275px 275px 275px", + gap: "20px", + width: "fit-content", + + position: "relative", + overflow: "visible", + }; + + const cardStyle = { + width: "275px", + height: "260px", + border: "1px solid red", + }; + + const testStyle = { + textAlign: "center", + }; + + const sectionStyle = { + justifySelf: "center", + }; + + const buttonStyle = { + marginTop: "64px", + fontWeight: "400", + padding: "14px 60px", + }; + + const htStyle = { + textAlign: "left", + }; + + const rButton = { + position: "absolute", + right: -20, // 필요시 조정 + top: "50%", + transform: "translateY(-50%)", + zIndex: 20, + }; + + const lButton = { + position: "absolute", + left: -20, // 필요시 조정 + top: "50%", + transform: "translateY(-50%)", + zIndex: 20, + }; + + useEffect(() => { + axiosInstance + .get("/18-3/recipients/?limit=5&offset=20") + .then((res) => { + console.log(res.data); + }) + .catch(console.error); + }, []); + + return ( +
+ /* navi 들어갈 자리 */ +
+
+

인기 롤링 페이퍼 🔥

+
+
+
+
+
+
+ +
+
+
+
+

최근에 만든 롤링 페이퍼 ⭐

+
+
+
+
+
+
+ +
+
+
+
+ +
+ ); + + /* axios 사용 예시코드 */ + // useEffect(() => { + // axiosInstance + // .get("/background-images/") + // .then((res) => { + // if (res.data && res.data.imageUrls && res.data.imageUrls.length > 0) { + // setImageUrl(res.data.imageUrls[0]); + // } + // }) + // .catch(console.error); + // }, []); + + // return ( + //
+ // {imageUrl ? ( + // background + // ) : ( + //

이미지를 불러오는 중입니다...

+ // )} + //
+ // ); +} + +export default ShowMessageList; diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index 0d34eee..2ae1ed2 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -36,6 +36,7 @@ function TestPage() { margin: 16, }} > +

🤯

From e0745c4767800f8b4536e4a89d1c71a0eccf37b5 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 12 Aug 2025 16:37:19 +0900 Subject: [PATCH 043/253] =?UTF-8?q?fix=20[]=20Missing=20import=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app.jsx b/src/app.jsx index 745c6e7..7fb23d8 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -1,5 +1,6 @@ import { BrowserRouter, Route, Routes } from "react-router"; import DropdownProvider from "./components/text-field/dropdown-input/dropdown-provider"; +import MessagePage from "./pages/message-list"; import TestPage from "./pages/test-page"; function App() { From 586ea8167673fac7050e2557a01fa632fc7b7563 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Mon, 11 Aug 2025 15:53:19 +0900 Subject: [PATCH 044/253] =?UTF-8?q?feat=20[#8]=20`Toast`=20component=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/ic-check-circle-green.svg | 3 ++ src/assets/ic-xmark.svg | 3 ++ src/components/toast/toast.jsx | 50 ++++++++++++++++++++++++++++ src/pages/test-page.jsx | 4 +++ 4 files changed, 60 insertions(+) create mode 100644 src/assets/ic-check-circle-green.svg create mode 100644 src/assets/ic-xmark.svg create mode 100644 src/components/toast/toast.jsx diff --git a/src/assets/ic-check-circle-green.svg b/src/assets/ic-check-circle-green.svg new file mode 100644 index 0000000..18be8ec --- /dev/null +++ b/src/assets/ic-check-circle-green.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/ic-xmark.svg b/src/assets/ic-xmark.svg new file mode 100644 index 0000000..c490a80 --- /dev/null +++ b/src/assets/ic-xmark.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/toast/toast.jsx b/src/components/toast/toast.jsx new file mode 100644 index 0000000..dadd5c3 --- /dev/null +++ b/src/components/toast/toast.jsx @@ -0,0 +1,50 @@ +import styled from "styled-components"; +import checkImg from "../../assets/ic-check-circle-green.svg"; +import closeImg from "../../assets/ic-xmark.svg"; + +const StyledToast = styled.div` + background-color: rgba(0, 0, 0, 0.8); + border-radius: 8px; + min-width: 524px; + height: 64px; + padding: 0 30px; + display: flex; + align-items: center; + gap: 12px; + + font-size: 16px; + font-weight: 400; + line-height: 26px; + color: white; + + p { + margin: 0; + flex-grow: 1; + } +`; + +const Icon = styled.div` + width: 24px; + height: 24px; + + img { + width: 100%; + height: 100%; + } +`; + +function Toast({ message }) { + return ( + + + 확인 + +

{message}

+ + 닫기 + +
+ ); +} + +export default Toast; diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index 2ae1ed2..39fcdbf 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -14,6 +14,7 @@ import BUTTON_SIZE from "../components/button/button-size"; import ToggleButton from "../components/button/toggle-button"; import TextField from "../components/text-field/text-field"; import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; +import Toast from "../components/toast/toast"; function TestPage() { const [option1, setOption1] = useState(); @@ -159,6 +160,9 @@ function TestPage() { onSelect={handleDropdownSelect2} />
+
+ +
); } From 7f7d3db9929aa127fae6300c37924afc1a7f9af9 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Mon, 11 Aug 2025 16:31:36 +0900 Subject: [PATCH 045/253] =?UTF-8?q?feat=20[#8]=20`Toast`=EB=A5=BC=20?= =?UTF-8?q?=EC=9D=BC=EC=A0=95=20=EC=8B=9C=EA=B0=84=20=EB=B3=B4=EC=97=AC?= =?UTF-8?q?=EC=A3=BC=EA=B3=A0=20=EC=A0=9C=EA=B1=B0=ED=95=98=EB=8A=94=20`us?= =?UTF-8?q?eToast`=20custom=20hook=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/toast/toast.jsx | 18 +++++++++++++++++- src/components/toast/useToast.jsx | 21 +++++++++++++++++++++ src/pages/test-page.jsx | 17 +++++++++++++++-- 3 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 src/components/toast/useToast.jsx diff --git a/src/components/toast/toast.jsx b/src/components/toast/toast.jsx index dadd5c3..d427e5f 100644 --- a/src/components/toast/toast.jsx +++ b/src/components/toast/toast.jsx @@ -11,16 +11,32 @@ const StyledToast = styled.div` display: flex; align-items: center; gap: 12px; - font-size: 16px; font-weight: 400; line-height: 26px; color: white; + white-space: nowrap; + position: fixed; + left: 50%; + bottom: 70px; + transform: translateX(-50%); p { margin: 0; flex-grow: 1; } + + @media (max-width: 1199px) { + bottom: 50px; + } + + @media (max-width: 767px) { + min-width: 0; + transform: none; + left: 20px; + right: 20px; + bottom: 88px; + } `; const Icon = styled.div` diff --git a/src/components/toast/useToast.jsx b/src/components/toast/useToast.jsx new file mode 100644 index 0000000..8b461b6 --- /dev/null +++ b/src/components/toast/useToast.jsx @@ -0,0 +1,21 @@ +import { useEffect, useState } from "react"; + +function useToast(timeout = 2500) { + const [showsToast, setShowsToast] = useState(false); + + useEffect(() => { + if (!showsToast) return; + + const id = setTimeout(() => { + setShowsToast(false); + }, timeout); + + return () => { + clearTimeout(id); + }; + }, [showsToast, setShowsToast, timeout]); + + return { showsToast, setShowsToast }; +} + +export { useToast }; diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index 39fcdbf..29cfa5e 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -15,11 +15,14 @@ import ToggleButton from "../components/button/toggle-button"; import TextField from "../components/text-field/text-field"; import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; import Toast from "../components/toast/toast"; +import { useToast } from "../components/toast/useToast"; function TestPage() { + /* Dropdown type TextField */ const [option1, setOption1] = useState(); const [option2, setOption2] = useState(); const [dropdown2Error, setDropdown2Error] = useState("Error Message"); + const handleDropdownSelect1 = (option) => { setOption1(option); }; @@ -28,6 +31,11 @@ function TestPage() { setDropdown2Error(null); }; + /* Toast */ + const { showsToast, setShowsToast } = useToast(); + + const handleToastClick = () => setShowsToast(true); + return (
-
- +
+ + {showsToast && }
); From 719e73d183169ea55ae43cc702cce30b894316b2 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Mon, 11 Aug 2025 16:35:25 +0900 Subject: [PATCH 046/253] =?UTF-8?q?feat=20[#8]=20=EB=8B=AB=EA=B8=B0=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=EC=9C=BC=EB=A1=9C=20`Toast`=EB=A5=BC=20?= =?UTF-8?q?=EB=8B=AB=EC=9D=84=20=EC=88=98=20=EC=9E=88=EA=B2=8C=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/toast/toast.jsx | 13 ++++++++++--- src/pages/test-page.jsx | 8 +++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/components/toast/toast.jsx b/src/components/toast/toast.jsx index d427e5f..e24c6e6 100644 --- a/src/components/toast/toast.jsx +++ b/src/components/toast/toast.jsx @@ -49,16 +49,23 @@ const Icon = styled.div` } `; -function Toast({ message }) { +const IconButton = styled(Icon)` + background: none; + border: none; + padding: 0; + cursor: pointer; +`; + +function Toast({ message, onDismiss }) { return ( 확인

{message}

- + 닫기 - +
); } diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index 29cfa5e..96651ea 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -35,6 +35,7 @@ function TestPage() { const { showsToast, setShowsToast } = useToast(); const handleToastClick = () => setShowsToast(true); + const handleToastDismiss = () => setShowsToast(false); return (
- {showsToast && } + {showsToast && ( + + )}
); From a59fa0598abe9c108dcec2f20631bb7204657d50 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 12 Aug 2025 19:58:05 +0900 Subject: [PATCH 047/253] =?UTF-8?q?refactor=20[]=20`useDropdown`=EC=9D=84?= =?UTF-8?q?=20`hooks`=20=EC=95=84=EB=9E=98=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/text-field/dropdown-input/dropdown-input.jsx | 2 +- src/hooks/{dropdown => }/use-dropdown.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/hooks/{dropdown => }/use-dropdown.jsx (92%) diff --git a/src/components/text-field/dropdown-input/dropdown-input.jsx b/src/components/text-field/dropdown-input/dropdown-input.jsx index 09c937b..5524bde 100644 --- a/src/components/text-field/dropdown-input/dropdown-input.jsx +++ b/src/components/text-field/dropdown-input/dropdown-input.jsx @@ -1,7 +1,7 @@ import styled from "styled-components"; import arrowDownImg from "../../../assets/ic-chevron-down.svg"; import arrowUpImg from "../../../assets/ic-chevron-up.svg"; -import { useDropdown } from "../../../hooks/dropdown/use-dropdown"; +import { useDropdown } from "../../../hooks/use-dropdown"; import INPUT_STYLES from "../input-styles"; import Dropdown from "./dropdown"; import DropdownOption from "./dropdown-option"; diff --git a/src/hooks/dropdown/use-dropdown.jsx b/src/hooks/use-dropdown.jsx similarity index 92% rename from src/hooks/dropdown/use-dropdown.jsx rename to src/hooks/use-dropdown.jsx index cdc06af..16f1601 100644 --- a/src/hooks/dropdown/use-dropdown.jsx +++ b/src/hooks/use-dropdown.jsx @@ -1,5 +1,5 @@ import { useContext, useRef, useState } from "react"; -import DropdownContext from "../../components/text-field/dropdown-input/dropdown-context"; +import DropdownContext from "../components/text-field/dropdown-input/dropdown-context"; function makeRect({ x, y, width } = { x: 0, y: 0, width: 0 }) { return { From f9ae5e5ed15b81e7fa23c30f943f40418cbb9f11 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 12 Aug 2025 19:58:23 +0900 Subject: [PATCH 048/253] =?UTF-8?q?refactor=20[]=20`useToast`=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=9D=B4=EB=A6=84=EC=9D=84=20kebab=20case=EB=A1=9C?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/{components/toast/useToast.jsx => hooks/use-toast.jsx} | 0 src/pages/test-page.jsx | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/{components/toast/useToast.jsx => hooks/use-toast.jsx} (100%) diff --git a/src/components/toast/useToast.jsx b/src/hooks/use-toast.jsx similarity index 100% rename from src/components/toast/useToast.jsx rename to src/hooks/use-toast.jsx diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index 96651ea..f0ddc35 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -15,7 +15,7 @@ import ToggleButton from "../components/button/toggle-button"; import TextField from "../components/text-field/text-field"; import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; import Toast from "../components/toast/toast"; -import { useToast } from "../components/toast/useToast"; +import { useToast } from "../hooks/use-toast"; function TestPage() { /* Dropdown type TextField */ From 0c1df6dfe06c082aa23f3671836835e50552762f Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Mon, 11 Aug 2025 15:53:19 +0900 Subject: [PATCH 049/253] =?UTF-8?q?feat=20[#8]=20`Toast`=20component=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/ic-check-circle-green.svg | 3 ++ src/assets/ic-xmark.svg | 3 ++ src/components/toast/toast.jsx | 50 ++++++++++++++++++++++++++++ src/pages/test-page.jsx | 4 +++ 4 files changed, 60 insertions(+) create mode 100644 src/assets/ic-check-circle-green.svg create mode 100644 src/assets/ic-xmark.svg create mode 100644 src/components/toast/toast.jsx diff --git a/src/assets/ic-check-circle-green.svg b/src/assets/ic-check-circle-green.svg new file mode 100644 index 0000000..18be8ec --- /dev/null +++ b/src/assets/ic-check-circle-green.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/ic-xmark.svg b/src/assets/ic-xmark.svg new file mode 100644 index 0000000..c490a80 --- /dev/null +++ b/src/assets/ic-xmark.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/toast/toast.jsx b/src/components/toast/toast.jsx new file mode 100644 index 0000000..dadd5c3 --- /dev/null +++ b/src/components/toast/toast.jsx @@ -0,0 +1,50 @@ +import styled from "styled-components"; +import checkImg from "../../assets/ic-check-circle-green.svg"; +import closeImg from "../../assets/ic-xmark.svg"; + +const StyledToast = styled.div` + background-color: rgba(0, 0, 0, 0.8); + border-radius: 8px; + min-width: 524px; + height: 64px; + padding: 0 30px; + display: flex; + align-items: center; + gap: 12px; + + font-size: 16px; + font-weight: 400; + line-height: 26px; + color: white; + + p { + margin: 0; + flex-grow: 1; + } +`; + +const Icon = styled.div` + width: 24px; + height: 24px; + + img { + width: 100%; + height: 100%; + } +`; + +function Toast({ message }) { + return ( + + + 확인 + +

{message}

+ + 닫기 + +
+ ); +} + +export default Toast; diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index 2ae1ed2..39fcdbf 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -14,6 +14,7 @@ import BUTTON_SIZE from "../components/button/button-size"; import ToggleButton from "../components/button/toggle-button"; import TextField from "../components/text-field/text-field"; import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; +import Toast from "../components/toast/toast"; function TestPage() { const [option1, setOption1] = useState(); @@ -159,6 +160,9 @@ function TestPage() { onSelect={handleDropdownSelect2} />
+
+ +
); } From 6543e98df55592a17606e9dd3cfd3f6c4b1177ae Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Mon, 11 Aug 2025 16:31:36 +0900 Subject: [PATCH 050/253] =?UTF-8?q?feat=20[#8]=20`Toast`=EB=A5=BC=20?= =?UTF-8?q?=EC=9D=BC=EC=A0=95=20=EC=8B=9C=EA=B0=84=20=EB=B3=B4=EC=97=AC?= =?UTF-8?q?=EC=A3=BC=EA=B3=A0=20=EC=A0=9C=EA=B1=B0=ED=95=98=EB=8A=94=20`us?= =?UTF-8?q?eToast`=20custom=20hook=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/toast/toast.jsx | 18 +++++++++++++++++- src/components/toast/useToast.jsx | 21 +++++++++++++++++++++ src/pages/test-page.jsx | 17 +++++++++++++++-- 3 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 src/components/toast/useToast.jsx diff --git a/src/components/toast/toast.jsx b/src/components/toast/toast.jsx index dadd5c3..d427e5f 100644 --- a/src/components/toast/toast.jsx +++ b/src/components/toast/toast.jsx @@ -11,16 +11,32 @@ const StyledToast = styled.div` display: flex; align-items: center; gap: 12px; - font-size: 16px; font-weight: 400; line-height: 26px; color: white; + white-space: nowrap; + position: fixed; + left: 50%; + bottom: 70px; + transform: translateX(-50%); p { margin: 0; flex-grow: 1; } + + @media (max-width: 1199px) { + bottom: 50px; + } + + @media (max-width: 767px) { + min-width: 0; + transform: none; + left: 20px; + right: 20px; + bottom: 88px; + } `; const Icon = styled.div` diff --git a/src/components/toast/useToast.jsx b/src/components/toast/useToast.jsx new file mode 100644 index 0000000..8b461b6 --- /dev/null +++ b/src/components/toast/useToast.jsx @@ -0,0 +1,21 @@ +import { useEffect, useState } from "react"; + +function useToast(timeout = 2500) { + const [showsToast, setShowsToast] = useState(false); + + useEffect(() => { + if (!showsToast) return; + + const id = setTimeout(() => { + setShowsToast(false); + }, timeout); + + return () => { + clearTimeout(id); + }; + }, [showsToast, setShowsToast, timeout]); + + return { showsToast, setShowsToast }; +} + +export { useToast }; diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index 39fcdbf..29cfa5e 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -15,11 +15,14 @@ import ToggleButton from "../components/button/toggle-button"; import TextField from "../components/text-field/text-field"; import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; import Toast from "../components/toast/toast"; +import { useToast } from "../components/toast/useToast"; function TestPage() { + /* Dropdown type TextField */ const [option1, setOption1] = useState(); const [option2, setOption2] = useState(); const [dropdown2Error, setDropdown2Error] = useState("Error Message"); + const handleDropdownSelect1 = (option) => { setOption1(option); }; @@ -28,6 +31,11 @@ function TestPage() { setDropdown2Error(null); }; + /* Toast */ + const { showsToast, setShowsToast } = useToast(); + + const handleToastClick = () => setShowsToast(true); + return (
-
- +
+ + {showsToast && }
); From 3519f0ccbf80d84242e39cf6e40125b23bcd6a24 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Mon, 11 Aug 2025 16:35:25 +0900 Subject: [PATCH 051/253] =?UTF-8?q?feat=20[#8]=20=EB=8B=AB=EA=B8=B0=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=EC=9C=BC=EB=A1=9C=20`Toast`=EB=A5=BC=20?= =?UTF-8?q?=EB=8B=AB=EC=9D=84=20=EC=88=98=20=EC=9E=88=EA=B2=8C=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/toast/toast.jsx | 13 ++++++++++--- src/pages/test-page.jsx | 8 +++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/components/toast/toast.jsx b/src/components/toast/toast.jsx index d427e5f..e24c6e6 100644 --- a/src/components/toast/toast.jsx +++ b/src/components/toast/toast.jsx @@ -49,16 +49,23 @@ const Icon = styled.div` } `; -function Toast({ message }) { +const IconButton = styled(Icon)` + background: none; + border: none; + padding: 0; + cursor: pointer; +`; + +function Toast({ message, onDismiss }) { return ( 확인

{message}

- + 닫기 - +
); } diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index 29cfa5e..96651ea 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -35,6 +35,7 @@ function TestPage() { const { showsToast, setShowsToast } = useToast(); const handleToastClick = () => setShowsToast(true); + const handleToastDismiss = () => setShowsToast(false); return (
- {showsToast && } + {showsToast && ( + + )}
); From 77d369b54687670119fd8cc70ae548a5c4e5ad43 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 12 Aug 2025 19:58:05 +0900 Subject: [PATCH 052/253] =?UTF-8?q?refactor=20[]=20`useDropdown`=EC=9D=84?= =?UTF-8?q?=20`hooks`=20=EC=95=84=EB=9E=98=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/text-field/dropdown-input/dropdown-input.jsx | 2 +- src/hooks/{dropdown => }/use-dropdown.jsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename src/hooks/{dropdown => }/use-dropdown.jsx (92%) diff --git a/src/components/text-field/dropdown-input/dropdown-input.jsx b/src/components/text-field/dropdown-input/dropdown-input.jsx index 09c937b..5524bde 100644 --- a/src/components/text-field/dropdown-input/dropdown-input.jsx +++ b/src/components/text-field/dropdown-input/dropdown-input.jsx @@ -1,7 +1,7 @@ import styled from "styled-components"; import arrowDownImg from "../../../assets/ic-chevron-down.svg"; import arrowUpImg from "../../../assets/ic-chevron-up.svg"; -import { useDropdown } from "../../../hooks/dropdown/use-dropdown"; +import { useDropdown } from "../../../hooks/use-dropdown"; import INPUT_STYLES from "../input-styles"; import Dropdown from "./dropdown"; import DropdownOption from "./dropdown-option"; diff --git a/src/hooks/dropdown/use-dropdown.jsx b/src/hooks/use-dropdown.jsx similarity index 92% rename from src/hooks/dropdown/use-dropdown.jsx rename to src/hooks/use-dropdown.jsx index cdc06af..16f1601 100644 --- a/src/hooks/dropdown/use-dropdown.jsx +++ b/src/hooks/use-dropdown.jsx @@ -1,5 +1,5 @@ import { useContext, useRef, useState } from "react"; -import DropdownContext from "../../components/text-field/dropdown-input/dropdown-context"; +import DropdownContext from "../components/text-field/dropdown-input/dropdown-context"; function makeRect({ x, y, width } = { x: 0, y: 0, width: 0 }) { return { From 07200f3ec3da8111c29eb9b890b424df991ada7a Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 12 Aug 2025 19:58:23 +0900 Subject: [PATCH 053/253] =?UTF-8?q?refactor=20[]=20`useToast`=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=9D=B4=EB=A6=84=EC=9D=84=20kebab=20case=EB=A1=9C?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/{components/toast/useToast.jsx => hooks/use-toast.jsx} | 0 src/pages/test-page.jsx | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/{components/toast/useToast.jsx => hooks/use-toast.jsx} (100%) diff --git a/src/components/toast/useToast.jsx b/src/hooks/use-toast.jsx similarity index 100% rename from src/components/toast/useToast.jsx rename to src/hooks/use-toast.jsx diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index 96651ea..f0ddc35 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -15,7 +15,7 @@ import ToggleButton from "../components/button/toggle-button"; import TextField from "../components/text-field/text-field"; import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; import Toast from "../components/toast/toast"; -import { useToast } from "../components/toast/useToast"; +import { useToast } from "../hooks/use-toast"; function TestPage() { /* Dropdown type TextField */ From b2dd6b27265f548aa6559eab3271906fd5854f46 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Mon, 11 Aug 2025 19:18:45 +0900 Subject: [PATCH 054/253] =?UTF-8?q?feat=20[#10]=20`Modal`=20component=20UI?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/ic-person.svg | 4 + src/components/modal/modal.jsx | 175 +++++++++++++++++++++++++++++++++ src/pages/test-page.jsx | 8 ++ src/utils/formatter.js | 8 ++ 4 files changed, 195 insertions(+) create mode 100644 src/assets/ic-person.svg create mode 100644 src/components/modal/modal.jsx create mode 100644 src/utils/formatter.js diff --git a/src/assets/ic-person.svg b/src/assets/ic-person.svg new file mode 100644 index 0000000..9aa412e --- /dev/null +++ b/src/assets/ic-person.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/components/modal/modal.jsx b/src/components/modal/modal.jsx new file mode 100644 index 0000000..fe17c58 --- /dev/null +++ b/src/components/modal/modal.jsx @@ -0,0 +1,175 @@ +import styled, { css } from "styled-components"; +import defaultProfileImg from "../../assets/ic-person.svg"; +import { formatDate } from "../../utils/formatter"; +import Badge from "../badge/badge"; +import BADGE_TYPE from "../badge/badge-type"; +import { PrimaryButton } from "../button/button"; +import BUTTON_SIZE from "../button/button-size"; +import Colors from "../color/colors"; + +/* ProfileImage */ + +const profileImageStyle = css` + width: 56px; + height: 56px; + border-radius: 28px; +`; + +const UserProfileImage = styled.div` + ${profileImageStyle} + + img { + width: 100%; + height: 100%; + } +`; + +const DefaultProfileImage = styled.div` + ${profileImageStyle} + background-color: ${Colors.gray(300)}; + display: flex; + justify-content: center; + align-items: center; + + img { + width: 32px; + height: 32px; + } +`; + +function ProfileImage({ profileImg }) { + const img = 프로필 사진; + return profileImg ? ( + {img} + ) : ( + {img} + ); +} + +/* UserInfo */ + +const Name = styled.span` + font-size: 20px; + font-weight: 400; + line-height: 24px; + + span { + font-weight: 700; + } +`; + +const StyledUserInfo = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 6px; +`; + +function UserInfo({ name, type }) { + return ( + + + From.{` ${name}`} + + + + ); +} + +/* UserProfile */ + +const StyledUserProfile = styled.div` + display: flex; + align-items: center; + gap: 16px; +`; + +function UserProfile({ profileImg, name }) { + return ( + + + + + ); +} + +/* Header */ + +const Date = styled.span` + font-size: 14px; + font-weight: 400; + line-height: 20px; + color: ${Colors.gray(400)}; +`; + +const StyledHeader = styled.div` + width: 100%; + border-bottom: 1px solid ${Colors.gray(200)}; + + & > div { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 19px; + } +`; + +function Header({ profileImg, name, date }) { + return ( + +
+ + {formatDate(date, ".")} +
+
+ ); +} + +/* Modal */ + +const Content = styled.p` + margin: 16px 0 24px; + height: 240px; + overflow: scroll; + font-size: 18px; + font-weight: 400; + line-height: 28px; + color: #5a5a5a; + padding-right: 16px; + + &::-webkit-scrollbar { + width: 4px; + height: 0px; + } + + &::-webkit-scrollbar-thumb { + background-color: ${Colors.gray(300)}; + border-radius: 2px; + + &:hover { + background-color: ${Colors.gray(400)}; + } + } +`; + +const StyledModal = styled.div` + width: 600px; + border-radius: 16px; + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08); + padding: 40px; + display: flex; + flex-direction: column; + align-items: center; +`; + +function Modal({ user, date, content }) { + return ( + +
+ {content} + + + ); +} + +export default Modal; diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index f0ddc35..1e08dec 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -12,6 +12,7 @@ import { } from "../components/button/button"; import BUTTON_SIZE from "../components/button/button-size"; import ToggleButton from "../components/button/toggle-button"; +import Modal from "../components/modal/modal"; import TextField from "../components/text-field/text-field"; import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; import Toast from "../components/toast/toast"; @@ -182,6 +183,13 @@ function TestPage() { /> )} +
+ +
); } diff --git a/src/utils/formatter.js b/src/utils/formatter.js new file mode 100644 index 0000000..14596a1 --- /dev/null +++ b/src/utils/formatter.js @@ -0,0 +1,8 @@ +function formatDate(date, token = "-") { + const year = date.getFullYear(); + const month = `${date.getMonth() + 1}`.padStart(2, "0"); + const day = `${date.getDate()}`.padStart(2, "0"); + return `${year}${token}${month}${token}${day}`; +} + +export { formatDate }; From 8a82af25ac16d663550e22385775721de3031ed9 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 12 Aug 2025 20:05:53 +0900 Subject: [PATCH 055/253] =?UTF-8?q?feat=20[#10]=20Modal=EC=9D=98=20?= =?UTF-8?q?=EC=A0=84=EC=97=AD=20=EC=83=81=ED=83=9C=EB=A5=BC=20=EA=B4=80?= =?UTF-8?q?=EB=A6=AC=ED=95=98=EB=8A=94=20context=20=EB=B0=8F=20provider=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.jsx | 13 +++++++++++-- src/components/modal/modal-context.js | 5 +++++ src/components/modal/modal-provider.jsx | 10 ++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 src/components/modal/modal-context.js create mode 100644 src/components/modal/modal-provider.jsx diff --git a/src/app.jsx b/src/app.jsx index 7fb23d8..47815ca 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -1,18 +1,27 @@ import { BrowserRouter, Route, Routes } from "react-router"; +import ModalProvider from "./components/modal/modal-provider"; import DropdownProvider from "./components/text-field/dropdown-input/dropdown-provider"; import MessagePage from "./pages/message-list"; import TestPage from "./pages/test-page"; +function Provider({ children }) { + return ( + + {children} + + ); +} + function App() { return ( - + } /> } /> - + ); } diff --git a/src/components/modal/modal-context.js b/src/components/modal/modal-context.js new file mode 100644 index 0000000..2cee28d --- /dev/null +++ b/src/components/modal/modal-context.js @@ -0,0 +1,5 @@ +import { createContext } from "react"; + +const ModalContext = createContext(); + +export default ModalContext; diff --git a/src/components/modal/modal-provider.jsx b/src/components/modal/modal-provider.jsx new file mode 100644 index 0000000..f7b6d44 --- /dev/null +++ b/src/components/modal/modal-provider.jsx @@ -0,0 +1,10 @@ +import { useState } from "react"; +import ModalContext from "./modal-context"; + +function ModalProvider({ children }) { + const [showsModal, setShowsModal] = useState(false); + const value = { showsModal, setShowsModal }; + return {children}; +} + +export default ModalProvider; From 79888c9081cd537be010979d7db7484bbe93e306 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 12 Aug 2025 20:05:59 +0900 Subject: [PATCH 056/253] =?UTF-8?q?Button=20=EB=93=B1=20trigger=EB=A5=BC?= =?UTF-8?q?=20=ED=86=B5=ED=95=B4=20Modal=20=EB=9D=84=EC=9A=B0=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 1 + src/components/modal/modal.jsx | 43 ++++++++++++++++++++++++++++++---- src/hooks/use-modal.jsx | 9 +++++++ src/pages/test-page.jsx | 20 ++++++++++++---- 4 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 src/hooks/use-modal.jsx diff --git a/index.html b/index.html index e57d567..80aec14 100644 --- a/index.html +++ b/index.html @@ -16,6 +16,7 @@
+ diff --git a/src/components/modal/modal.jsx b/src/components/modal/modal.jsx index fe17c58..d8b4aa2 100644 --- a/src/components/modal/modal.jsx +++ b/src/components/modal/modal.jsx @@ -1,5 +1,7 @@ +import { createPortal } from "react-dom"; import styled, { css } from "styled-components"; import defaultProfileImg from "../../assets/ic-person.svg"; +import { useModal } from "../../hooks/use-modal"; import { formatDate } from "../../utils/formatter"; import Badge from "../badge/badge"; import BADGE_TYPE from "../badge/badge-type"; @@ -153,6 +155,7 @@ const Content = styled.p` `; const StyledModal = styled.div` + background-color: white; width: 600px; border-radius: 16px; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08); @@ -162,13 +165,43 @@ const StyledModal = styled.div` align-items: center; `; +/* Container */ + +const ModalContainer = styled.div` + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + background-color: rgba(0, 0, 0, 0.6); + display: flex; + justify-content: center; + align-items: center; +`; + function Modal({ user, date, content }) { + const { setShowsModal } = useModal(); + + const ModalPortal = ({ children }) => { + return createPortal(children, document.getElementById("modal")); + }; + + const handleConfirmClick = () => setShowsModal(false); + return ( - -
- {content} - - + + + +
+ {content} + + + + ); } diff --git a/src/hooks/use-modal.jsx b/src/hooks/use-modal.jsx new file mode 100644 index 0000000..d215967 --- /dev/null +++ b/src/hooks/use-modal.jsx @@ -0,0 +1,9 @@ +import { useContext } from "react"; +import ModalContext from "../components/modal/modal-context"; + +function useModal() { + const { showsModal, setShowsModal } = useContext(ModalContext); + return { showsModal, setShowsModal }; +} + +export { useModal }; diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index 1e08dec..98dc546 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -16,6 +16,7 @@ import Modal from "../components/modal/modal"; import TextField from "../components/text-field/text-field"; import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; import Toast from "../components/toast/toast"; +import { useModal } from "../hooks/use-modal"; import { useToast } from "../hooks/use-toast"; function TestPage() { @@ -38,6 +39,10 @@ function TestPage() { const handleToastClick = () => setShowsToast(true); const handleToastDismiss = () => setShowsToast(false); + /* Modal */ + const { showsModal, setShowsModal } = useModal(); + const handleModalClick = () => setShowsModal(true); + return (
- + {showsModal && ( + + )}
); From 47814f52c7c10c2f37fde0d0975c1f2a3190833a Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 12 Aug 2025 21:17:38 +0900 Subject: [PATCH 057/253] =?UTF-8?q?feat=20[#15]=20Header=20component=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/logo.svg | 4 ++++ src/components/header/header.jsx | 37 ++++++++++++++++++++++++++++++++ src/pages/test-page.jsx | 6 ++++++ src/utils/media.js | 7 ++++++ 4 files changed, 54 insertions(+) create mode 100644 src/assets/logo.svg create mode 100644 src/components/header/header.jsx create mode 100644 src/utils/media.js diff --git a/src/assets/logo.svg b/src/assets/logo.svg new file mode 100644 index 0000000..43d1c8e --- /dev/null +++ b/src/assets/logo.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/components/header/header.jsx b/src/components/header/header.jsx new file mode 100644 index 0000000..1ec8714 --- /dev/null +++ b/src/components/header/header.jsx @@ -0,0 +1,37 @@ +import styled from "styled-components"; +import logoImg from "../../assets/logo.svg"; +import { media } from "../../utils/media"; + +const HeaderContent = styled.div` + width: 100%; + max-width: 1200px; + display: flex; + justify-content: space-between; + align-items: center; +`; + +const StyledHeader = styled.header` + display: flex; + justify-content: center; + align-items: center; + height: 64px; + border-bottom: 1px solid #ededed; + padding: 0 24px; + + ${media.mobile} { + padding: 0 16px; + } +`; + +function Header({ className, children }) { + return ( + + + 로고 +
{children}
+
+
+ ); +} + +export default Header; diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index 2ae1ed2..751218a 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -1,4 +1,5 @@ import { useState } from "react"; +import styled from "styled-components"; import smileAddImg from "../assets/ic-face-smile-add.svg"; import Badge from "../components/badge/badge"; import BADGE_TYPE from "../components/badge/badge-type"; @@ -12,9 +13,14 @@ import { } from "../components/button/button"; import BUTTON_SIZE from "../components/button/button-size"; import ToggleButton from "../components/button/toggle-button"; +import Header from "../components/header/header"; import TextField from "../components/text-field/text-field"; import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; +const OutlinedHeader = styled(Header)` + border: 1px solid black; +`; + function TestPage() { const [option1, setOption1] = useState(); const [option2, setOption2] = useState(); diff --git a/src/utils/media.js b/src/utils/media.js new file mode 100644 index 0000000..a389097 --- /dev/null +++ b/src/utils/media.js @@ -0,0 +1,7 @@ +const media = { + desktop: "@media (min-width: 1200px)", + tablet: "@media (max-width: 1199px)", + mobile: "@media (max-width: 797px)", +}; + +export { media }; From 4e7f9d9922c7637581d16f79cd39a5b2deba9808 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 12 Aug 2025 21:31:34 +0900 Subject: [PATCH 058/253] =?UTF-8?q?feat=20[#15]=20`OnboardingLayout`=20com?= =?UTF-8?q?ponent=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.jsx | 19 ++++++++++++++++++- src/layouts/onboarding-layout.jsx | 20 ++++++++++++++++++++ src/pages/main-page.jsx | 5 +++++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 src/layouts/onboarding-layout.jsx create mode 100644 src/pages/main-page.jsx diff --git a/src/app.jsx b/src/app.jsx index 7fb23d8..9ac6f65 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -1,5 +1,7 @@ import { BrowserRouter, Route, Routes } from "react-router"; import DropdownProvider from "./components/text-field/dropdown-input/dropdown-provider"; +import OnboardingLayout from "./layouts/onboarding-layout"; +import MainPage from "./pages/main-page"; import MessagePage from "./pages/message-list"; import TestPage from "./pages/test-page"; @@ -8,8 +10,23 @@ function App() { + + + + } + /> + + + + } + /> } /> - } /> diff --git a/src/layouts/onboarding-layout.jsx b/src/layouts/onboarding-layout.jsx new file mode 100644 index 0000000..c85f52d --- /dev/null +++ b/src/layouts/onboarding-layout.jsx @@ -0,0 +1,20 @@ +import { OutlinedButton } from "../components/button/button"; +import BUTTON_SIZE from "../components/button/button-size"; +import Header from "../components/header/header"; + +function OnboardingLayout({ children, onCreate }) { + return ( + <> +
+ +
+
{children}
+ + ); +} + +export default OnboardingLayout; diff --git a/src/pages/main-page.jsx b/src/pages/main-page.jsx new file mode 100644 index 0000000..a1d2cba --- /dev/null +++ b/src/pages/main-page.jsx @@ -0,0 +1,5 @@ +function MainPage() { + return

Main Page

; +} + +export default MainPage; From 223f7e8770e67790dd4d7311c9280904d28e2f0a Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 12 Aug 2025 21:47:21 +0900 Subject: [PATCH 059/253] =?UTF-8?q?feat=20[#15]=20`ContentLayout`=20compon?= =?UTF-8?q?ent=20=EA=B5=AC=ED=98=84,=20dummy=20page=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=20=ED=9B=84=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.jsx | 30 ++++++++++++++++++++++++++++++ src/layouts/content-layout.jsx | 12 ++++++++++++ src/pages/add-post-page.jsx | 5 +++++ src/pages/recipient-post-page.jsx | 5 +++++ src/pages/send-message-page.jsx | 5 +++++ 5 files changed, 57 insertions(+) create mode 100644 src/layouts/content-layout.jsx create mode 100644 src/pages/add-post-page.jsx create mode 100644 src/pages/recipient-post-page.jsx create mode 100644 src/pages/send-message-page.jsx diff --git a/src/app.jsx b/src/app.jsx index 9ac6f65..bf1c3b1 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -1,8 +1,12 @@ import { BrowserRouter, Route, Routes } from "react-router"; import DropdownProvider from "./components/text-field/dropdown-input/dropdown-provider"; +import ContentLayout from "./layouts/content-layout"; import OnboardingLayout from "./layouts/onboarding-layout"; +import AddPostPage from "./pages/add-post-page"; import MainPage from "./pages/main-page"; import MessagePage from "./pages/message-list"; +import RecipientPostPage from "./pages/recipient-post-page"; +import SendMessagePage from "./pages/send-message-page"; import TestPage from "./pages/test-page"; function App() { @@ -26,6 +30,32 @@ function App() { } /> + + + + + } + /> + + + + } + /> + + + + } + /> + } /> diff --git a/src/layouts/content-layout.jsx b/src/layouts/content-layout.jsx new file mode 100644 index 0000000..d6b6307 --- /dev/null +++ b/src/layouts/content-layout.jsx @@ -0,0 +1,12 @@ +import Header from "../components/header/header"; + +function ContentLayout({ children }) { + return ( + <> +
+
{children}
+ + ); +} + +export default ContentLayout; diff --git a/src/pages/add-post-page.jsx b/src/pages/add-post-page.jsx new file mode 100644 index 0000000..a2a8a50 --- /dev/null +++ b/src/pages/add-post-page.jsx @@ -0,0 +1,5 @@ +function AddPostPage() { + return

Add Post Page

; +} + +export default AddPostPage; diff --git a/src/pages/recipient-post-page.jsx b/src/pages/recipient-post-page.jsx new file mode 100644 index 0000000..26765cb --- /dev/null +++ b/src/pages/recipient-post-page.jsx @@ -0,0 +1,5 @@ +function RecipientPostPage() { + return

Recipient Post Page

; +} + +export default RecipientPostPage; diff --git a/src/pages/send-message-page.jsx b/src/pages/send-message-page.jsx new file mode 100644 index 0000000..9bab5b6 --- /dev/null +++ b/src/pages/send-message-page.jsx @@ -0,0 +1,5 @@ +function SendMessagePage() { + return

Send Message Page

; +} + +export default SendMessagePage; From 900f8ce052a1e4333f4bf1a56034d21fa2a3c563 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 12 Aug 2025 21:49:09 +0900 Subject: [PATCH 060/253] =?UTF-8?q?refactor=20[#15]=20=EC=9D=B4=EB=A6=84?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD:=20`add-post-page`=20->=20`create-post-pa?= =?UTF-8?q?ge`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.jsx | 4 ++-- src/pages/add-post-page.jsx | 5 ----- src/pages/create-post-page.jsx | 5 +++++ 3 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 src/pages/add-post-page.jsx create mode 100644 src/pages/create-post-page.jsx diff --git a/src/app.jsx b/src/app.jsx index bf1c3b1..448dca1 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -2,7 +2,7 @@ import { BrowserRouter, Route, Routes } from "react-router"; import DropdownProvider from "./components/text-field/dropdown-input/dropdown-provider"; import ContentLayout from "./layouts/content-layout"; import OnboardingLayout from "./layouts/onboarding-layout"; -import AddPostPage from "./pages/add-post-page"; +import CreatePostPage from "./pages/create-post-page"; import MainPage from "./pages/main-page"; import MessagePage from "./pages/message-list"; import RecipientPostPage from "./pages/recipient-post-page"; @@ -35,7 +35,7 @@ function App() { index element={ - + } /> diff --git a/src/pages/add-post-page.jsx b/src/pages/add-post-page.jsx deleted file mode 100644 index a2a8a50..0000000 --- a/src/pages/add-post-page.jsx +++ /dev/null @@ -1,5 +0,0 @@ -function AddPostPage() { - return

Add Post Page

; -} - -export default AddPostPage; diff --git a/src/pages/create-post-page.jsx b/src/pages/create-post-page.jsx new file mode 100644 index 0000000..9645cf3 --- /dev/null +++ b/src/pages/create-post-page.jsx @@ -0,0 +1,5 @@ +function CreatePostPage() { + return

Create Post Page

; +} + +export default CreatePostPage; From 32530cda2d6fc268a1e036f050f992f140efd33a Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 12 Aug 2025 21:52:00 +0900 Subject: [PATCH 061/253] =?UTF-8?q?feat=20[#15]=20`OnboardingLayout`=20?= =?UTF-8?q?=EB=82=B4=EB=B6=80=EC=97=90=EC=84=9C=20'=EB=A1=A4=EB=A7=81=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=ED=8D=BC=20=EB=A7=8C=EB=93=A4=EA=B8=B0'=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=20=ED=81=B4=EB=A6=AD=20=EC=8B=9C=20=EC=A7=81?= =?UTF-8?q?=EC=A0=91=20'/post'=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/layouts/onboarding-layout.jsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/layouts/onboarding-layout.jsx b/src/layouts/onboarding-layout.jsx index c85f52d..beab0ed 100644 --- a/src/layouts/onboarding-layout.jsx +++ b/src/layouts/onboarding-layout.jsx @@ -1,15 +1,20 @@ +import { useNavigate } from "react-router"; import { OutlinedButton } from "../components/button/button"; import BUTTON_SIZE from "../components/button/button-size"; import Header from "../components/header/header"; -function OnboardingLayout({ children, onCreate }) { +function OnboardingLayout({ children }) { + const navigate = useNavigate(); + + const handlePostCreate = () => navigate("/post"); + return ( <>
{children}
From 1aabb14766f23e72c4914813826a3f7557a20635 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Wed, 13 Aug 2025 03:49:49 +0900 Subject: [PATCH 062/253] =?UTF-8?q?feat=20[#22]=20Post=20Page=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84,=20=EA=B3=B5=ED=86=B5=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 32 +++------ src/app.jsx | 4 +- src/assets/ic-check.svg | 3 + src/components/option/colorchip-option.jsx | 0 src/pages/post-page.jsx | 84 ++++++++++++++++++++++ 5 files changed, 99 insertions(+), 24 deletions(-) create mode 100644 src/assets/ic-check.svg create mode 100644 src/components/option/colorchip-option.jsx create mode 100644 src/pages/post-page.jsx diff --git a/package-lock.json b/package-lock.json index a13efef..612f3c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,6 @@ "axios": "^1.11.0", "react": "^19.1.1", "react-dom": "^19.1.1", - "react-router": "^7.8.0", "styled-components": "^6.1.19" }, "devDependencies": { @@ -1044,6 +1043,15 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@remix-run/router": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.0.tgz", + "integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.27", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", @@ -2825,28 +2833,6 @@ "node": ">=0.10.0" } }, - "node_modules/react-router": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.8.0.tgz", - "integrity": "sha512-r15M3+LHKgM4SOapNmsH3smAizWds1vJ0Z9C4mWaKnT9/wD7+d/0jYcj6LmOvonkrO4Rgdyp4KQ/29gWN2i1eg==", - "license": "MIT", - "dependencies": { - "cookie": "^1.0.1", - "set-cookie-parser": "^2.6.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "react": ">=18", - "react-dom": ">=18" - }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - } - } - }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", diff --git a/src/app.jsx b/src/app.jsx index 7fb23d8..653bd71 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -1,7 +1,8 @@ -import { BrowserRouter, Route, Routes } from "react-router"; +import { BrowserRouter, Route, Routes } from "react-router-dom"; import DropdownProvider from "./components/text-field/dropdown-input/dropdown-provider"; import MessagePage from "./pages/message-list"; import TestPage from "./pages/test-page"; +import PostPage from "./pages/post-page"; function App() { return ( @@ -10,6 +11,7 @@ function App() { } /> } /> + } /> diff --git a/src/assets/ic-check.svg b/src/assets/ic-check.svg new file mode 100644 index 0000000..e5806ba --- /dev/null +++ b/src/assets/ic-check.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/option/colorchip-option.jsx b/src/components/option/colorchip-option.jsx new file mode 100644 index 0000000..e69de29 diff --git a/src/pages/post-page.jsx b/src/pages/post-page.jsx new file mode 100644 index 0000000..901a7c3 --- /dev/null +++ b/src/pages/post-page.jsx @@ -0,0 +1,84 @@ +import { useState } from "react"; +import InputTextField from "../components/text-field/text-field"; +import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; +import Colors from "../components/color/colors"; +import ToggleButton from "../components/button/toggle-button"; + +const postContainerStyle = { + display: "flex", + flexDirection: "column", + justifyContent: "center", + alignItems: "center", + width: "100%", + margin: "0 auto", +}; + +const wrapperStyle = { + paddingTop: "50px", + width: "720px", +}; + +const postTitleStyle = { + fontWeight: "700", +}; + +const postSummaryStyle = { + fontWeight: "400", + color: Colors.gray(500), +}; + +const postToggleButtonStyle = { + width: "100%", + display: "flex", +}; + +function PostPage() { + const [name, setName] = useState(""); + const [nameError, setNameError] = useState(""); + + const handleChange = (e) => { + const value = e.target.value; + setName(value); + + // 값 입력 중 에러 없애기 + if (nameError) { + setNameError(""); + } + }; + + const handleOnBlur = () => { + if (name.trim() === "") { + setNameError("값을 입력해 주세요"); + } else if (name !== name.trim()) { + setNameError("공백 없이 입력해 주세요"); // 텍스트 앞 뒤 공백 에러 처리(임시) + } + }; + + return ( +
+
+

To.

+ +
+
+

배경화면을 선택해 주세요.

+

+ 컬러를 선택하거나, 이미지를 선택할 수 있습니다. +

+
+ +
+
+ +
+ ); +} + +export default PostPage; From 8ffcd0abba813f8ec5915c740f66fef3f3f2da7d Mon Sep 17 00:00:00 2001 From: luli Date: Wed, 13 Aug 2025 15:18:05 +0900 Subject: [PATCH 063/253] =?UTF-8?q?[#27]=20list=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=20styled-components=EB=A1=9C=20=EB=B3=80=EA=B2=BD,=20=EC=B9=B4?= =?UTF-8?q?=EB=93=9C=20arrow=EB=B2=84=ED=8A=BC=20=EA=B0=84=EB=8B=A8?= =?UTF-8?q?=ED=95=98=EA=B2=8C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit test데이터도 아직 완벽하게 테스트용은 아니고 단지 출력이 잘 되는지만 테스트할려고 뽑은거라서 아~~~주 간단하게만 해놓았습니다. --- src/pages/message-list.jsx | 266 ++++++++++++++++++++++--------------- 1 file changed, 156 insertions(+), 110 deletions(-) diff --git a/src/pages/message-list.jsx b/src/pages/message-list.jsx index 6cc97b3..1635722 100644 --- a/src/pages/message-list.jsx +++ b/src/pages/message-list.jsx @@ -10,128 +10,174 @@ import ToggleButton from "../components/button/toggle-button"; import React, { useEffect, useState } from "react"; import axiosInstance from "../api/axios-instance"; +import styled from "styled-components"; + +/* styled components */ +const TopContainer = styled.div` + text-align: center; +`; + +const CardSection = styled.section` + justify-self: center; +`; + +const CardTitle = styled.h2` + text-align: left; +`; + +const CardContainer = styled.div` + border: 1px solid red; + display: grid; + grid-template-columns: 275px 275px 275px 275px; + gap: 20px; + width: fit-content; + + position: relative; + overflow: visible; +`; + +const CardItem = styled.div` + width: 275px; + height: 260px; + border: 1px solid red; +`; + +const NextBtnWpr = styled.div` + position: absolute; + right: -20px; + top: 50%; + transform: translateY(-50%); + z-index: 10; +`; + +const PrevBtnWpr = styled.div` + position: absolute; + left: -20px; + top: 50%; + transform: translateY(-50%); + z-index: 10; +`; + +const MakingBtn = styled(PrimaryButton)` + margin-top: 64px; + font-weight: 400; + padding: 14px 60px; +`; + +/* 그냥 출력 테스트용 */ +const testData = [ + { id: 1, to: "test1", messageCount: 1 }, + { id: 2, to: "test2", messageCount: 5 }, + { id: 3, to: "test3", messageCount: 10 }, + { id: 4, to: "test4", messageCount: 2 }, + { id: 5, to: "test5", messageCount: 3 }, + { id: 6, to: "test6", messageCount: 1 }, +]; function ShowMessageList() { - // const [imageUrl, setImageUrl] = useState(null); + const [pprCurrentPage, setPprCurrentPage] = useState(0); // 인기카드 + const [currentPage, setCurrentPage] = useState(0); // 일반카드 + const [pprShowCards, setPprShowCards] = useState([]); + const [showCards, setShowCards] = useState([]); + const cardCount = 4; + + /* axios로 데이터 가져온다고 가정 */ + // axiosInstance + // .get("/18-3/recipients/?limit=5&offset=20") + // .then((res) => { + // console.log(res.data); + // }) + // .catch(console.error); + + const totalPages = Math.ceil(testData.length / cardCount); - const cardConStyle = { - border: "1px solid red", - display: "grid", - gridTemplateColumns: "275px 275px 275px 275px", - gap: "20px", - width: "fit-content", - - position: "relative", - overflow: "visible", - }; - - const cardStyle = { - width: "275px", - height: "260px", - border: "1px solid red", - }; - - const testStyle = { - textAlign: "center", - }; - - const sectionStyle = { - justifySelf: "center", - }; - - const buttonStyle = { - marginTop: "64px", - fontWeight: "400", - padding: "14px 60px", - }; - - const htStyle = { - textAlign: "left", - }; - - const rButton = { - position: "absolute", - right: -20, // 필요시 조정 - top: "50%", - transform: "translateY(-50%)", - zIndex: 20, + useEffect(() => { + const strtPageNum = currentPage * cardCount; + const endPageNum = strtPageNum + cardCount; + + const pprStrtPageNum = pprCurrentPage * cardCount; + const pprEndPageNum = pprStrtPageNum + cardCount; + + /* createdAt(생성된 시점)에 따라서 정렬 */ + setShowCards(testData.slice(strtPageNum, endPageNum)); + + /* 여기서 messageCount(메시지수)에 따라서 정렬 */ + setPprShowCards(testData.slice(pprStrtPageNum, pprEndPageNum)); + }, [pprCurrentPage, currentPage]); + + const nextPage = (mode = null) => { + if (mode) { + console.log("pprnext"); + if (pprCurrentPage < totalPages - 1) { + setPprCurrentPage((pprCurrentNum) => pprCurrentNum + 1); + } + } else { + console.log("justnext"); + if (currentPage < totalPages - 1) { + setCurrentPage((currentNum) => currentNum + 1); + } + } }; - const lButton = { - position: "absolute", - left: -20, // 필요시 조정 - top: "50%", - transform: "translateY(-50%)", - zIndex: 20, + const prevPage = (mode = null) => { + if (mode) { + console.log("pprprev"); + if (pprCurrentPage > 0) { + setPprCurrentPage((pprCurrentNum) => pprCurrentNum - 1); + } + } else { + console.log("justprev"); + if (currentPage > 0) { + setCurrentPage((currentNum) => currentNum - 1); + } + } }; - useEffect(() => { - axiosInstance - .get("/18-3/recipients/?limit=5&offset=20") - .then((res) => { - console.log(res.data); - }) - .catch(console.error); - }, []); - return ( -
+ /* navi 들어갈 자리 */
-
-

인기 롤링 페이퍼 🔥

-
-
-
-
-
-
- -
-
-
-
-

최근에 만든 롤링 페이퍼 ⭐

-
-
-
-
-
-
- -
-
-
+ + 인기 롤링 페이퍼 🔥 + + {pprShowCards.map((item) => ( + {item.to} // 테스트용 + ))} + {pprCurrentPage > 0 ? ( + prevPage("ppr")}> + + + ) : null} + {pprCurrentPage < totalPages - 1 ? ( + nextPage("ppr")}> + + + ) : null} + + + + + 최근에 만든 롤링 페이퍼 ⭐ + + {showCards.map((item) => ( + {item.to} // 테스트용 + ))} + {currentPage > 0 ? ( + prevPage()}> + + + ) : null} + {currentPage < totalPages - 1 ? ( + nextPage()}> + + + ) : null} + +
- -
+ + ); - - /* axios 사용 예시코드 */ - // useEffect(() => { - // axiosInstance - // .get("/background-images/") - // .then((res) => { - // if (res.data && res.data.imageUrls && res.data.imageUrls.length > 0) { - // setImageUrl(res.data.imageUrls[0]); - // } - // }) - // .catch(console.error); - // }, []); - - // return ( - //
- // {imageUrl ? ( - // background - // ) : ( - //

이미지를 불러오는 중입니다...

- // )} - //
- // ); } export default ShowMessageList; From 920452aafd98019f75ad3807690a11ccc8827e23 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Wed, 13 Aug 2025 15:46:28 +0900 Subject: [PATCH 064/253] =?UTF-8?q?refactor=20#22=20styled-components=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9,=20=EC=BD=94=EB=93=9C=20=EA=B0=9C=EC=84=A0?= =?UTF-8?q?=20/=20feat=20#29=20SendPage=20=EA=B5=AC=ED=98=84=20=EC=A4=80?= =?UTF-8?q?=EB=B9=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 49 +++++++++--- package.json | 1 + src/app.jsx | 2 + src/components/option/colorchip-option.jsx | 0 src/pages/post-page.jsx | 90 +++++++++++---------- src/pages/send-page.jsx | 91 ++++++++++++++++++++++ 6 files changed, 178 insertions(+), 55 deletions(-) delete mode 100644 src/components/option/colorchip-option.jsx create mode 100644 src/pages/send-page.jsx diff --git a/package-lock.json b/package-lock.json index 612f3c5..7d25d6a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,8 @@ "axios": "^1.11.0", "react": "^19.1.1", "react-dom": "^19.1.1", + "react-router": "^7.8.0", + "react-router-dom": "^7.8.0", "styled-components": "^6.1.19" }, "devDependencies": { @@ -1043,15 +1045,6 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@remix-run/router": { - "version": "1.23.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.0.tgz", - "integrity": "sha512-O3rHJzAQKamUz1fvE0Qaw0xSFqsA/yafi2iqeE0pvdFtCO1viYx8QL6f3Ln/aCCTLxs68SLf0KPM9eSeM8yBnA==", - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.27", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", @@ -2833,6 +2826,44 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.8.0.tgz", + "integrity": "sha512-r15M3+LHKgM4SOapNmsH3smAizWds1vJ0Z9C4mWaKnT9/wD7+d/0jYcj6LmOvonkrO4Rgdyp4KQ/29gWN2i1eg==", + "license": "MIT", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.8.0.tgz", + "integrity": "sha512-ntInsnDVnVRdtSu6ODmTQ41cbluak/ENeTif7GBce0L6eztFg6/e1hXAysFQI8X25C8ipKmT9cClbJwxx3Kaqw==", + "license": "MIT", + "dependencies": { + "react-router": "7.8.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", diff --git a/package.json b/package.json index 72906b1..6364243 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "react": "^19.1.1", "react-dom": "^19.1.1", "react-router": "^7.8.0", + "react-router-dom": "^7.8.0", "styled-components": "^6.1.19" }, "devDependencies": { diff --git a/src/app.jsx b/src/app.jsx index 653bd71..ce38db8 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -3,6 +3,7 @@ import DropdownProvider from "./components/text-field/dropdown-input/dropdown-pr import MessagePage from "./pages/message-list"; import TestPage from "./pages/test-page"; import PostPage from "./pages/post-page"; +import SendPage from "./pages/send-page"; function App() { return ( @@ -12,6 +13,7 @@ function App() { } /> } /> } /> + } /> diff --git a/src/components/option/colorchip-option.jsx b/src/components/option/colorchip-option.jsx deleted file mode 100644 index e69de29..0000000 diff --git a/src/pages/post-page.jsx b/src/pages/post-page.jsx index 901a7c3..f88a174 100644 --- a/src/pages/post-page.jsx +++ b/src/pages/post-page.jsx @@ -3,34 +3,35 @@ import InputTextField from "../components/text-field/text-field"; import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; import Colors from "../components/color/colors"; import ToggleButton from "../components/button/toggle-button"; +import styled from "styled-components"; -const postContainerStyle = { - display: "flex", - flexDirection: "column", - justifyContent: "center", - alignItems: "center", - width: "100%", - margin: "0 auto", -}; +const PostContainerStyle = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + width: 100%; + margin: 0 auto; +`; -const wrapperStyle = { - paddingTop: "50px", - width: "720px", -}; +const WrapperStyle = styled.div` + padding-top: 50px; + width: 720px; +`; -const postTitleStyle = { - fontWeight: "700", -}; +const PostTitleStyle = styled.h2` + font-weight: 700; +`; -const postSummaryStyle = { - fontWeight: "400", - color: Colors.gray(500), -}; +const PostSummaryStyle = styled.p` + font-weight: 400; + color: Colors.gray(500); +`; -const postToggleButtonStyle = { - width: "100%", - display: "flex", -}; +const PostToggleButtonStyle = styled.div` + width: 100%; + display: flex; +`; function PostPage() { const [name, setName] = useState(""); @@ -39,45 +40,42 @@ function PostPage() { const handleChange = (e) => { const value = e.target.value; setName(value); - - // 값 입력 중 에러 없애기 - if (nameError) { - setNameError(""); - } + setNameError(""); // 값 입력 중 에러 없애기 }; - const handleOnBlur = () => { - if (name.trim() === "") { + const handleBlur = () => { + const trimmed = name.trim(); + if (trimmed === "") { setNameError("값을 입력해 주세요"); - } else if (name !== name.trim()) { - setNameError("공백 없이 입력해 주세요"); // 텍스트 앞 뒤 공백 에러 처리(임시) + } else if (name !== trimmed) { + setNameError("앞 뒤 공백 없이 입력해 주세요"); // 텍스트 앞 뒤 공백 에러 처리(임시) } }; return ( -
-
-

To.

- + + To. + -
-
-

배경화면을 선택해 주세요.

-

+ + + 배경화면을 선택해 주세요. + 컬러를 선택하거나, 이미지를 선택할 수 있습니다. -

-
+ + -
-
+ + -
+ ); } diff --git a/src/pages/send-page.jsx b/src/pages/send-page.jsx new file mode 100644 index 0000000..c0d2391 --- /dev/null +++ b/src/pages/send-page.jsx @@ -0,0 +1,91 @@ +import { useState } from "react"; +import InputTextField from "../components/text-field/text-field"; +import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; +import Colors from "../components/color/colors"; +import ToggleButton from "../components/button/toggle-button"; +import styled from "styled-components"; + +const SendContainerStyle = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + width: 100%; + margin: 0 auto; +`; + +const WrapperStyle = styled.div` + padding-top: 50px; + width: 720px; +`; + +const SendTitleStyle = styled.h2` + font-weight: 700; +`; + +const SendSummaryStyle = styled.p` + font-weight: 400; + color: Colors.gray(500); +`; + +const SendToggleButtonStyle = styled.div` + width: 100%; + display: flex; +`; + +function SendPage() { + const [name, setName] = useState(""); + const [nameError, setNameError] = useState(""); + + const handleChange = (e) => { + const value = e.target.value; + setName(value); + + // 값 입력 중 에러 없애기 + if (nameError) { + setNameError(""); + } + }; + + const handleOnBlur = () => { + if (name.trim() === "") { + setNameError("값을 입력해 주세요"); + } else if (name !== name.trim()) { + setNameError("공백 없이 입력해 주세요"); // 텍스트 앞 뒤 공백 에러 처리(임시) + } + }; + + return ( + + + From. + + + + 프로필 이미지 + 프로필 이미지를 선택해 주세요! + + + 상대와의 관계 + + + 내용을 입력해 주세요 + + + 폰트 선택 + + + + + + ); +} + +export default SendPage; From 8c2b5fe42ba970fa05ba7353e51b6c712a9f0286 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Wed, 13 Aug 2025 17:40:02 +0900 Subject: [PATCH 065/253] =?UTF-8?q?refactor=20[#24]=20=EC=9D=B4=EB=A6=84?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD:=20`InputTextField`=20->=20`TextField`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `TextField` component를 input과 dropdown type으로 나누는 과정에서 이름을 미처 수정하지 못했습니다. --- src/components/text-field/text-field.jsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/text-field/text-field.jsx b/src/components/text-field/text-field.jsx index c97832d..36656d6 100644 --- a/src/components/text-field/text-field.jsx +++ b/src/components/text-field/text-field.jsx @@ -4,7 +4,7 @@ import DropdownInput from "./dropdown-input/dropdown-input"; import TEXT_FIELD_TYPE from "./text-field-type"; import TextInput from "./text-input/text-input"; -const StyledInputTextField = styled.div` +const StyledTextField = styled.div` display: flex; flex-direction: column; gap: 4px; @@ -18,17 +18,17 @@ const ErrorMessage = styled.p` color: ${Colors.error}; `; -function InputTextField({ type, error, dropdownId, ...props }) { +function TextField({ type, error, dropdownId, ...props }) { return ( - + {type === TEXT_FIELD_TYPE.input ? ( ) : ( )} {error && {error}} - + ); } -export default InputTextField; +export default TextField; From 8daa7194432b91b827277640cf22177651282c8d Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Wed, 13 Aug 2025 17:41:44 +0900 Subject: [PATCH 066/253] =?UTF-8?q?refactor=20[]=20=EC=B6=95=EC=95=BD?= =?UTF-8?q?=EB=90=9C=20=EC=9D=B4=EB=A6=84=EC=9D=84=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EC=9D=8C=20(`~Img`=20->=20`~Imag?= =?UTF-8?q?e`)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/button/arrow-button.jsx | 8 +++---- src/components/header/header.jsx | 4 ++-- src/components/modal/modal.jsx | 4 ++-- .../dropdown-input/dropdown-input.jsx | 6 ++--- src/components/toast/toast.jsx | 8 +++---- src/pages/test-page.jsx | 22 +++++++++---------- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/components/button/arrow-button.jsx b/src/components/button/arrow-button.jsx index b1a53c9..12b0919 100644 --- a/src/components/button/arrow-button.jsx +++ b/src/components/button/arrow-button.jsx @@ -1,12 +1,12 @@ import styled from "styled-components"; -import arrowLeftImg from "../../assets/ic-chevron-left.svg"; -import arrowRightImg from "../../assets/ic-chevron-right.svg"; +import arrowLeftImage from "../../assets/ic-chevron-left.svg"; +import arrowRightImage from "../../assets/ic-chevron-right.svg"; import Colors from "../color/colors"; import ARROW_BUTTON_DIRECTION from "./arrow-button-direction"; const arrowImg = { - [ARROW_BUTTON_DIRECTION.left]: arrowLeftImg, - [ARROW_BUTTON_DIRECTION.right]: arrowRightImg, + [ARROW_BUTTON_DIRECTION.left]: arrowLeftImage, + [ARROW_BUTTON_DIRECTION.right]: arrowRightImage, }; const StyledArrowButton = styled.button` diff --git a/src/components/header/header.jsx b/src/components/header/header.jsx index 1ec8714..3d3fe46 100644 --- a/src/components/header/header.jsx +++ b/src/components/header/header.jsx @@ -1,5 +1,5 @@ import styled from "styled-components"; -import logoImg from "../../assets/logo.svg"; +import logoImage from "../../assets/logo.svg"; import { media } from "../../utils/media"; const HeaderContent = styled.div` @@ -27,7 +27,7 @@ function Header({ className, children }) { return ( - 로고 + 로고
{children}
diff --git a/src/components/modal/modal.jsx b/src/components/modal/modal.jsx index d8b4aa2..0aa5fbc 100644 --- a/src/components/modal/modal.jsx +++ b/src/components/modal/modal.jsx @@ -1,6 +1,6 @@ import { createPortal } from "react-dom"; import styled, { css } from "styled-components"; -import defaultProfileImg from "../../assets/ic-person.svg"; +import defaultProfileImage from "../../assets/ic-person.svg"; import { useModal } from "../../hooks/use-modal"; import { formatDate } from "../../utils/formatter"; import Badge from "../badge/badge"; @@ -40,7 +40,7 @@ const DefaultProfileImage = styled.div` `; function ProfileImage({ profileImg }) { - const img = 프로필 사진; + const img = 프로필 사진; return profileImg ? ( {img} ) : ( diff --git a/src/components/text-field/dropdown-input/dropdown-input.jsx b/src/components/text-field/dropdown-input/dropdown-input.jsx index 5524bde..880b506 100644 --- a/src/components/text-field/dropdown-input/dropdown-input.jsx +++ b/src/components/text-field/dropdown-input/dropdown-input.jsx @@ -1,6 +1,6 @@ import styled from "styled-components"; -import arrowDownImg from "../../../assets/ic-chevron-down.svg"; -import arrowUpImg from "../../../assets/ic-chevron-up.svg"; +import arrowDownImage from "../../../assets/ic-chevron-down.svg"; +import arrowUpImage from "../../../assets/ic-chevron-up.svg"; import { useDropdown } from "../../../hooks/use-dropdown"; import INPUT_STYLES from "../input-styles"; import Dropdown from "./dropdown"; @@ -117,7 +117,7 @@ function DropdownInput({ Dropdown 화살표 diff --git a/src/components/toast/toast.jsx b/src/components/toast/toast.jsx index e24c6e6..9a276ea 100644 --- a/src/components/toast/toast.jsx +++ b/src/components/toast/toast.jsx @@ -1,6 +1,6 @@ import styled from "styled-components"; -import checkImg from "../../assets/ic-check-circle-green.svg"; -import closeImg from "../../assets/ic-xmark.svg"; +import checkImage from "../../assets/ic-check-circle-green.svg"; +import closeImage from "../../assets/ic-xmark.svg"; const StyledToast = styled.div` background-color: rgba(0, 0, 0, 0.8); @@ -60,11 +60,11 @@ function Toast({ message, onDismiss }) { return ( - 확인 + 확인

{message}

- 닫기 + 닫기
); diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index c254524..0ac405d 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -1,6 +1,6 @@ import { useState } from "react"; import styled from "styled-components"; -import smileAddImg from "../assets/ic-face-smile-add.svg"; +import smileAddImage from "../assets/ic-face-smile-add.svg"; import Badge from "../components/badge/badge"; import BADGE_TYPE from "../components/badge/badge-type"; import EmojiBadge from "../components/badge/emoji-badge"; @@ -44,11 +44,11 @@ function TestPage() { const handleToastClick = () => setShowsToast(true); const handleToastDismiss = () => setShowsToast(false); - + /* Modal */ const { showsModal, setShowsModal } = useModal(); const handleModalClick = () => setShowsModal(true); - + return (
- - - + + +
From fe6ec267f5733645baf78f6f38432db0f4fbda65 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Wed, 13 Aug 2025 17:53:24 +0900 Subject: [PATCH 067/253] =?UTF-8?q?refactor=20[]=20Test=20page=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=20=EA=B0=80=EC=9A=B4=EB=8D=B0=20=EC=A0=95=EB=A0=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Window size가 줄어들 때 dropdown type의 `TextField` component가 이동하는 경우 dropdown 위치가 갱신되지 않는 문제를 재현하기 위해 test page 수정 --- src/pages/test-page.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index c254524..6bc3594 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -44,18 +44,18 @@ function TestPage() { const handleToastClick = () => setShowsToast(true); const handleToastDismiss = () => setShowsToast(false); - + /* Modal */ const { showsModal, setShowsModal } = useModal(); const handleModalClick = () => setShowsModal(true); - + return (

🤯

From 49e7756cbb2a298eb345d1df4586ad01ecc1bcf6 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Wed, 13 Aug 2025 18:02:15 +0900 Subject: [PATCH 068/253] =?UTF-8?q?fix=20[#25]=20Window=20size=EA=B0=80=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=EB=90=A0=20=EB=95=8C=20dropdown=20layout?= =?UTF-8?q?=EC=9D=84=20=EC=83=88=EB=A1=9C=EC=9A=B4=20target=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=EC=97=90=20=EB=A7=9E=EA=B2=8C=20=EA=B0=B1=EC=8B=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/use-dropdown.jsx | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/hooks/use-dropdown.jsx b/src/hooks/use-dropdown.jsx index 16f1601..5a25cb6 100644 --- a/src/hooks/use-dropdown.jsx +++ b/src/hooks/use-dropdown.jsx @@ -1,4 +1,4 @@ -import { useContext, useRef, useState } from "react"; +import { useContext, useEffect, useRef, useState } from "react"; import DropdownContext from "../components/text-field/dropdown-input/dropdown-context"; function makeRect({ x, y, width } = { x: 0, y: 0, width: 0 }) { @@ -36,12 +36,27 @@ function useDropdown({ id, type }) { setDropdownState((prev) => ({ ...prev, [key]: shows })); }; + const updateDropdownLayout = (target) => { + const rect = calculateDropdownRect(target); + setDropdownRect(rect); + }; + const handleTargetClick = (shows) => { - const rect = calculateDropdownRect(targetRef.current); + updateDropdownLayout(targetRef.current); setShowsDropdown(shows); - setDropdownRect(rect); }; + useEffect(() => { + if (!showsDropdown) return; + + function handleWindowResize() { + updateDropdownLayout(targetRef.current); + } + + window.addEventListener("resize", handleWindowResize); + return () => window.removeEventListener("resize", handleWindowResize); + }, [showsDropdown, targetRef]); + return { targetRef, dropdownRect, From d663eea658a128812384430ecafb70228e5005bd Mon Sep 17 00:00:00 2001 From: luli Date: Wed, 13 Aug 2025 15:18:05 +0900 Subject: [PATCH 069/253] =?UTF-8?q?[#27]=20list=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=20styled-components=EB=A1=9C=20=EB=B3=80=EA=B2=BD,=20=EC=B9=B4?= =?UTF-8?q?=EB=93=9C=20arrow=EB=B2=84=ED=8A=BC=20=EA=B0=84=EB=8B=A8?= =?UTF-8?q?=ED=95=98=EA=B2=8C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit test데이터도 아직 완벽하게 테스트용은 아니고 단지 출력이 잘 되는지만 테스트할려고 뽑은거라서 아~~~주 간단하게만 해놓았습니다. --- src/pages/message-list.jsx | 266 ++++++++++++++++++++++--------------- 1 file changed, 156 insertions(+), 110 deletions(-) diff --git a/src/pages/message-list.jsx b/src/pages/message-list.jsx index 6cc97b3..1635722 100644 --- a/src/pages/message-list.jsx +++ b/src/pages/message-list.jsx @@ -10,128 +10,174 @@ import ToggleButton from "../components/button/toggle-button"; import React, { useEffect, useState } from "react"; import axiosInstance from "../api/axios-instance"; +import styled from "styled-components"; + +/* styled components */ +const TopContainer = styled.div` + text-align: center; +`; + +const CardSection = styled.section` + justify-self: center; +`; + +const CardTitle = styled.h2` + text-align: left; +`; + +const CardContainer = styled.div` + border: 1px solid red; + display: grid; + grid-template-columns: 275px 275px 275px 275px; + gap: 20px; + width: fit-content; + + position: relative; + overflow: visible; +`; + +const CardItem = styled.div` + width: 275px; + height: 260px; + border: 1px solid red; +`; + +const NextBtnWpr = styled.div` + position: absolute; + right: -20px; + top: 50%; + transform: translateY(-50%); + z-index: 10; +`; + +const PrevBtnWpr = styled.div` + position: absolute; + left: -20px; + top: 50%; + transform: translateY(-50%); + z-index: 10; +`; + +const MakingBtn = styled(PrimaryButton)` + margin-top: 64px; + font-weight: 400; + padding: 14px 60px; +`; + +/* 그냥 출력 테스트용 */ +const testData = [ + { id: 1, to: "test1", messageCount: 1 }, + { id: 2, to: "test2", messageCount: 5 }, + { id: 3, to: "test3", messageCount: 10 }, + { id: 4, to: "test4", messageCount: 2 }, + { id: 5, to: "test5", messageCount: 3 }, + { id: 6, to: "test6", messageCount: 1 }, +]; function ShowMessageList() { - // const [imageUrl, setImageUrl] = useState(null); + const [pprCurrentPage, setPprCurrentPage] = useState(0); // 인기카드 + const [currentPage, setCurrentPage] = useState(0); // 일반카드 + const [pprShowCards, setPprShowCards] = useState([]); + const [showCards, setShowCards] = useState([]); + const cardCount = 4; + + /* axios로 데이터 가져온다고 가정 */ + // axiosInstance + // .get("/18-3/recipients/?limit=5&offset=20") + // .then((res) => { + // console.log(res.data); + // }) + // .catch(console.error); + + const totalPages = Math.ceil(testData.length / cardCount); - const cardConStyle = { - border: "1px solid red", - display: "grid", - gridTemplateColumns: "275px 275px 275px 275px", - gap: "20px", - width: "fit-content", - - position: "relative", - overflow: "visible", - }; - - const cardStyle = { - width: "275px", - height: "260px", - border: "1px solid red", - }; - - const testStyle = { - textAlign: "center", - }; - - const sectionStyle = { - justifySelf: "center", - }; - - const buttonStyle = { - marginTop: "64px", - fontWeight: "400", - padding: "14px 60px", - }; - - const htStyle = { - textAlign: "left", - }; - - const rButton = { - position: "absolute", - right: -20, // 필요시 조정 - top: "50%", - transform: "translateY(-50%)", - zIndex: 20, + useEffect(() => { + const strtPageNum = currentPage * cardCount; + const endPageNum = strtPageNum + cardCount; + + const pprStrtPageNum = pprCurrentPage * cardCount; + const pprEndPageNum = pprStrtPageNum + cardCount; + + /* createdAt(생성된 시점)에 따라서 정렬 */ + setShowCards(testData.slice(strtPageNum, endPageNum)); + + /* 여기서 messageCount(메시지수)에 따라서 정렬 */ + setPprShowCards(testData.slice(pprStrtPageNum, pprEndPageNum)); + }, [pprCurrentPage, currentPage]); + + const nextPage = (mode = null) => { + if (mode) { + console.log("pprnext"); + if (pprCurrentPage < totalPages - 1) { + setPprCurrentPage((pprCurrentNum) => pprCurrentNum + 1); + } + } else { + console.log("justnext"); + if (currentPage < totalPages - 1) { + setCurrentPage((currentNum) => currentNum + 1); + } + } }; - const lButton = { - position: "absolute", - left: -20, // 필요시 조정 - top: "50%", - transform: "translateY(-50%)", - zIndex: 20, + const prevPage = (mode = null) => { + if (mode) { + console.log("pprprev"); + if (pprCurrentPage > 0) { + setPprCurrentPage((pprCurrentNum) => pprCurrentNum - 1); + } + } else { + console.log("justprev"); + if (currentPage > 0) { + setCurrentPage((currentNum) => currentNum - 1); + } + } }; - useEffect(() => { - axiosInstance - .get("/18-3/recipients/?limit=5&offset=20") - .then((res) => { - console.log(res.data); - }) - .catch(console.error); - }, []); - return ( -
+ /* navi 들어갈 자리 */
-
-

인기 롤링 페이퍼 🔥

-
-
-
-
-
-
- -
-
-
-
-

최근에 만든 롤링 페이퍼 ⭐

-
-
-
-
-
-
- -
-
-
+ + 인기 롤링 페이퍼 🔥 + + {pprShowCards.map((item) => ( + {item.to} // 테스트용 + ))} + {pprCurrentPage > 0 ? ( + prevPage("ppr")}> + + + ) : null} + {pprCurrentPage < totalPages - 1 ? ( + nextPage("ppr")}> + + + ) : null} + + + + + 최근에 만든 롤링 페이퍼 ⭐ + + {showCards.map((item) => ( + {item.to} // 테스트용 + ))} + {currentPage > 0 ? ( + prevPage()}> + + + ) : null} + {currentPage < totalPages - 1 ? ( + nextPage()}> + + + ) : null} + +
- -
+ + ); - - /* axios 사용 예시코드 */ - // useEffect(() => { - // axiosInstance - // .get("/background-images/") - // .then((res) => { - // if (res.data && res.data.imageUrls && res.data.imageUrls.length > 0) { - // setImageUrl(res.data.imageUrls[0]); - // } - // }) - // .catch(console.error); - // }, []); - - // return ( - //
- // {imageUrl ? ( - // background - // ) : ( - //

이미지를 불러오는 중입니다...

- // )} - //
- // ); } export default ShowMessageList; From 0df381e4268a9cfe9355261362b4bc9ab8e06871 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 14 Aug 2025 09:03:57 +0900 Subject: [PATCH 070/253] =?UTF-8?q?feat=20[#25]=20Modal=20container?= =?UTF-8?q?=EB=A5=BC=20fixed=20position=EC=9C=BC=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Scroll이 발생하더라도 fixed position이므로, scroll 하더라도 최초 화면 전체에 띄워진 위치가 고정된다. --- src/components/modal/modal.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/modal/modal.jsx b/src/components/modal/modal.jsx index d8b4aa2..6bedd32 100644 --- a/src/components/modal/modal.jsx +++ b/src/components/modal/modal.jsx @@ -168,7 +168,7 @@ const StyledModal = styled.div` /* Container */ const ModalContainer = styled.div` - position: absolute; + position: fixed; top: 0; left: 0; right: 0; From 5fddd685271664aff78fd88f31b66c8a0de2cadd Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 14 Aug 2025 13:49:05 +0900 Subject: [PATCH 071/253] =?UTF-8?q?feat=20[#36]=20Popover=20layer=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/index.html b/index.html index 80aec14..07a9876 100644 --- a/index.html +++ b/index.html @@ -16,6 +16,7 @@
+
From 04c43dc216d12ed9a6750dba6bc11acf6cda1289 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 14 Aug 2025 13:49:31 +0900 Subject: [PATCH 072/253] =?UTF-8?q?feat=20[#36]=20Popover=20=EC=A0=84?= =?UTF-8?q?=EC=97=AD=20=EC=83=81=ED=83=9C=EB=A5=BC=20=EA=B4=80=EB=A6=AC?= =?UTF-8?q?=ED=95=98=EB=8A=94=20context=20=EB=B0=8F=20provider=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.jsx | 5 ++++- src/components/popover/popover-context.js | 5 +++++ src/components/popover/popover-provider.jsx | 10 ++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 src/components/popover/popover-context.js create mode 100644 src/components/popover/popover-provider.jsx diff --git a/src/app.jsx b/src/app.jsx index d3303ef..0052846 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -1,5 +1,6 @@ import { BrowserRouter, Route, Routes } from "react-router"; import ModalProvider from "./components/modal/modal-provider"; +import PopoverProvider from "./components/popover/popover-provider"; import DropdownProvider from "./components/text-field/dropdown-input/dropdown-provider"; import ContentLayout from "./layouts/content-layout"; import OnboardingLayout from "./layouts/onboarding-layout"; @@ -13,7 +14,9 @@ import TestPage from "./pages/test-page"; function Provider({ children }) { return ( - {children} + + {children} + ); } diff --git a/src/components/popover/popover-context.js b/src/components/popover/popover-context.js new file mode 100644 index 0000000..06b8815 --- /dev/null +++ b/src/components/popover/popover-context.js @@ -0,0 +1,5 @@ +import { createContext } from "react"; + +const PopoverContext = createContext(); + +export default PopoverContext; diff --git a/src/components/popover/popover-provider.jsx b/src/components/popover/popover-provider.jsx new file mode 100644 index 0000000..4529615 --- /dev/null +++ b/src/components/popover/popover-provider.jsx @@ -0,0 +1,10 @@ +import { useState } from "react"; +import PopoverContext from "./popover-context"; + +function PopoverProvider({ children }) { + const [showsPopover, setShowsPopover] = useState(false); + const value = { showsPopover, setShowsPopover }; + return {children}; +} + +export default PopoverProvider; From a2c0d7fbc1ddf9cff54b7c91ba7252f8774ea80a Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 14 Aug 2025 13:50:44 +0900 Subject: [PATCH 073/253] =?UTF-8?q?feat=20[#36]=20Popover=EA=B0=80=20trigg?= =?UTF-8?q?er=20=EB=90=A0=20=EB=95=8C=20left/right=20alignment=EB=A1=9C=20?= =?UTF-8?q?popover=20=ED=91=9C=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/popover/popover-alignment.js | 6 +++ src/components/popover/popover.jsx | 39 ++++++++++++++++ src/hooks/use-popover.jsx | 49 +++++++++++++++++++++ src/pages/test-page.jsx | 49 +++++++++++++++++++-- 4 files changed, 140 insertions(+), 3 deletions(-) create mode 100644 src/components/popover/popover-alignment.js create mode 100644 src/components/popover/popover.jsx create mode 100644 src/hooks/use-popover.jsx diff --git a/src/components/popover/popover-alignment.js b/src/components/popover/popover-alignment.js new file mode 100644 index 0000000..a08fdf5 --- /dev/null +++ b/src/components/popover/popover-alignment.js @@ -0,0 +1,6 @@ +const POPOVER_ALIGNMENT = Object.freeze({ + left: "left", + right: "right", +}); + +export default POPOVER_ALIGNMENT; diff --git a/src/components/popover/popover.jsx b/src/components/popover/popover.jsx new file mode 100644 index 0000000..2258612 --- /dev/null +++ b/src/components/popover/popover.jsx @@ -0,0 +1,39 @@ +import { createPortal } from "react-dom"; +import styled from "styled-components"; + +const Container = styled.div` + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; +`; + +function PopoverPortal({ children }) { + return createPortal(children, document.getElementById("popover")); +} + +const StyledPopover = styled.div` + position: absolute; + top: ${({ $position }) => $position.top}px; + ${({ $position }) => ($position.left ? `left: ${$position.left}px` : "")}; + ${({ $position }) => ($position.right ? `right: ${$position.right}px` : "")}; + border-radius: 8px; + border: 1px solid #b6b6b6; + background-color: white; + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08); +`; + +function Popover({ isOpen, onClose, position, children }) { + return ( + isOpen && ( + + + {children} + + + ) + ); +} + +export default Popover; diff --git a/src/hooks/use-popover.jsx b/src/hooks/use-popover.jsx new file mode 100644 index 0000000..6efc314 --- /dev/null +++ b/src/hooks/use-popover.jsx @@ -0,0 +1,49 @@ +import { useContext, useState } from "react"; +import POPOVER_ALIGNMENT from "../components/popover/popover-alignment"; +import PopoverContext from "../components/popover/popover-context"; + +function calculatePopoverPosition(target, alignment) { + if (!target) { + return { top: 0, left: 0, right: 0 }; + } + + const targetRect = target.getBoundingClientRect(); + const position = { + top: targetRect.bottom + 8, + }; + + switch (alignment) { + case POPOVER_ALIGNMENT.right: + position.right = window.innerWidth - targetRect.right; + break; + default: + position.left = targetRect.left; + break; + } + + return position; +} + +function usePopover() { + const { showsPopover, setShowsPopover } = useContext(PopoverContext); + const [popoverPosition, setPopoverPosition] = useState(); + + const openPopopver = ({ target, alignment }) => { + const position = calculatePopoverPosition(target, alignment); + setShowsPopover(true); + setPopoverPosition(position); + }; + + const closePopover = () => { + setShowsPopover(false); + }; + + return { + popoverPosition, + showsPopover, + openPopopver, + closePopover, + }; +} + +export { usePopover }; diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index c254524..acbb892 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useRef, useState } from "react"; import styled from "styled-components"; import smileAddImg from "../assets/ic-face-smile-add.svg"; import Badge from "../components/badge/badge"; @@ -15,10 +15,13 @@ import BUTTON_SIZE from "../components/button/button-size"; import ToggleButton from "../components/button/toggle-button"; import Header from "../components/header/header"; import Modal from "../components/modal/modal"; +import Popover from "../components/popover/popover"; +import POPOVER_ALIGNMENT from "../components/popover/popover-alignment"; import TextField from "../components/text-field/text-field"; import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; import Toast from "../components/toast/toast"; import { useModal } from "../hooks/use-modal"; +import { usePopover } from "../hooks/use-popover"; import { useToast } from "../hooks/use-toast"; const OutlinedHeader = styled(Header)` @@ -44,11 +47,30 @@ function TestPage() { const handleToastClick = () => setShowsToast(true); const handleToastDismiss = () => setShowsToast(false); - + /* Modal */ const { showsModal, setShowsModal } = useModal(); const handleModalClick = () => setShowsModal(true); - + + /* Popover */ + const { popoverPosition, showsPopover, openPopopver, closePopover } = + usePopover(); + const popoverLeftRef = useRef(); + const popoverRightRef = useRef(); + + const handlePopoverLeftClick = () => { + openPopopver({ + target: popoverLeftRef.current, + alignment: POPOVER_ALIGNMENT.left, + }); + }; + const handlePopoverRightClick = () => { + openPopopver({ + target: popoverRightRef.current, + alignment: POPOVER_ALIGNMENT.right, + }); + }; + return (
)}
+
+ + + +

This is Popover.

+
+
); } From 0961f622afe80aed465ee3c3bef34d48338ef60d Mon Sep 17 00:00:00 2001 From: luli Date: Thu, 14 Aug 2025 14:35:00 +0900 Subject: [PATCH 074/253] =?UTF-8?q?Revert=20"[#27]=20list=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20styled-components=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD,=20=EC=B9=B4=EB=93=9C=20arrow=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EA=B0=84=EB=8B=A8=ED=95=98=EA=B2=8C=20=EA=B5=AC=ED=98=84"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit d663eea658a128812384430ecafb70228e5005bd. --- src/pages/message-list.jsx | 266 +++++++++++++++---------------------- 1 file changed, 110 insertions(+), 156 deletions(-) diff --git a/src/pages/message-list.jsx b/src/pages/message-list.jsx index 1635722..6cc97b3 100644 --- a/src/pages/message-list.jsx +++ b/src/pages/message-list.jsx @@ -10,174 +10,128 @@ import ToggleButton from "../components/button/toggle-button"; import React, { useEffect, useState } from "react"; import axiosInstance from "../api/axios-instance"; -import styled from "styled-components"; - -/* styled components */ -const TopContainer = styled.div` - text-align: center; -`; - -const CardSection = styled.section` - justify-self: center; -`; - -const CardTitle = styled.h2` - text-align: left; -`; - -const CardContainer = styled.div` - border: 1px solid red; - display: grid; - grid-template-columns: 275px 275px 275px 275px; - gap: 20px; - width: fit-content; - - position: relative; - overflow: visible; -`; - -const CardItem = styled.div` - width: 275px; - height: 260px; - border: 1px solid red; -`; - -const NextBtnWpr = styled.div` - position: absolute; - right: -20px; - top: 50%; - transform: translateY(-50%); - z-index: 10; -`; - -const PrevBtnWpr = styled.div` - position: absolute; - left: -20px; - top: 50%; - transform: translateY(-50%); - z-index: 10; -`; - -const MakingBtn = styled(PrimaryButton)` - margin-top: 64px; - font-weight: 400; - padding: 14px 60px; -`; - -/* 그냥 출력 테스트용 */ -const testData = [ - { id: 1, to: "test1", messageCount: 1 }, - { id: 2, to: "test2", messageCount: 5 }, - { id: 3, to: "test3", messageCount: 10 }, - { id: 4, to: "test4", messageCount: 2 }, - { id: 5, to: "test5", messageCount: 3 }, - { id: 6, to: "test6", messageCount: 1 }, -]; function ShowMessageList() { - const [pprCurrentPage, setPprCurrentPage] = useState(0); // 인기카드 - const [currentPage, setCurrentPage] = useState(0); // 일반카드 - const [pprShowCards, setPprShowCards] = useState([]); - const [showCards, setShowCards] = useState([]); - const cardCount = 4; - - /* axios로 데이터 가져온다고 가정 */ - // axiosInstance - // .get("/18-3/recipients/?limit=5&offset=20") - // .then((res) => { - // console.log(res.data); - // }) - // .catch(console.error); - - const totalPages = Math.ceil(testData.length / cardCount); + // const [imageUrl, setImageUrl] = useState(null); - useEffect(() => { - const strtPageNum = currentPage * cardCount; - const endPageNum = strtPageNum + cardCount; - - const pprStrtPageNum = pprCurrentPage * cardCount; - const pprEndPageNum = pprStrtPageNum + cardCount; - - /* createdAt(생성된 시점)에 따라서 정렬 */ - setShowCards(testData.slice(strtPageNum, endPageNum)); - - /* 여기서 messageCount(메시지수)에 따라서 정렬 */ - setPprShowCards(testData.slice(pprStrtPageNum, pprEndPageNum)); - }, [pprCurrentPage, currentPage]); - - const nextPage = (mode = null) => { - if (mode) { - console.log("pprnext"); - if (pprCurrentPage < totalPages - 1) { - setPprCurrentPage((pprCurrentNum) => pprCurrentNum + 1); - } - } else { - console.log("justnext"); - if (currentPage < totalPages - 1) { - setCurrentPage((currentNum) => currentNum + 1); - } - } + const cardConStyle = { + border: "1px solid red", + display: "grid", + gridTemplateColumns: "275px 275px 275px 275px", + gap: "20px", + width: "fit-content", + + position: "relative", + overflow: "visible", }; - const prevPage = (mode = null) => { - if (mode) { - console.log("pprprev"); - if (pprCurrentPage > 0) { - setPprCurrentPage((pprCurrentNum) => pprCurrentNum - 1); - } - } else { - console.log("justprev"); - if (currentPage > 0) { - setCurrentPage((currentNum) => currentNum - 1); - } - } + const cardStyle = { + width: "275px", + height: "260px", + border: "1px solid red", }; + const testStyle = { + textAlign: "center", + }; + + const sectionStyle = { + justifySelf: "center", + }; + + const buttonStyle = { + marginTop: "64px", + fontWeight: "400", + padding: "14px 60px", + }; + + const htStyle = { + textAlign: "left", + }; + + const rButton = { + position: "absolute", + right: -20, // 필요시 조정 + top: "50%", + transform: "translateY(-50%)", + zIndex: 20, + }; + + const lButton = { + position: "absolute", + left: -20, // 필요시 조정 + top: "50%", + transform: "translateY(-50%)", + zIndex: 20, + }; + + useEffect(() => { + axiosInstance + .get("/18-3/recipients/?limit=5&offset=20") + .then((res) => { + console.log(res.data); + }) + .catch(console.error); + }, []); + return ( - +
/* navi 들어갈 자리 */
- - 인기 롤링 페이퍼 🔥 - - {pprShowCards.map((item) => ( - {item.to} // 테스트용 - ))} - {pprCurrentPage > 0 ? ( - prevPage("ppr")}> - - - ) : null} - {pprCurrentPage < totalPages - 1 ? ( - nextPage("ppr")}> - - - ) : null} - - - - - 최근에 만든 롤링 페이퍼 ⭐ - - {showCards.map((item) => ( - {item.to} // 테스트용 - ))} - {currentPage > 0 ? ( - prevPage()}> - - - ) : null} - {currentPage < totalPages - 1 ? ( - nextPage()}> - - - ) : null} - - +
+

인기 롤링 페이퍼 🔥

+
+
+
+
+
+
+ +
+
+
+
+

최근에 만든 롤링 페이퍼 ⭐

+
+
+
+
+
+
+ +
+
+
- - + +
); + + /* axios 사용 예시코드 */ + // useEffect(() => { + // axiosInstance + // .get("/background-images/") + // .then((res) => { + // if (res.data && res.data.imageUrls && res.data.imageUrls.length > 0) { + // setImageUrl(res.data.imageUrls[0]); + // } + // }) + // .catch(console.error); + // }, []); + + // return ( + //
+ // {imageUrl ? ( + // background + // ) : ( + //

이미지를 불러오는 중입니다...

+ // )} + //
+ // ); } export default ShowMessageList; From d35aaaff4a9cfaa9eb7358bb12d665d2a2a02eef Mon Sep 17 00:00:00 2001 From: luli Date: Thu, 14 Aug 2025 14:37:55 +0900 Subject: [PATCH 075/253] =?UTF-8?q?[#27]=20pr=EC=88=98=EC=A0=95=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EC=A0=81=EC=9A=A9,=20freatures=EA=B2=BD=EB=A1=9C?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pr수정사항 적용하였고, 페이지랑 내부 컴포넌트 분리할 src\features\rolling-paper\components 파일경로 추가하였습니다. --- src/app.jsx | 2 +- .../components/rolling-paper-list.jsx | 0 src/pages/rolling-paper-list-page.jsx | 271 + src/pages/test_recipients_data.json | 17227 ++++++++++++++++ 4 files changed, 17499 insertions(+), 1 deletion(-) create mode 100644 src/features/rolling-paper/components/rolling-paper-list.jsx create mode 100644 src/pages/rolling-paper-list-page.jsx create mode 100644 src/pages/test_recipients_data.json diff --git a/src/app.jsx b/src/app.jsx index d3303ef..486acd6 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -5,7 +5,7 @@ import ContentLayout from "./layouts/content-layout"; import OnboardingLayout from "./layouts/onboarding-layout"; import CreatePostPage from "./pages/create-post-page"; import MainPage from "./pages/main-page"; -import MessagePage from "./pages/message-list"; +import MessagePage from "./pages/rolling-paper-list-page"; import RecipientPostPage from "./pages/recipient-post-page"; import SendMessagePage from "./pages/send-message-page"; import TestPage from "./pages/test-page"; diff --git a/src/features/rolling-paper/components/rolling-paper-list.jsx b/src/features/rolling-paper/components/rolling-paper-list.jsx new file mode 100644 index 0000000..e69de29 diff --git a/src/pages/rolling-paper-list-page.jsx b/src/pages/rolling-paper-list-page.jsx new file mode 100644 index 0000000..8812315 --- /dev/null +++ b/src/pages/rolling-paper-list-page.jsx @@ -0,0 +1,271 @@ +import ArrowButton from "../components/button/arrow-button"; +import ARROW_BUTTON_DIRECTION from "../components/button/arrow-button-direction"; +import { + OutlinedButton, + PrimaryButton, + SecondaryButton, +} from "../components/button/button"; +import BUTTON_SIZE from "../components/button/button-size"; +import ToggleButton from "../components/button/toggle-button"; + +import React, { useEffect, useState } from "react"; +import axiosInstance from "../api/axios-instance"; +import testDataFile from "./test_recipients_data.json"; + +import styled from "styled-components"; + +const backgroundColors = { + beige: "#FFD382", + purple: "#DCB9FF", + green: "#9BE282", + blue: "#9DDDFF", +}; + +const TopContainer = styled.div` + text-align: center; +`; + +const CardSection = styled.section` + justify-self: center; +`; + +const CardTitle = styled.h2` + text-align: left; +`; + +const CardContainer = styled.div` + border: 1px solid red; + display: grid; + grid-template-columns: 275px 275px 275px 275px; + gap: 20px; + width: fit-content; + + position: relative; + overflow: visible; +`; + +const CardItem = styled.div` + width: 275px; + height: 260px; + border: 1px solid red; + text-align: left; + padding: 30px 24px 20px 24px; + + display: grid; + grid-template-rows: 1fr 1fr auto; + + background-color: ${(props) => + backgroundColors[props.backgroundColor] || "white"}; + + img { + height: 28px; + width: 28px; + border-radius: 50%; + border: 1px solid #ffffff; + + margin-left: -12px; + &:first-child { + margin-left: 0; + } + } + + div.message-images { + display: flex; + } + + div.over-profile { + height: 28px; + width: 28px; + background-color: #ffffff; + border-radius: 50%; + + margin-left: -12px; + + display: flex; + justify-content: center; + align-items: center; + font-size: 12px; + } + + h2 { + margin: 0; + } + + div.emoji-div { + border-top: 1px solid red; + } +`; + +const NextBtnWpr = styled.div` + position: absolute; + right: -20px; + top: 50%; + transform: translateY(-50%); + z-index: 10; +`; + +const PrevBtnWpr = styled.div` + position: absolute; + left: -20px; + top: 50%; + transform: translateY(-50%); + z-index: 10; +`; + +const MakingBtn = styled(PrimaryButton)` + margin-top: 64px; + font-weight: 400; + padding: 14px 60px; +`; + +function ShowMessageList() { + const [testData, setTestData] = useState([]); + const [popularCurrentPage, setPopularCurrentPage] = useState(0); + const [recentCurrentPage, setRecentCurrentPage] = useState(0); + const [popularrecentShowCards, setPopularrecentShowCards] = useState([]); + const [recentShowCards, setRecentShowCards] = useState([]); + const cardCount = 4; + + useEffect(() => { + setTestData(testDataFile); + // axiosInstance + // .get("/18-3/recipients/?limit=5&offset=20") + // .then((res) => { + // setTestData(res.data); + // console.log(res.data); + // }) + // .catch((err) => { + // console.error("오류:", err); + // }); + }, []); + + const totalPages = Math.ceil(testData.length / cardCount); + + useEffect(() => { + const startPageNum = recentCurrentPage * cardCount; + const endPageNum = startPageNum + cardCount; + + const popularStartPageNum = popularCurrentPage * cardCount; + const popularEndPageNum = popularStartPageNum + cardCount; + + /* createdAt(생성된 시점)에 따라서 정렬 */ + setRecentShowCards(testData.slice(startPageNum, endPageNum)); + + /* 여기서 messageCount(메시지수)에 따라서 정렬 */ + setPopularrecentShowCards( + testData.slice(popularStartPageNum, popularEndPageNum) + ); + }, [popularCurrentPage, recentCurrentPage, testData]); + + const nextPage = (mode) => { + if (mode) { + if (popularCurrentPage < totalPages - 1) { + setPopularCurrentPage((pprCurrentNum) => pprCurrentNum + 1); + } + } else { + if (recentCurrentPage < totalPages - 1) { + setRecentCurrentPage((currentNum) => currentNum + 1); + } + } + }; + + const prevPage = (mode) => { + if (mode) { + if (popularCurrentPage > 0) { + setPopularCurrentPage((pprCurrentNum) => pprCurrentNum - 1); + } + } else { + if (recentCurrentPage > 0) { + setRecentCurrentPage((currentNum) => currentNum - 1); + } + } + }; + + return ( + +
+ + 인기 롤링 페이퍼 🔥 + + {popularrecentShowCards.map((item) => ( + +

To. {item.name}

+
+ {item.recentMessages.slice(0, 3).map((messageItem, index) => ( + {`profile-${index}`} + ))} + {item.messageCount > 3 ? ( +
+ +{item.messageCount - 3} +
+ ) : null} +
+ + {item.messageCount}명이 작성했어요! + +
test
+
+ ))} + {popularCurrentPage > 0 ? ( + prevPage("ppr")}> + + + ) : null} + {popularCurrentPage < totalPages - 1 ? ( + nextPage("ppr")}> + + + ) : null} +
+
+ + + 최근에 만든 롤링 페이퍼 ⭐ + + {recentShowCards.map((item) => ( + +

To. {item.name}

+
+ {item.recentMessages.slice(0, 3).map((messageItem, index) => ( + {`profile-${index}`} + ))} + {item.messageCount > 3 ? ( +
+ +{item.messageCount - 3} +
+ ) : null} +
+ + {item.messageCount}명이 작성했어요! + +
+ ))} + {recentCurrentPage > 0 ? ( + prevPage()}> + + + ) : null} + {recentCurrentPage < totalPages - 1 ? ( + nextPage()}> + + + ) : null} +
+
+
+ +
+ ); +} + +export default ShowMessageList; diff --git a/src/pages/test_recipients_data.json b/src/pages/test_recipients_data.json new file mode 100644 index 0000000..3111f67 --- /dev/null +++ b/src/pages/test_recipients_data.json @@ -0,0 +1,17227 @@ +[ + { + "id": 7024, + "name": "이병헌", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-10-22T19:15:11Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 90163, + "recipientId": 7024, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/142/200/200", + "relationship": "친구", + "content": "김하은님의 메세지 내용 50", + "font": "Roboto", + "createdAt": "2023-08-18T21:20:29Z" + }, + { + "id": 90164, + "recipientId": 7024, + "sender": "강동원", + "profileImageURL": "https://picsum.photos/id/142/200/200", + "relationship": "친구", + "content": "강동원님의 메세지 내용 50", + "font": "Roboto", + "createdAt": "2023-08-19T21:20:29Z" + }, + { + "id": 90165, + "recipientId": 7024, + "sender": "고수", + "profileImageURL": "https://picsum.photos/id/142/200/200", + "relationship": "친구", + "content": "고수님의 메세지 내용 50", + "font": "Roboto", + "createdAt": "2023-08-20T21:20:29Z" + } + ], + "reactionCount": 77, + "topReactions": [ + { + "id": 78000, + "emoji": "😁", + "count": 6 + }, + { + "id": 70479, + "emoji": "🥹", + "count": 15 + }, + { + "id": 32001, + "emoji": "😁", + "count": 5 + }, + { + "id": 25196, + "emoji": "🥹", + "count": 18 + }, + { + "id": 15685, + "emoji": "🥹", + "count": 2 + } + ] + }, + { + "id": 71200, + "name": "박서준", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/71200/600/400", + "createdAt": "2023-01-03T05:35:33Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 42811, + "recipientId": 71200, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/435/200/200", + "relationship": "가족", + "content": "현빈님의 메세지 내용 25", + "font": "Roboto", + "createdAt": "2023-06-23T06:13:02Z" + }, + { + "id": 32677, + "recipientId": 71200, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/435/200/200", + "relationship": "지인", + "content": "정우성님의 메세지 내용 28", + "font": "Roboto", + "createdAt": "2023-01-27T19:16:37Z" + }, + { + "id": 19164, + "recipientId": 71200, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/54/200/200", + "relationship": "동료", + "content": "송혜교님의 메세지 내용 73", + "font": "Nanum Gothic", + "createdAt": "2024-01-13T10:43:25Z" + } + ], + "reactionCount": 66, + "topReactions": [ + { + "id": 84284, + "emoji": "🥹", + "count": 4 + }, + { + "id": 67905, + "emoji": "😁", + "count": 2 + }, + { + "id": 19092, + "emoji": "👍", + "count": 4 + }, + { + "id": 62998, + "emoji": "😁", + "count": 5 + }, + { + "id": 49907, + "emoji": "🥹", + "count": 10 + }, + { + "id": 306, + "emoji": "🥹", + "count": 3 + } + ] + }, + { + "id": 43558, + "name": "현빈", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-12-11T02:38:21Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 30238, + "recipientId": 43558, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/340/200/200", + "relationship": "가족", + "content": "이병헌님의 메세지 내용 32", + "font": "Nanum Gothic", + "createdAt": "2023-06-17T00:31:29Z" + }, + { + "id": 87763, + "recipientId": 43558, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/259/200/200", + "relationship": "동료", + "content": "정우성님의 메세지 내용 96", + "font": "Pretendard", + "createdAt": "2023-08-07T07:41:19Z" + }, + { + "id": 67784, + "recipientId": 43558, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/300/200/200", + "relationship": "지인", + "content": "이영준님의 메세지 내용 73", + "font": "Nanum Gothic", + "createdAt": "2024-01-17T09:44:31Z" + } + ], + "reactionCount": 13, + "topReactions": [ + { + "id": 84326, + "emoji": "😀", + "count": 13 + }, + { + "id": 29537, + "emoji": "🥹", + "count": 2 + }, + { + "id": 78412, + "emoji": "😁", + "count": 4 + }, + { + "id": 91457, + "emoji": "🎉", + "count": 6 + }, + { + "id": 50902, + "emoji": "🥹", + "count": 7 + }, + { + "id": 5434, + "emoji": "🥹", + "count": 14 + } + ] + }, + { + "id": 90454, + "name": "김하은", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/90454/600/400", + "createdAt": "2023-01-25T17:12:55Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 3505, + "recipientId": 90454, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/239/200/200", + "relationship": "가족", + "content": "박서준님의 메세지 내용 17", + "font": "Nanum Gothic", + "createdAt": "2023-06-17T18:32:49Z" + }, + { + "id": 38476, + "recipientId": 90454, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/13/200/200", + "relationship": "지인", + "content": "박서준님의 메세지 내용 89", + "font": "Pretendard", + "createdAt": "2023-01-20T02:06:16Z" + } + ], + "reactionCount": 84, + "topReactions": [ + { + "id": 605, + "emoji": "🥹", + "count": 14 + }, + { + "id": 90894, + "emoji": "🥹", + "count": 3 + }, + { + "id": 26499, + "emoji": "🥹", + "count": 5 + } + ] + }, + { + "id": 18499, + "name": "이병헌", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/18499/600/400", + "createdAt": "2023-06-03T04:15:47Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 48979, + "recipientId": 18499, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/11/200/200", + "relationship": "지인", + "content": "이병헌님의 메세지 내용 77", + "font": "Nanum Gothic", + "createdAt": "2023-08-25T00:15:25Z" + }, + { + "id": 99385, + "recipientId": 18499, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/287/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 15", + "font": "Pretendard", + "createdAt": "2023-10-12T13:55:45Z" + }, + { + "id": 35753, + "recipientId": 18499, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/173/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 67", + "font": "Nanum Gothic", + "createdAt": "2023-07-23T23:14:30Z" + } + ], + "reactionCount": 61, + "topReactions": [ + { + "id": 84545, + "emoji": "👍", + "count": 2 + }, + { + "id": 91678, + "emoji": "❤️", + "count": 10 + }, + { + "id": 13771, + "emoji": "😀", + "count": 20 + }, + { + "id": 45654, + "emoji": "❤️", + "count": 2 + }, + { + "id": 97554, + "emoji": "🥹", + "count": 6 + }, + { + "id": 78344, + "emoji": "👍", + "count": 1 + } + ] + }, + { + "id": 84206, + "name": "정우성", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-11-30T22:40:21Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 5762, + "recipientId": 84206, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/474/200/200", + "relationship": "동료", + "content": "전지현님의 메세지 내용 31", + "font": "Pretendard", + "createdAt": "2023-04-24T12:23:57Z" + }, + { + "id": 45324, + "recipientId": 84206, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/264/200/200", + "relationship": "지인", + "content": "한지민님의 메세지 내용 84", + "font": "Pretendard", + "createdAt": "2023-09-30T14:29:23Z" + }, + { + "id": 14049, + "recipientId": 84206, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/406/200/200", + "relationship": "친구", + "content": "현빈님의 메세지 내용 15", + "font": "Noto Sans", + "createdAt": "2023-04-15T06:15:06Z" + } + ], + "reactionCount": 14, + "topReactions": [ + { + "id": 5423, + "emoji": "😁", + "count": 19 + }, + { + "id": 694, + "emoji": "😀", + "count": 2 + }, + { + "id": 2845, + "emoji": "🥹", + "count": 13 + }, + { + "id": 90938, + "emoji": "🥹", + "count": 19 + } + ] + }, + { + "id": 97449, + "name": "송혜교", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-05-27T18:06:58Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 64517, + "recipientId": 97449, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/180/200/200", + "relationship": "지인", + "content": "현빈님의 메세지 내용 39", + "font": "Roboto", + "createdAt": "2023-03-11T02:20:57Z" + }, + { + "id": 95376, + "recipientId": 97449, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/443/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 29", + "font": "Nanum Gothic", + "createdAt": "2023-03-18T20:25:35Z" + }, + { + "id": 7602, + "recipientId": 97449, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/18/200/200", + "relationship": "동료", + "content": "이영준님의 메세지 내용 57", + "font": "Roboto", + "createdAt": "2023-12-04T21:16:03Z" + } + ], + "reactionCount": 87, + "topReactions": [ + { + "id": 71912, + "emoji": "😀", + "count": 1 + }, + { + "id": 53543, + "emoji": "❤️", + "count": 12 + }, + { + "id": 90369, + "emoji": "😀", + "count": 11 + }, + { + "id": 65448, + "emoji": "😁", + "count": 17 + }, + { + "id": 96672, + "emoji": "👍", + "count": 15 + } + ] + }, + { + "id": 13425, + "name": "이병헌", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/13425/600/400", + "createdAt": "2023-07-06T20:30:52Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 74302, + "recipientId": 13425, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/244/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 69", + "font": "Pretendard", + "createdAt": "2023-04-09T12:19:23Z" + } + ], + "reactionCount": 33, + "topReactions": [ + { + "id": 78114, + "emoji": "😁", + "count": 5 + }, + { + "id": 46240, + "emoji": "👍", + "count": 10 + }, + { + "id": 3995, + "emoji": "❤️", + "count": 7 + }, + { + "id": 47582, + "emoji": "👍", + "count": 11 + } + ] + }, + { + "id": 35155, + "name": "박서준", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-05-11T22:06:17Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 34211, + "recipientId": 35155, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/477/200/200", + "relationship": "지인", + "content": "전지현님의 메세지 내용 43", + "font": "Noto Sans", + "createdAt": "2024-01-05T06:58:56Z" + }, + { + "id": 60206, + "recipientId": 35155, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/343/200/200", + "relationship": "친구", + "content": "최민수님의 메세지 내용 54", + "font": "Roboto", + "createdAt": "2023-03-30T16:06:27Z" + }, + { + "id": 88132, + "recipientId": 35155, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/325/200/200", + "relationship": "동료", + "content": "정우성님의 메세지 내용 68", + "font": "Noto Sans", + "createdAt": "2023-08-09T19:25:45Z" + } + ], + "reactionCount": 61, + "topReactions": [ + { + "id": 58872, + "emoji": "🥹", + "count": 13 + } + ] + }, + { + "id": 97436, + "name": "정우성", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/97436/600/400", + "createdAt": "2023-10-03T12:44:17Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 34424, + "recipientId": 97436, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/141/200/200", + "relationship": "지인", + "content": "이병헌님의 메세지 내용 6", + "font": "Nanum Gothic", + "createdAt": "2023-06-01T12:35:35Z" + }, + { + "id": 41272, + "recipientId": 97436, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/162/200/200", + "relationship": "가족", + "content": "한지민님의 메세지 내용 19", + "font": "Roboto", + "createdAt": "2023-05-07T04:01:58Z" + }, + { + "id": 36494, + "recipientId": 97436, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/307/200/200", + "relationship": "친구", + "content": "박서준님의 메세지 내용 71", + "font": "Noto Sans", + "createdAt": "2023-07-14T08:50:29Z" + } + ], + "reactionCount": 61, + "topReactions": [ + { + "id": 34505, + "emoji": "😀", + "count": 2 + }, + { + "id": 97779, + "emoji": "😁", + "count": 14 + }, + { + "id": 64296, + "emoji": "🥹", + "count": 17 + } + ] + }, + { + "id": 22932, + "name": "이병헌", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/22932/600/400", + "createdAt": "2023-12-21T05:29:02Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 5965, + "recipientId": 22932, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/368/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 41", + "font": "Roboto", + "createdAt": "2023-10-30T21:49:17Z" + } + ], + "reactionCount": 54, + "topReactions": [ + { + "id": 80894, + "emoji": "👍", + "count": 6 + } + ] + }, + { + "id": 93316, + "name": "전지현", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-09-26T09:48:47Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 15981, + "recipientId": 93316, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/29/200/200", + "relationship": "동료", + "content": "송혜교님의 메세지 내용 23", + "font": "Nanum Gothic", + "createdAt": "2023-07-01T10:41:23Z" + }, + { + "id": 88647, + "recipientId": 93316, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/391/200/200", + "relationship": "가족", + "content": "이영준님의 메세지 내용 91", + "font": "Pretendard", + "createdAt": "2023-09-23T14:40:50Z" + }, + { + "id": 36796, + "recipientId": 93316, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/485/200/200", + "relationship": "지인", + "content": "송혜교님의 메세지 내용 69", + "font": "Nanum Gothic", + "createdAt": "2023-08-22T23:41:19Z" + } + ], + "reactionCount": 67, + "topReactions": [ + { + "id": 20683, + "emoji": "😁", + "count": 7 + }, + { + "id": 55812, + "emoji": "❤️", + "count": 8 + } + ] + }, + { + "id": 25223, + "name": "전지현", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-12-10T04:25:18Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 55898, + "recipientId": 25223, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/377/200/200", + "relationship": "동료", + "content": "이영준님의 메세지 내용 97", + "font": "Pretendard", + "createdAt": "2023-03-28T00:32:15Z" + }, + { + "id": 28874, + "recipientId": 25223, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/338/200/200", + "relationship": "동료", + "content": "최민수님의 메세지 내용 71", + "font": "Roboto", + "createdAt": "2023-08-06T08:16:58Z" + }, + { + "id": 21132, + "recipientId": 25223, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/259/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 53", + "font": "Noto Sans", + "createdAt": "2024-02-01T12:33:31Z" + } + ], + "reactionCount": 29, + "topReactions": [ + { + "id": 60975, + "emoji": "🎉", + "count": 16 + }, + { + "id": 94228, + "emoji": "🎉", + "count": 12 + } + ] + }, + { + "id": 2194, + "name": "송혜교", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-10-16T00:02:43Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 97432, + "recipientId": 2194, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/140/200/200", + "relationship": "가족", + "content": "전지현님의 메세지 내용 42", + "font": "Pretendard", + "createdAt": "2023-02-14T20:58:12Z" + }, + { + "id": 57885, + "recipientId": 2194, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/496/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 39", + "font": "Roboto", + "createdAt": "2023-10-19T16:47:29Z" + }, + { + "id": 88963, + "recipientId": 2194, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/317/200/200", + "relationship": "가족", + "content": "이병헌님의 메세지 내용 81", + "font": "Nanum Gothic", + "createdAt": "2023-03-12T08:38:10Z" + } + ], + "reactionCount": 32, + "topReactions": [ + { + "id": 60382, + "emoji": "🎉", + "count": 14 + }, + { + "id": 35188, + "emoji": "😁", + "count": 16 + }, + { + "id": 36631, + "emoji": "😁", + "count": 7 + }, + { + "id": 42371, + "emoji": "❤️", + "count": 9 + }, + { + "id": 49401, + "emoji": "🥹", + "count": 14 + }, + { + "id": 62636, + "emoji": "😀", + "count": 4 + } + ] + }, + { + "id": 93426, + "name": "박서준", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-10-25T18:47:40Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 59310, + "recipientId": 93426, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/148/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 64", + "font": "Nanum Gothic", + "createdAt": "2023-12-24T10:04:46Z" + }, + { + "id": 91544, + "recipientId": 93426, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/153/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 79", + "font": "Noto Sans", + "createdAt": "2023-08-13T10:48:12Z" + }, + { + "id": 56708, + "recipientId": 93426, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/55/200/200", + "relationship": "친구", + "content": "현빈님의 메세지 내용 32", + "font": "Noto Sans", + "createdAt": "2023-01-27T22:18:54Z" + } + ], + "reactionCount": 3, + "topReactions": [ + { + "id": 75158, + "emoji": "😁", + "count": 16 + }, + { + "id": 91157, + "emoji": "👍", + "count": 1 + }, + { + "id": 62992, + "emoji": "👍", + "count": 5 + }, + { + "id": 36793, + "emoji": "😀", + "count": 11 + }, + { + "id": 47139, + "emoji": "👍", + "count": 18 + } + ] + }, + { + "id": 6785, + "name": "현빈", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/6785/600/400", + "createdAt": "2023-08-05T10:49:34Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 96256, + "recipientId": 6785, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/487/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 14", + "font": "Nanum Gothic", + "createdAt": "2023-08-05T11:24:48Z" + }, + { + "id": 95988, + "recipientId": 6785, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/123/200/200", + "relationship": "동료", + "content": "현빈님의 메세지 내용 78", + "font": "Pretendard", + "createdAt": "2023-05-16T00:54:03Z" + }, + { + "id": 85410, + "recipientId": 6785, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/85/200/200", + "relationship": "동료", + "content": "한지민님의 메세지 내용 45", + "font": "Roboto", + "createdAt": "2023-09-22T09:06:14Z" + } + ], + "reactionCount": 18, + "topReactions": [ + { + "id": 88345, + "emoji": "😀", + "count": 17 + } + ] + }, + { + "id": 70576, + "name": "정우성", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2024-01-24T03:10:15Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 5439, + "recipientId": 70576, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/172/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 41", + "font": "Roboto", + "createdAt": "2023-04-08T06:16:02Z" + } + ], + "reactionCount": 86, + "topReactions": [ + { + "id": 61646, + "emoji": "😁", + "count": 6 + }, + { + "id": 36266, + "emoji": "🎉", + "count": 11 + }, + { + "id": 19739, + "emoji": "🎉", + "count": 19 + }, + { + "id": 49081, + "emoji": "🎉", + "count": 7 + }, + { + "id": 60907, + "emoji": "👍", + "count": 11 + }, + { + "id": 82566, + "emoji": "❤️", + "count": 14 + } + ] + }, + { + "id": 45901, + "name": "이병헌", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-06-14T15:34:31Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 38672, + "recipientId": 45901, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/444/200/200", + "relationship": "동료", + "content": "이영준님의 메세지 내용 57", + "font": "Pretendard", + "createdAt": "2023-08-25T13:09:41Z" + }, + { + "id": 36570, + "recipientId": 45901, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/26/200/200", + "relationship": "지인", + "content": "전지현님의 메세지 내용 24", + "font": "Noto Sans", + "createdAt": "2023-08-23T03:39:28Z" + }, + { + "id": 62649, + "recipientId": 45901, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/332/200/200", + "relationship": "가족", + "content": "이영준님의 메세지 내용 79", + "font": "Noto Sans", + "createdAt": "2023-01-07T13:25:26Z" + } + ], + "reactionCount": 15, + "topReactions": [ + { + "id": 32010, + "emoji": "❤️", + "count": 20 + }, + { + "id": 25614, + "emoji": "❤️", + "count": 18 + }, + { + "id": 44236, + "emoji": "😁", + "count": 5 + }, + { + "id": 26955, + "emoji": "❤️", + "count": 12 + }, + { + "id": 68249, + "emoji": "😁", + "count": 9 + } + ] + }, + { + "id": 11943, + "name": "한지민", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-12-25T19:30:42Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 48559, + "recipientId": 11943, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/96/200/200", + "relationship": "지인", + "content": "정우성님의 메세지 내용 96", + "font": "Pretendard", + "createdAt": "2023-12-20T03:53:10Z" + } + ], + "reactionCount": 17, + "topReactions": [ + { + "id": 38691, + "emoji": "🎉", + "count": 14 + }, + { + "id": 74561, + "emoji": "😁", + "count": 16 + }, + { + "id": 67482, + "emoji": "🥹", + "count": 11 + }, + { + "id": 77948, + "emoji": "😀", + "count": 5 + } + ] + }, + { + "id": 72748, + "name": "전지현", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2024-01-18T06:23:22Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 70819, + "recipientId": 72748, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/178/200/200", + "relationship": "동료", + "content": "현빈님의 메세지 내용 32", + "font": "Pretendard", + "createdAt": "2023-11-07T20:19:02Z" + }, + { + "id": 26784, + "recipientId": 72748, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/400/200/200", + "relationship": "친구", + "content": "김하은님의 메세지 내용 61", + "font": "Nanum Gothic", + "createdAt": "2023-10-23T08:44:07Z" + } + ], + "reactionCount": 36, + "topReactions": [ + { + "id": 41246, + "emoji": "😀", + "count": 3 + }, + { + "id": 91855, + "emoji": "❤️", + "count": 17 + }, + { + "id": 88660, + "emoji": "🎉", + "count": 1 + }, + { + "id": 98907, + "emoji": "❤️", + "count": 15 + } + ] + }, + { + "id": 84532, + "name": "김하은", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-11-26T12:07:49Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 99518, + "recipientId": 84532, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/2/200/200", + "relationship": "가족", + "content": "이병헌님의 메세지 내용 83", + "font": "Nanum Gothic", + "createdAt": "2023-07-12T22:08:05Z" + }, + { + "id": 26554, + "recipientId": 84532, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/411/200/200", + "relationship": "가족", + "content": "정우성님의 메세지 내용 100", + "font": "Nanum Gothic", + "createdAt": "2023-12-14T17:02:19Z" + }, + { + "id": 70782, + "recipientId": 84532, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/179/200/200", + "relationship": "친구", + "content": "김하은님의 메세지 내용 92", + "font": "Pretendard", + "createdAt": "2023-04-05T09:48:12Z" + } + ], + "reactionCount": 27, + "topReactions": [ + { + "id": 24529, + "emoji": "🥹", + "count": 15 + }, + { + "id": 72262, + "emoji": "😀", + "count": 20 + }, + { + "id": 85359, + "emoji": "🎉", + "count": 16 + } + ] + }, + { + "id": 85839, + "name": "최민수", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/85839/600/400", + "createdAt": "2023-12-24T00:08:48Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 30831, + "recipientId": 85839, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/384/200/200", + "relationship": "지인", + "content": "송혜교님의 메세지 내용 43", + "font": "Nanum Gothic", + "createdAt": "2023-09-07T15:08:29Z" + }, + { + "id": 12285, + "recipientId": 85839, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/85/200/200", + "relationship": "친구", + "content": "현빈님의 메세지 내용 3", + "font": "Nanum Gothic", + "createdAt": "2023-04-02T09:00:54Z" + }, + { + "id": 72173, + "recipientId": 85839, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/137/200/200", + "relationship": "동료", + "content": "이병헌님의 메세지 내용 84", + "font": "Pretendard", + "createdAt": "2023-04-01T12:40:19Z" + } + ], + "reactionCount": 77, + "topReactions": [ + { + "id": 89993, + "emoji": "❤️", + "count": 5 + }, + { + "id": 92268, + "emoji": "👍", + "count": 18 + }, + { + "id": 77791, + "emoji": "🎉", + "count": 15 + }, + { + "id": 34959, + "emoji": "🥹", + "count": 11 + }, + { + "id": 7685, + "emoji": "😀", + "count": 10 + }, + { + "id": 34844, + "emoji": "👍", + "count": 14 + } + ] + }, + { + "id": 34462, + "name": "최민수", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/34462/600/400", + "createdAt": "2023-05-09T05:20:10Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 94727, + "recipientId": 34462, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/495/200/200", + "relationship": "동료", + "content": "최민수님의 메세지 내용 1", + "font": "Roboto", + "createdAt": "2024-01-27T04:45:27Z" + }, + { + "id": 65061, + "recipientId": 34462, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/477/200/200", + "relationship": "친구", + "content": "김하은님의 메세지 내용 64", + "font": "Roboto", + "createdAt": "2023-02-21T19:08:42Z" + }, + { + "id": 75109, + "recipientId": 34462, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/149/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 38", + "font": "Roboto", + "createdAt": "2023-05-12T08:59:51Z" + } + ], + "reactionCount": 18, + "topReactions": [ + { + "id": 39441, + "emoji": "👍", + "count": 16 + }, + { + "id": 89350, + "emoji": "🥹", + "count": 1 + } + ] + }, + { + "id": 76172, + "name": "박서준", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/76172/600/400", + "createdAt": "2023-12-30T15:01:40Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 28913, + "recipientId": 76172, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/499/200/200", + "relationship": "동료", + "content": "이영준님의 메세지 내용 85", + "font": "Nanum Gothic", + "createdAt": "2023-01-06T21:55:19Z" + }, + { + "id": 20559, + "recipientId": 76172, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/315/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 53", + "font": "Roboto", + "createdAt": "2023-07-06T05:06:42Z" + }, + { + "id": 92696, + "recipientId": 76172, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/71/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 39", + "font": "Roboto", + "createdAt": "2023-12-04T21:02:50Z" + } + ], + "reactionCount": 55, + "topReactions": [ + { + "id": 1687, + "emoji": "🥹", + "count": 15 + } + ] + }, + { + "id": 22270, + "name": "최민수", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-08-29T23:33:29Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 12379, + "recipientId": 22270, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/212/200/200", + "relationship": "동료", + "content": "현빈님의 메세지 내용 30", + "font": "Pretendard", + "createdAt": "2023-01-03T08:31:04Z" + }, + { + "id": 16402, + "recipientId": 22270, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/354/200/200", + "relationship": "동료", + "content": "현빈님의 메세지 내용 34", + "font": "Noto Sans", + "createdAt": "2023-07-25T04:27:06Z" + }, + { + "id": 379, + "recipientId": 22270, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/14/200/200", + "relationship": "친구", + "content": "박서준님의 메세지 내용 4", + "font": "Pretendard", + "createdAt": "2023-07-09T01:19:05Z" + } + ], + "reactionCount": 11, + "topReactions": [ + { + "id": 3029, + "emoji": "👍", + "count": 13 + }, + { + "id": 76170, + "emoji": "👍", + "count": 15 + }, + { + "id": 96379, + "emoji": "😀", + "count": 13 + }, + { + "id": 89555, + "emoji": "😀", + "count": 16 + }, + { + "id": 39796, + "emoji": "❤️", + "count": 17 + } + ] + }, + { + "id": 525, + "name": "김하은", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2024-01-23T15:35:52Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 42938, + "recipientId": 525, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/301/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 29", + "font": "Roboto", + "createdAt": "2023-02-24T19:32:02Z" + }, + { + "id": 26243, + "recipientId": 525, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/470/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 36", + "font": "Noto Sans", + "createdAt": "2024-02-01T22:09:11Z" + }, + { + "id": 87049, + "recipientId": 525, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/97/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 19", + "font": "Pretendard", + "createdAt": "2023-03-20T23:42:55Z" + } + ], + "reactionCount": 40, + "topReactions": [ + { + "id": 92021, + "emoji": "❤️", + "count": 17 + }, + { + "id": 63448, + "emoji": "😀", + "count": 11 + } + ] + }, + { + "id": 21667, + "name": "박서준", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/21667/600/400", + "createdAt": "2023-09-14T10:29:13Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 68623, + "recipientId": 21667, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/272/200/200", + "relationship": "가족", + "content": "박서준님의 메세지 내용 34", + "font": "Pretendard", + "createdAt": "2023-04-14T02:05:32Z" + } + ], + "reactionCount": 2, + "topReactions": [ + { + "id": 6976, + "emoji": "❤️", + "count": 1 + } + ] + }, + { + "id": 22425, + "name": "박서준", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/22425/600/400", + "createdAt": "2023-10-10T09:00:27Z", + "messageCount": 3, + "recentMessages": [ + { + "id": 73839, + "recipientId": 22425, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/10/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 77", + "font": "Pretendard", + "createdAt": "2023-12-14T00:57:33Z" + }, + { + "id": 52414, + "recipientId": 22425, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/225/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 93", + "font": "Nanum Gothic", + "createdAt": "2024-01-13T15:32:28Z" + }, + { + "id": 2179, + "recipientId": 22425, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/233/200/200", + "relationship": "지인", + "content": "김하은님의 메세지 내용 89", + "font": "Noto Sans", + "createdAt": "2023-12-12T17:43:00Z" + } + ], + "reactionCount": 28, + "topReactions": [ + { + "id": 38379, + "emoji": "🥹", + "count": 3 + } + ] + }, + { + "id": 80244, + "name": "현빈", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/80244/600/400", + "createdAt": "2023-11-15T21:46:24Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 68208, + "recipientId": 80244, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/113/200/200", + "relationship": "가족", + "content": "김하은님의 메세지 내용 4", + "font": "Nanum Gothic", + "createdAt": "2023-11-16T20:54:09Z" + }, + { + "id": 71898, + "recipientId": 80244, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/466/200/200", + "relationship": "동료", + "content": "정우성님의 메세지 내용 20", + "font": "Roboto", + "createdAt": "2023-04-22T21:18:17Z" + }, + { + "id": 70652, + "recipientId": 80244, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/169/200/200", + "relationship": "가족", + "content": "박서준님의 메세지 내용 38", + "font": "Nanum Gothic", + "createdAt": "2023-08-27T22:00:41Z" + } + ], + "reactionCount": 54, + "topReactions": [ + { + "id": 63000, + "emoji": "🎉", + "count": 12 + } + ] + }, + { + "id": 76854, + "name": "한지민", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/76854/600/400", + "createdAt": "2023-05-13T20:54:53Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 8442, + "recipientId": 76854, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/391/200/200", + "relationship": "지인", + "content": "이병헌님의 메세지 내용 6", + "font": "Pretendard", + "createdAt": "2023-12-21T09:27:19Z" + }, + { + "id": 78435, + "recipientId": 76854, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/478/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 90", + "font": "Noto Sans", + "createdAt": "2024-01-11T13:23:28Z" + }, + { + "id": 51295, + "recipientId": 76854, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/470/200/200", + "relationship": "가족", + "content": "박서준님의 메세지 내용 25", + "font": "Roboto", + "createdAt": "2023-11-25T10:48:40Z" + } + ], + "reactionCount": 86, + "topReactions": [ + { + "id": 27143, + "emoji": "🥹", + "count": 8 + } + ] + }, + { + "id": 50919, + "name": "이영준", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-04-06T15:13:00Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 3111, + "recipientId": 50919, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/384/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 80", + "font": "Pretendard", + "createdAt": "2023-08-12T11:51:00Z" + }, + { + "id": 38535, + "recipientId": 50919, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/170/200/200", + "relationship": "동료", + "content": "정우성님의 메세지 내용 59", + "font": "Roboto", + "createdAt": "2024-01-21T06:32:43Z" + }, + { + "id": 80939, + "recipientId": 50919, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/67/200/200", + "relationship": "친구", + "content": "송혜교님의 메세지 내용 8", + "font": "Noto Sans", + "createdAt": "2023-09-23T14:56:17Z" + } + ], + "reactionCount": 76, + "topReactions": [ + { + "id": 89101, + "emoji": "👍", + "count": 12 + }, + { + "id": 60242, + "emoji": "😁", + "count": 17 + }, + { + "id": 97519, + "emoji": "🎉", + "count": 11 + }, + { + "id": 65104, + "emoji": "❤️", + "count": 7 + } + ] + }, + { + "id": 44601, + "name": "전지현", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-01-29T11:53:40Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 90217, + "recipientId": 44601, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/445/200/200", + "relationship": "동료", + "content": "현빈님의 메세지 내용 14", + "font": "Roboto", + "createdAt": "2023-09-25T19:48:08Z" + }, + { + "id": 73220, + "recipientId": 44601, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/32/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 73", + "font": "Roboto", + "createdAt": "2023-06-09T10:53:20Z" + }, + { + "id": 24251, + "recipientId": 44601, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/256/200/200", + "relationship": "지인", + "content": "전지현님의 메세지 내용 98", + "font": "Noto Sans", + "createdAt": "2023-10-12T16:19:37Z" + } + ], + "reactionCount": 90, + "topReactions": [ + { + "id": 95691, + "emoji": "🎉", + "count": 3 + }, + { + "id": 89483, + "emoji": "😁", + "count": 2 + }, + { + "id": 56468, + "emoji": "🎉", + "count": 13 + } + ] + }, + { + "id": 37974, + "name": "정우성", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-12-26T20:53:27Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 43644, + "recipientId": 37974, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/215/200/200", + "relationship": "지인", + "content": "송혜교님의 메세지 내용 26", + "font": "Roboto", + "createdAt": "2023-10-29T16:46:20Z" + } + ], + "reactionCount": 88, + "topReactions": [ + { + "id": 72401, + "emoji": "❤️", + "count": 3 + }, + { + "id": 5640, + "emoji": "❤️", + "count": 5 + } + ] + }, + { + "id": 65650, + "name": "현빈", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-12-29T01:51:13Z", + "messageCount": 3, + "recentMessages": [ + { + "id": 20882, + "recipientId": 65650, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/342/200/200", + "relationship": "동료", + "content": "한지민님의 메세지 내용 76", + "font": "Roboto", + "createdAt": "2023-01-13T21:59:32Z" + }, + { + "id": 79855, + "recipientId": 65650, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/42/200/200", + "relationship": "동료", + "content": "정우성님의 메세지 내용 71", + "font": "Roboto", + "createdAt": "2023-05-13T19:20:45Z" + }, + { + "id": 38337, + "recipientId": 65650, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/459/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 83", + "font": "Roboto", + "createdAt": "2023-03-02T21:24:55Z" + } + ], + "reactionCount": 17, + "topReactions": [ + { + "id": 91559, + "emoji": "🥹", + "count": 3 + }, + { + "id": 56771, + "emoji": "🎉", + "count": 3 + }, + { + "id": 15952, + "emoji": "❤️", + "count": 18 + }, + { + "id": 90450, + "emoji": "👍", + "count": 15 + }, + { + "id": 52341, + "emoji": "😀", + "count": 14 + } + ] + }, + { + "id": 41386, + "name": "김하은", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-01-01T07:46:06Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 89635, + "recipientId": 41386, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/192/200/200", + "relationship": "가족", + "content": "전지현님의 메세지 내용 44", + "font": "Nanum Gothic", + "createdAt": "2023-08-29T17:09:14Z" + }, + { + "id": 89440, + "recipientId": 41386, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/401/200/200", + "relationship": "지인", + "content": "박서준님의 메세지 내용 35", + "font": "Noto Sans", + "createdAt": "2023-12-31T16:32:30Z" + }, + { + "id": 54885, + "recipientId": 41386, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/97/200/200", + "relationship": "가족", + "content": "전지현님의 메세지 내용 43", + "font": "Nanum Gothic", + "createdAt": "2023-05-05T08:14:34Z" + } + ], + "reactionCount": 78, + "topReactions": [ + { + "id": 65046, + "emoji": "🎉", + "count": 12 + }, + { + "id": 94282, + "emoji": "😀", + "count": 15 + }, + { + "id": 87051, + "emoji": "🎉", + "count": 12 + }, + { + "id": 76472, + "emoji": "😁", + "count": 12 + }, + { + "id": 43401, + "emoji": "🥹", + "count": 1 + } + ] + }, + { + "id": 5465, + "name": "이병헌", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-01-10T18:10:25Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 28514, + "recipientId": 5465, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/388/200/200", + "relationship": "가족", + "content": "정우성님의 메세지 내용 77", + "font": "Pretendard", + "createdAt": "2023-10-28T19:29:15Z" + }, + { + "id": 69038, + "recipientId": 5465, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/412/200/200", + "relationship": "지인", + "content": "전지현님의 메세지 내용 88", + "font": "Noto Sans", + "createdAt": "2023-06-16T07:01:10Z" + }, + { + "id": 24211, + "recipientId": 5465, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/89/200/200", + "relationship": "지인", + "content": "한지민님의 메세지 내용 16", + "font": "Pretendard", + "createdAt": "2023-01-05T16:10:00Z" + } + ], + "reactionCount": 25, + "topReactions": [ + { + "id": 59656, + "emoji": "😁", + "count": 15 + }, + { + "id": 91642, + "emoji": "👍", + "count": 6 + }, + { + "id": 63844, + "emoji": "🎉", + "count": 9 + }, + { + "id": 38254, + "emoji": "🎉", + "count": 13 + }, + { + "id": 80222, + "emoji": "🎉", + "count": 3 + }, + { + "id": 76177, + "emoji": "🎉", + "count": 10 + } + ] + }, + { + "id": 51890, + "name": "이영준", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-10-30T15:21:41Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 35764, + "recipientId": 51890, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/169/200/200", + "relationship": "가족", + "content": "한지민님의 메세지 내용 43", + "font": "Nanum Gothic", + "createdAt": "2024-01-14T11:24:57Z" + } + ], + "reactionCount": 60, + "topReactions": [ + { + "id": 21526, + "emoji": "❤️", + "count": 9 + }, + { + "id": 89624, + "emoji": "😁", + "count": 9 + }, + { + "id": 92331, + "emoji": "🎉", + "count": 17 + }, + { + "id": 56922, + "emoji": "🎉", + "count": 12 + } + ] + }, + { + "id": 3937, + "name": "김하은", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-08-26T13:39:55Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 16211, + "recipientId": 3937, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/329/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 72", + "font": "Noto Sans", + "createdAt": "2023-09-13T00:33:13Z" + }, + { + "id": 60479, + "recipientId": 3937, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/165/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 34", + "font": "Noto Sans", + "createdAt": "2023-12-21T21:06:23Z" + }, + { + "id": 77695, + "recipientId": 3937, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/390/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 62", + "font": "Pretendard", + "createdAt": "2023-07-27T13:22:46Z" + } + ], + "reactionCount": 3, + "topReactions": [ + { + "id": 75083, + "emoji": "🎉", + "count": 3 + }, + { + "id": 99458, + "emoji": "👍", + "count": 8 + }, + { + "id": 58435, + "emoji": "🥹", + "count": 9 + }, + { + "id": 35549, + "emoji": "😀", + "count": 12 + }, + { + "id": 89316, + "emoji": "🥹", + "count": 12 + }, + { + "id": 92464, + "emoji": "😀", + "count": 12 + } + ] + }, + { + "id": 15425, + "name": "최민수", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/15425/600/400", + "createdAt": "2024-01-29T12:40:23Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 40648, + "recipientId": 15425, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/236/200/200", + "relationship": "동료", + "content": "정우성님의 메세지 내용 50", + "font": "Roboto", + "createdAt": "2023-01-19T11:20:15Z" + }, + { + "id": 4968, + "recipientId": 15425, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/433/200/200", + "relationship": "동료", + "content": "전지현님의 메세지 내용 47", + "font": "Roboto", + "createdAt": "2023-11-15T17:20:59Z" + }, + { + "id": 38363, + "recipientId": 15425, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/246/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 72", + "font": "Nanum Gothic", + "createdAt": "2023-03-18T16:01:25Z" + } + ], + "reactionCount": 50, + "topReactions": [ + { + "id": 16722, + "emoji": "🎉", + "count": 11 + }, + { + "id": 59575, + "emoji": "👍", + "count": 9 + }, + { + "id": 92248, + "emoji": "😁", + "count": 2 + } + ] + }, + { + "id": 5267, + "name": "한지민", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/5267/600/400", + "createdAt": "2023-08-21T12:37:58Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 56322, + "recipientId": 5267, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/270/200/200", + "relationship": "동료", + "content": "현빈님의 메세지 내용 87", + "font": "Noto Sans", + "createdAt": "2023-12-15T10:09:08Z" + }, + { + "id": 59649, + "recipientId": 5267, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/283/200/200", + "relationship": "지인", + "content": "현빈님의 메세지 내용 5", + "font": "Roboto", + "createdAt": "2023-09-27T15:11:17Z" + }, + { + "id": 30468, + "recipientId": 5267, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/241/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 90", + "font": "Roboto", + "createdAt": "2023-02-21T22:25:32Z" + } + ], + "reactionCount": 19, + "topReactions": [ + { + "id": 40145, + "emoji": "😁", + "count": 19 + }, + { + "id": 85434, + "emoji": "❤️", + "count": 4 + }, + { + "id": 12101, + "emoji": "😁", + "count": 14 + }, + { + "id": 81287, + "emoji": "😁", + "count": 16 + }, + { + "id": 4370, + "emoji": "❤️", + "count": 6 + }, + { + "id": 37361, + "emoji": "😀", + "count": 3 + } + ] + }, + { + "id": 76905, + "name": "한지민", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/76905/600/400", + "createdAt": "2023-07-25T12:26:52Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 71574, + "recipientId": 76905, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/299/200/200", + "relationship": "지인", + "content": "송혜교님의 메세지 내용 65", + "font": "Pretendard", + "createdAt": "2023-12-25T00:11:15Z" + }, + { + "id": 881, + "recipientId": 76905, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/225/200/200", + "relationship": "지인", + "content": "송혜교님의 메세지 내용 55", + "font": "Pretendard", + "createdAt": "2023-10-08T00:53:44Z" + }, + { + "id": 3393, + "recipientId": 76905, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/140/200/200", + "relationship": "지인", + "content": "전지현님의 메세지 내용 36", + "font": "Noto Sans", + "createdAt": "2023-11-01T14:38:31Z" + } + ], + "reactionCount": 89, + "topReactions": [ + { + "id": 68890, + "emoji": "😁", + "count": 8 + }, + { + "id": 36484, + "emoji": "🥹", + "count": 11 + } + ] + }, + { + "id": 90385, + "name": "송혜교", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/90385/600/400", + "createdAt": "2023-08-06T10:39:41Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 66552, + "recipientId": 90385, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/498/200/200", + "relationship": "동료", + "content": "이병헌님의 메세지 내용 36", + "font": "Noto Sans", + "createdAt": "2023-10-17T11:54:41Z" + } + ], + "reactionCount": 73, + "topReactions": [ + { + "id": 88512, + "emoji": "❤️", + "count": 4 + }, + { + "id": 33951, + "emoji": "🥹", + "count": 10 + } + ] + }, + { + "id": 83350, + "name": "박서준", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/83350/600/400", + "createdAt": "2024-01-11T21:50:53Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 85297, + "recipientId": 83350, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/454/200/200", + "relationship": "친구", + "content": "최민수님의 메세지 내용 81", + "font": "Roboto", + "createdAt": "2023-07-28T00:02:33Z" + }, + { + "id": 78381, + "recipientId": 83350, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/293/200/200", + "relationship": "친구", + "content": "송혜교님의 메세지 내용 61", + "font": "Nanum Gothic", + "createdAt": "2023-05-23T14:59:39Z" + } + ], + "reactionCount": 87, + "topReactions": [ + { + "id": 7092, + "emoji": "🥹", + "count": 20 + } + ] + }, + { + "id": 82914, + "name": "이영준", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-01-18T08:55:14Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 97740, + "recipientId": 82914, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/30/200/200", + "relationship": "가족", + "content": "한지민님의 메세지 내용 95", + "font": "Noto Sans", + "createdAt": "2023-05-17T12:57:29Z" + }, + { + "id": 47854, + "recipientId": 82914, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/267/200/200", + "relationship": "동료", + "content": "송혜교님의 메세지 내용 91", + "font": "Roboto", + "createdAt": "2023-02-08T23:14:03Z" + }, + { + "id": 93329, + "recipientId": 82914, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/468/200/200", + "relationship": "동료", + "content": "한지민님의 메세지 내용 86", + "font": "Nanum Gothic", + "createdAt": "2023-04-12T17:20:58Z" + } + ], + "reactionCount": 48, + "topReactions": [ + { + "id": 47934, + "emoji": "❤️", + "count": 7 + }, + { + "id": 38552, + "emoji": "🥹", + "count": 12 + }, + { + "id": 97573, + "emoji": "❤️", + "count": 17 + }, + { + "id": 90066, + "emoji": "👍", + "count": 17 + }, + { + "id": 75594, + "emoji": "👍", + "count": 5 + }, + { + "id": 80625, + "emoji": "🥹", + "count": 10 + } + ] + }, + { + "id": 39122, + "name": "현빈", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/39122/600/400", + "createdAt": "2024-01-28T01:36:34Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 59673, + "recipientId": 39122, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/467/200/200", + "relationship": "동료", + "content": "이병헌님의 메세지 내용 15", + "font": "Nanum Gothic", + "createdAt": "2023-03-20T07:58:11Z" + }, + { + "id": 30276, + "recipientId": 39122, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/111/200/200", + "relationship": "가족", + "content": "전지현님의 메세지 내용 19", + "font": "Nanum Gothic", + "createdAt": "2023-01-11T05:07:07Z" + }, + { + "id": 34351, + "recipientId": 39122, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/201/200/200", + "relationship": "친구", + "content": "전지현님의 메세지 내용 90", + "font": "Roboto", + "createdAt": "2023-03-09T04:25:04Z" + } + ], + "reactionCount": 54, + "topReactions": [ + { + "id": 21238, + "emoji": "❤️", + "count": 7 + }, + { + "id": 36319, + "emoji": "🥹", + "count": 8 + } + ] + }, + { + "id": 36279, + "name": "최민수", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-04-06T20:33:22Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 12730, + "recipientId": 36279, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/410/200/200", + "relationship": "동료", + "content": "현빈님의 메세지 내용 15", + "font": "Noto Sans", + "createdAt": "2023-08-13T17:05:31Z" + }, + { + "id": 64017, + "recipientId": 36279, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/1/200/200", + "relationship": "동료", + "content": "송혜교님의 메세지 내용 22", + "font": "Nanum Gothic", + "createdAt": "2023-07-14T20:46:20Z" + }, + { + "id": 87956, + "recipientId": 36279, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/362/200/200", + "relationship": "가족", + "content": "이병헌님의 메세지 내용 45", + "font": "Pretendard", + "createdAt": "2023-01-10T01:43:19Z" + } + ], + "reactionCount": 58, + "topReactions": [ + { + "id": 37731, + "emoji": "🎉", + "count": 19 + }, + { + "id": 95128, + "emoji": "🥹", + "count": 12 + }, + { + "id": 65326, + "emoji": "🎉", + "count": 9 + } + ] + }, + { + "id": 75295, + "name": "정우성", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/75295/600/400", + "createdAt": "2023-06-12T15:45:08Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 87774, + "recipientId": 75295, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/376/200/200", + "relationship": "지인", + "content": "현빈님의 메세지 내용 49", + "font": "Roboto", + "createdAt": "2023-01-22T06:59:23Z" + }, + { + "id": 46159, + "recipientId": 75295, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/478/200/200", + "relationship": "동료", + "content": "이영준님의 메세지 내용 57", + "font": "Noto Sans", + "createdAt": "2023-07-18T17:15:24Z" + }, + { + "id": 34427, + "recipientId": 75295, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/371/200/200", + "relationship": "동료", + "content": "정우성님의 메세지 내용 46", + "font": "Nanum Gothic", + "createdAt": "2023-09-30T13:38:37Z" + } + ], + "reactionCount": 11, + "topReactions": [ + { + "id": 60036, + "emoji": "🎉", + "count": 20 + }, + { + "id": 66223, + "emoji": "😁", + "count": 5 + }, + { + "id": 57559, + "emoji": "❤️", + "count": 14 + }, + { + "id": 85462, + "emoji": "❤️", + "count": 18 + }, + { + "id": 78366, + "emoji": "❤️", + "count": 10 + } + ] + }, + { + "id": 53963, + "name": "이영준", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-04-10T05:19:05Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 8017, + "recipientId": 53963, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/176/200/200", + "relationship": "가족", + "content": "한지민님의 메세지 내용 62", + "font": "Nanum Gothic", + "createdAt": "2023-08-08T16:57:27Z" + }, + { + "id": 65904, + "recipientId": 53963, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/242/200/200", + "relationship": "가족", + "content": "한지민님의 메세지 내용 91", + "font": "Nanum Gothic", + "createdAt": "2023-05-25T20:32:37Z" + }, + { + "id": 38157, + "recipientId": 53963, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/241/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 33", + "font": "Pretendard", + "createdAt": "2023-02-22T19:17:47Z" + } + ], + "reactionCount": 1, + "topReactions": [ + { + "id": 85067, + "emoji": "❤️", + "count": 19 + }, + { + "id": 23463, + "emoji": "🎉", + "count": 14 + } + ] + }, + { + "id": 48079, + "name": "현빈", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-08-04T13:19:14Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 66088, + "recipientId": 48079, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/450/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 79", + "font": "Noto Sans", + "createdAt": "2023-03-02T15:36:09Z" + }, + { + "id": 80363, + "recipientId": 48079, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/413/200/200", + "relationship": "동료", + "content": "한지민님의 메세지 내용 56", + "font": "Noto Sans", + "createdAt": "2023-07-22T12:40:41Z" + }, + { + "id": 7160, + "recipientId": 48079, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/394/200/200", + "relationship": "친구", + "content": "전지현님의 메세지 내용 43", + "font": "Nanum Gothic", + "createdAt": "2023-05-06T03:20:45Z" + } + ], + "reactionCount": 13, + "topReactions": [ + { + "id": 47472, + "emoji": "🥹", + "count": 1 + }, + { + "id": 73490, + "emoji": "👍", + "count": 7 + }, + { + "id": 9397, + "emoji": "😁", + "count": 18 + }, + { + "id": 62463, + "emoji": "😀", + "count": 8 + } + ] + }, + { + "id": 2640, + "name": "정우성", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-10-09T05:47:27Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 23910, + "recipientId": 2640, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/181/200/200", + "relationship": "친구", + "content": "이영준님의 메세지 내용 99", + "font": "Roboto", + "createdAt": "2024-01-05T08:03:41Z" + }, + { + "id": 60985, + "recipientId": 2640, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/440/200/200", + "relationship": "동료", + "content": "이병헌님의 메세지 내용 52", + "font": "Pretendard", + "createdAt": "2023-05-11T23:03:58Z" + }, + { + "id": 32855, + "recipientId": 2640, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/29/200/200", + "relationship": "가족", + "content": "정우성님의 메세지 내용 76", + "font": "Roboto", + "createdAt": "2023-01-24T04:09:39Z" + } + ], + "reactionCount": 39, + "topReactions": [ + { + "id": 68723, + "emoji": "😁", + "count": 10 + } + ] + }, + { + "id": 54287, + "name": "이영준", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2024-01-12T17:22:52Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 79772, + "recipientId": 54287, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/25/200/200", + "relationship": "지인", + "content": "전지현님의 메세지 내용 20", + "font": "Pretendard", + "createdAt": "2023-06-06T00:54:01Z" + }, + { + "id": 54858, + "recipientId": 54287, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/28/200/200", + "relationship": "지인", + "content": "현빈님의 메세지 내용 13", + "font": "Noto Sans", + "createdAt": "2024-01-30T02:08:36Z" + } + ], + "reactionCount": 59, + "topReactions": [ + { + "id": 67796, + "emoji": "👍", + "count": 17 + }, + { + "id": 73312, + "emoji": "🎉", + "count": 14 + }, + { + "id": 69831, + "emoji": "❤️", + "count": 6 + }, + { + "id": 68250, + "emoji": "😁", + "count": 15 + } + ] + }, + { + "id": 51366, + "name": "이영준", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/51366/600/400", + "createdAt": "2023-09-29T07:35:31Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 92592, + "recipientId": 51366, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/301/200/200", + "relationship": "동료", + "content": "송혜교님의 메세지 내용 7", + "font": "Roboto", + "createdAt": "2023-02-08T19:54:33Z" + }, + { + "id": 22441, + "recipientId": 51366, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/424/200/200", + "relationship": "가족", + "content": "한지민님의 메세지 내용 12", + "font": "Noto Sans", + "createdAt": "2023-03-22T19:53:29Z" + }, + { + "id": 74021, + "recipientId": 51366, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/111/200/200", + "relationship": "친구", + "content": "현빈님의 메세지 내용 100", + "font": "Noto Sans", + "createdAt": "2023-09-03T16:40:11Z" + } + ], + "reactionCount": 3, + "topReactions": [ + { + "id": 61747, + "emoji": "😁", + "count": 6 + }, + { + "id": 25034, + "emoji": "🥹", + "count": 7 + } + ] + }, + { + "id": 53790, + "name": "김하은", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/53790/600/400", + "createdAt": "2023-08-17T10:17:13Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 18233, + "recipientId": 53790, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/323/200/200", + "relationship": "친구", + "content": "송혜교님의 메세지 내용 35", + "font": "Nanum Gothic", + "createdAt": "2023-07-03T01:10:13Z" + }, + { + "id": 61256, + "recipientId": 53790, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/121/200/200", + "relationship": "지인", + "content": "정우성님의 메세지 내용 80", + "font": "Roboto", + "createdAt": "2023-10-21T06:37:14Z" + }, + { + "id": 44921, + "recipientId": 53790, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/398/200/200", + "relationship": "친구", + "content": "김하은님의 메세지 내용 45", + "font": "Noto Sans", + "createdAt": "2023-06-24T09:03:26Z" + } + ], + "reactionCount": 64, + "topReactions": [ + { + "id": 3352, + "emoji": "👍", + "count": 10 + }, + { + "id": 39601, + "emoji": "😀", + "count": 10 + }, + { + "id": 11421, + "emoji": "🎉", + "count": 5 + }, + { + "id": 35027, + "emoji": "🎉", + "count": 10 + } + ] + }, + { + "id": 79165, + "name": "이영준", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/79165/600/400", + "createdAt": "2023-06-19T21:21:37Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 35200, + "recipientId": 79165, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/66/200/200", + "relationship": "지인", + "content": "송혜교님의 메세지 내용 94", + "font": "Noto Sans", + "createdAt": "2023-01-31T01:24:39Z" + } + ], + "reactionCount": 43, + "topReactions": [ + { + "id": 8574, + "emoji": "🎉", + "count": 7 + }, + { + "id": 64170, + "emoji": "❤️", + "count": 8 + } + ] + }, + { + "id": 28312, + "name": "현빈", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2024-02-02T23:39:16Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 48020, + "recipientId": 28312, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/405/200/200", + "relationship": "지인", + "content": "한지민님의 메세지 내용 64", + "font": "Nanum Gothic", + "createdAt": "2023-12-24T00:02:37Z" + }, + { + "id": 20798, + "recipientId": 28312, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/435/200/200", + "relationship": "가족", + "content": "한지민님의 메세지 내용 83", + "font": "Noto Sans", + "createdAt": "2023-04-23T15:30:26Z" + }, + { + "id": 87481, + "recipientId": 28312, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/284/200/200", + "relationship": "지인", + "content": "한지민님의 메세지 내용 11", + "font": "Pretendard", + "createdAt": "2023-05-11T12:13:58Z" + } + ], + "reactionCount": 31, + "topReactions": [ + { + "id": 9532, + "emoji": "🎉", + "count": 15 + }, + { + "id": 71554, + "emoji": "🎉", + "count": 3 + }, + { + "id": 39488, + "emoji": "👍", + "count": 14 + } + ] + }, + { + "id": 63671, + "name": "송혜교", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-11-27T08:35:03Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 38644, + "recipientId": 63671, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/254/200/200", + "relationship": "지인", + "content": "박서준님의 메세지 내용 13", + "font": "Roboto", + "createdAt": "2023-03-06T23:53:26Z" + }, + { + "id": 83644, + "recipientId": 63671, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/4/200/200", + "relationship": "지인", + "content": "한지민님의 메세지 내용 65", + "font": "Noto Sans", + "createdAt": "2023-05-26T11:25:25Z" + }, + { + "id": 17855, + "recipientId": 63671, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/100/200/200", + "relationship": "친구", + "content": "현빈님의 메세지 내용 56", + "font": "Noto Sans", + "createdAt": "2023-06-05T01:49:30Z" + } + ], + "reactionCount": 33, + "topReactions": [ + { + "id": 52748, + "emoji": "👍", + "count": 10 + }, + { + "id": 16337, + "emoji": "😁", + "count": 12 + }, + { + "id": 61443, + "emoji": "🥹", + "count": 20 + }, + { + "id": 68842, + "emoji": "😁", + "count": 16 + }, + { + "id": 32585, + "emoji": "🎉", + "count": 10 + }, + { + "id": 71746, + "emoji": "😁", + "count": 9 + } + ] + }, + { + "id": 68523, + "name": "박서준", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/68523/600/400", + "createdAt": "2023-01-29T05:15:30Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 24735, + "recipientId": 68523, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/60/200/200", + "relationship": "가족", + "content": "김하은님의 메세지 내용 99", + "font": "Pretendard", + "createdAt": "2023-10-16T13:33:28Z" + }, + { + "id": 98757, + "recipientId": 68523, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/486/200/200", + "relationship": "지인", + "content": "박서준님의 메세지 내용 21", + "font": "Nanum Gothic", + "createdAt": "2024-01-13T00:27:10Z" + }, + { + "id": 34120, + "recipientId": 68523, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/294/200/200", + "relationship": "친구", + "content": "송혜교님의 메세지 내용 73", + "font": "Pretendard", + "createdAt": "2023-11-11T07:45:22Z" + } + ], + "reactionCount": 74, + "topReactions": [ + { + "id": 47111, + "emoji": "👍", + "count": 12 + }, + { + "id": 67878, + "emoji": "😀", + "count": 16 + }, + { + "id": 49575, + "emoji": "😀", + "count": 10 + }, + { + "id": 72740, + "emoji": "🎉", + "count": 15 + }, + { + "id": 66239, + "emoji": "❤️", + "count": 16 + }, + { + "id": 78326, + "emoji": "🥹", + "count": 14 + } + ] + }, + { + "id": 73648, + "name": "한지민", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-05-23T17:26:38Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 47579, + "recipientId": 73648, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/331/200/200", + "relationship": "지인", + "content": "현빈님의 메세지 내용 11", + "font": "Roboto", + "createdAt": "2023-12-19T14:09:40Z" + }, + { + "id": 96788, + "recipientId": 73648, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/249/200/200", + "relationship": "가족", + "content": "이병헌님의 메세지 내용 54", + "font": "Nanum Gothic", + "createdAt": "2023-09-16T01:58:06Z" + }, + { + "id": 20726, + "recipientId": 73648, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/431/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 78", + "font": "Pretendard", + "createdAt": "2023-07-25T07:59:44Z" + } + ], + "reactionCount": 45, + "topReactions": [ + { + "id": 86527, + "emoji": "😁", + "count": 15 + }, + { + "id": 59551, + "emoji": "🥹", + "count": 16 + }, + { + "id": 3729, + "emoji": "😀", + "count": 2 + }, + { + "id": 29902, + "emoji": "🎉", + "count": 12 + }, + { + "id": 39150, + "emoji": "❤️", + "count": 19 + } + ] + }, + { + "id": 3519, + "name": "이영준", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/3519/600/400", + "createdAt": "2023-03-07T10:55:33Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 49350, + "recipientId": 3519, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/37/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 49", + "font": "Roboto", + "createdAt": "2023-12-23T10:53:50Z" + } + ], + "reactionCount": 59, + "topReactions": [ + { + "id": 93221, + "emoji": "👍", + "count": 1 + }, + { + "id": 95714, + "emoji": "🎉", + "count": 8 + }, + { + "id": 8397, + "emoji": "🎉", + "count": 16 + }, + { + "id": 70176, + "emoji": "🎉", + "count": 9 + }, + { + "id": 67165, + "emoji": "🎉", + "count": 10 + }, + { + "id": 41000, + "emoji": "👍", + "count": 7 + } + ] + }, + { + "id": 29324, + "name": "전지현", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-11-15T12:34:37Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 66891, + "recipientId": 29324, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/150/200/200", + "relationship": "지인", + "content": "이영준님의 메세지 내용 28", + "font": "Roboto", + "createdAt": "2024-01-16T01:09:36Z" + } + ], + "reactionCount": 91, + "topReactions": [ + { + "id": 72115, + "emoji": "👍", + "count": 5 + }, + { + "id": 91626, + "emoji": "❤️", + "count": 18 + }, + { + "id": 19336, + "emoji": "😀", + "count": 4 + } + ] + }, + { + "id": 34799, + "name": "최민수", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/34799/600/400", + "createdAt": "2023-05-26T14:19:32Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 64083, + "recipientId": 34799, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/269/200/200", + "relationship": "동료", + "content": "정우성님의 메세지 내용 15", + "font": "Nanum Gothic", + "createdAt": "2023-09-02T06:05:45Z" + }, + { + "id": 29589, + "recipientId": 34799, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/471/200/200", + "relationship": "지인", + "content": "박서준님의 메세지 내용 7", + "font": "Noto Sans", + "createdAt": "2023-06-15T19:01:12Z" + }, + { + "id": 30989, + "recipientId": 34799, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/129/200/200", + "relationship": "지인", + "content": "박서준님의 메세지 내용 45", + "font": "Roboto", + "createdAt": "2023-03-23T13:04:58Z" + } + ], + "reactionCount": 8, + "topReactions": [ + { + "id": 3482, + "emoji": "👍", + "count": 18 + }, + { + "id": 66591, + "emoji": "🥹", + "count": 7 + }, + { + "id": 38585, + "emoji": "🥹", + "count": 19 + } + ] + }, + { + "id": 35446, + "name": "현빈", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-12-14T18:07:09Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 58428, + "recipientId": 35446, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/426/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 29", + "font": "Noto Sans", + "createdAt": "2023-09-15T23:26:36Z" + }, + { + "id": 58296, + "recipientId": 35446, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/211/200/200", + "relationship": "동료", + "content": "최민수님의 메세지 내용 44", + "font": "Nanum Gothic", + "createdAt": "2023-01-01T12:11:21Z" + }, + { + "id": 2388, + "recipientId": 35446, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/489/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 92", + "font": "Noto Sans", + "createdAt": "2023-01-24T10:23:16Z" + } + ], + "reactionCount": 68, + "topReactions": [ + { + "id": 59908, + "emoji": "❤️", + "count": 9 + }, + { + "id": 88137, + "emoji": "❤️", + "count": 18 + }, + { + "id": 73395, + "emoji": "😀", + "count": 1 + }, + { + "id": 1194, + "emoji": "👍", + "count": 7 + } + ] + }, + { + "id": 43465, + "name": "이영준", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/43465/600/400", + "createdAt": "2023-06-17T10:24:36Z", + "messageCount": 3, + "recentMessages": [ + { + "id": 49416, + "recipientId": 43465, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/159/200/200", + "relationship": "가족", + "content": "이영준님의 메세지 내용 31", + "font": "Nanum Gothic", + "createdAt": "2023-09-13T13:59:21Z" + }, + { + "id": 47626, + "recipientId": 43465, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/428/200/200", + "relationship": "가족", + "content": "현빈님의 메세지 내용 40", + "font": "Pretendard", + "createdAt": "2023-06-13T04:40:39Z" + }, + { + "id": 38141, + "recipientId": 43465, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/165/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 19", + "font": "Nanum Gothic", + "createdAt": "2023-03-01T14:53:42Z" + } + ], + "reactionCount": 32, + "topReactions": [ + { + "id": 91871, + "emoji": "🎉", + "count": 13 + }, + { + "id": 78009, + "emoji": "🎉", + "count": 6 + }, + { + "id": 19885, + "emoji": "😁", + "count": 16 + }, + { + "id": 93729, + "emoji": "❤️", + "count": 19 + }, + { + "id": 57682, + "emoji": "🥹", + "count": 19 + }, + { + "id": 6511, + "emoji": "🎉", + "count": 15 + } + ] + }, + { + "id": 35138, + "name": "정우성", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/35138/600/400", + "createdAt": "2023-10-26T18:11:01Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 28846, + "recipientId": 35138, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/383/200/200", + "relationship": "지인", + "content": "현빈님의 메세지 내용 85", + "font": "Pretendard", + "createdAt": "2023-10-31T04:33:01Z" + }, + { + "id": 67016, + "recipientId": 35138, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/473/200/200", + "relationship": "지인", + "content": "정우성님의 메세지 내용 30", + "font": "Noto Sans", + "createdAt": "2023-08-22T17:48:28Z" + }, + { + "id": 26345, + "recipientId": 35138, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/424/200/200", + "relationship": "친구", + "content": "최민수님의 메세지 내용 77", + "font": "Roboto", + "createdAt": "2023-08-06T00:17:22Z" + } + ], + "reactionCount": 53, + "topReactions": [ + { + "id": 14727, + "emoji": "🥹", + "count": 20 + }, + { + "id": 66436, + "emoji": "🎉", + "count": 5 + }, + { + "id": 36308, + "emoji": "👍", + "count": 14 + }, + { + "id": 21367, + "emoji": "😁", + "count": 18 + }, + { + "id": 12087, + "emoji": "😁", + "count": 9 + } + ] + }, + { + "id": 57025, + "name": "최민수", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-09-24T09:40:21Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 86332, + "recipientId": 57025, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/66/200/200", + "relationship": "친구", + "content": "현빈님의 메세지 내용 3", + "font": "Noto Sans", + "createdAt": "2023-08-27T00:28:01Z" + }, + { + "id": 62727, + "recipientId": 57025, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/322/200/200", + "relationship": "가족", + "content": "박서준님의 메세지 내용 24", + "font": "Roboto", + "createdAt": "2023-02-01T13:03:37Z" + } + ], + "reactionCount": 97, + "topReactions": [ + { + "id": 57205, + "emoji": "👍", + "count": 19 + } + ] + }, + { + "id": 73391, + "name": "전지현", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/73391/600/400", + "createdAt": "2024-01-13T03:42:57Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 55060, + "recipientId": 73391, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/255/200/200", + "relationship": "지인", + "content": "박서준님의 메세지 내용 54", + "font": "Roboto", + "createdAt": "2023-11-01T01:54:10Z" + }, + { + "id": 73020, + "recipientId": 73391, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/124/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 61", + "font": "Nanum Gothic", + "createdAt": "2023-06-28T02:59:56Z" + }, + { + "id": 65998, + "recipientId": 73391, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/117/200/200", + "relationship": "가족", + "content": "이병헌님의 메세지 내용 7", + "font": "Noto Sans", + "createdAt": "2023-06-29T21:54:39Z" + } + ], + "reactionCount": 64, + "topReactions": [ + { + "id": 87665, + "emoji": "🎉", + "count": 12 + } + ] + }, + { + "id": 14280, + "name": "송혜교", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-08-01T17:10:49Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 56101, + "recipientId": 14280, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/371/200/200", + "relationship": "친구", + "content": "전지현님의 메세지 내용 71", + "font": "Pretendard", + "createdAt": "2023-06-06T07:40:33Z" + }, + { + "id": 95535, + "recipientId": 14280, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/31/200/200", + "relationship": "지인", + "content": "송혜교님의 메세지 내용 13", + "font": "Noto Sans", + "createdAt": "2023-01-24T13:48:36Z" + }, + { + "id": 61373, + "recipientId": 14280, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/378/200/200", + "relationship": "동료", + "content": "전지현님의 메세지 내용 94", + "font": "Nanum Gothic", + "createdAt": "2023-10-05T12:57:26Z" + } + ], + "reactionCount": 18, + "topReactions": [ + { + "id": 55291, + "emoji": "😁", + "count": 15 + }, + { + "id": 90016, + "emoji": "❤️", + "count": 15 + }, + { + "id": 84184, + "emoji": "😁", + "count": 9 + }, + { + "id": 43715, + "emoji": "🥹", + "count": 3 + }, + { + "id": 62315, + "emoji": "🎉", + "count": 6 + }, + { + "id": 34308, + "emoji": "🎉", + "count": 12 + } + ] + }, + { + "id": 62767, + "name": "최민수", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-02-20T13:06:25Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 88527, + "recipientId": 62767, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/344/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 55", + "font": "Noto Sans", + "createdAt": "2023-08-22T10:55:21Z" + }, + { + "id": 13081, + "recipientId": 62767, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/354/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 29", + "font": "Roboto", + "createdAt": "2024-01-03T06:33:31Z" + }, + { + "id": 60642, + "recipientId": 62767, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/378/200/200", + "relationship": "친구", + "content": "현빈님의 메세지 내용 48", + "font": "Noto Sans", + "createdAt": "2023-05-16T05:34:20Z" + } + ], + "reactionCount": 64, + "topReactions": [ + { + "id": 27890, + "emoji": "🥹", + "count": 12 + }, + { + "id": 56175, + "emoji": "👍", + "count": 17 + }, + { + "id": 91877, + "emoji": "🥹", + "count": 6 + }, + { + "id": 69359, + "emoji": "😀", + "count": 7 + }, + { + "id": 52444, + "emoji": "❤️", + "count": 19 + }, + { + "id": 40782, + "emoji": "😁", + "count": 13 + } + ] + }, + { + "id": 7728, + "name": "이영준", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/7728/600/400", + "createdAt": "2023-09-25T02:59:47Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 37394, + "recipientId": 7728, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/309/200/200", + "relationship": "친구", + "content": "현빈님의 메세지 내용 74", + "font": "Noto Sans", + "createdAt": "2023-03-21T04:47:53Z" + }, + { + "id": 88123, + "recipientId": 7728, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/370/200/200", + "relationship": "지인", + "content": "김하은님의 메세지 내용 25", + "font": "Pretendard", + "createdAt": "2023-08-14T12:27:46Z" + }, + { + "id": 43663, + "recipientId": 7728, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/444/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 84", + "font": "Nanum Gothic", + "createdAt": "2023-12-29T08:07:41Z" + } + ], + "reactionCount": 36, + "topReactions": [ + { + "id": 76073, + "emoji": "🥹", + "count": 8 + }, + { + "id": 96332, + "emoji": "🎉", + "count": 17 + }, + { + "id": 10485, + "emoji": "🥹", + "count": 5 + }, + { + "id": 59065, + "emoji": "👍", + "count": 7 + } + ] + }, + { + "id": 26744, + "name": "이병헌", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-03-23T03:14:00Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 71764, + "recipientId": 26744, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/311/200/200", + "relationship": "친구", + "content": "전지현님의 메세지 내용 72", + "font": "Roboto", + "createdAt": "2023-05-07T16:58:02Z" + }, + { + "id": 64322, + "recipientId": 26744, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/6/200/200", + "relationship": "친구", + "content": "현빈님의 메세지 내용 11", + "font": "Roboto", + "createdAt": "2023-12-03T19:24:09Z" + }, + { + "id": 94348, + "recipientId": 26744, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/84/200/200", + "relationship": "친구", + "content": "최민수님의 메세지 내용 100", + "font": "Pretendard", + "createdAt": "2023-11-23T06:33:34Z" + } + ], + "reactionCount": 96, + "topReactions": [ + { + "id": 43701, + "emoji": "😁", + "count": 11 + }, + { + "id": 56499, + "emoji": "🎉", + "count": 3 + }, + { + "id": 84055, + "emoji": "😀", + "count": 11 + }, + { + "id": 17678, + "emoji": "🥹", + "count": 15 + }, + { + "id": 79009, + "emoji": "❤️", + "count": 17 + }, + { + "id": 77257, + "emoji": "😀", + "count": 8 + } + ] + }, + { + "id": 93103, + "name": "현빈", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/93103/600/400", + "createdAt": "2023-01-01T05:08:24Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 5540, + "recipientId": 93103, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/74/200/200", + "relationship": "동료", + "content": "최민수님의 메세지 내용 49", + "font": "Nanum Gothic", + "createdAt": "2023-03-28T10:31:32Z" + }, + { + "id": 50339, + "recipientId": 93103, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/74/200/200", + "relationship": "지인", + "content": "박서준님의 메세지 내용 12", + "font": "Noto Sans", + "createdAt": "2023-10-03T18:22:10Z" + }, + { + "id": 75277, + "recipientId": 93103, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/165/200/200", + "relationship": "친구", + "content": "김하은님의 메세지 내용 17", + "font": "Roboto", + "createdAt": "2023-07-28T04:12:32Z" + } + ], + "reactionCount": 57, + "topReactions": [ + { + "id": 14687, + "emoji": "😀", + "count": 19 + }, + { + "id": 39344, + "emoji": "👍", + "count": 7 + }, + { + "id": 34161, + "emoji": "🎉", + "count": 13 + }, + { + "id": 35565, + "emoji": "🎉", + "count": 16 + } + ] + }, + { + "id": 90477, + "name": "현빈", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/90477/600/400", + "createdAt": "2023-03-02T13:15:54Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 35228, + "recipientId": 90477, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/94/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 63", + "font": "Roboto", + "createdAt": "2023-05-25T06:02:55Z" + }, + { + "id": 50401, + "recipientId": 90477, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/89/200/200", + "relationship": "동료", + "content": "현빈님의 메세지 내용 84", + "font": "Pretendard", + "createdAt": "2024-01-09T23:38:08Z" + }, + { + "id": 95955, + "recipientId": 90477, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/472/200/200", + "relationship": "친구", + "content": "최민수님의 메세지 내용 21", + "font": "Pretendard", + "createdAt": "2023-08-01T20:07:21Z" + } + ], + "reactionCount": 96, + "topReactions": [ + { + "id": 23630, + "emoji": "🥹", + "count": 19 + }, + { + "id": 94766, + "emoji": "😁", + "count": 3 + }, + { + "id": 59725, + "emoji": "😀", + "count": 19 + } + ] + }, + { + "id": 82677, + "name": "김하은", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/82677/600/400", + "createdAt": "2023-02-13T13:40:06Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 90214, + "recipientId": 82677, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/195/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 99", + "font": "Pretendard", + "createdAt": "2023-07-17T22:33:03Z" + }, + { + "id": 9562, + "recipientId": 82677, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/92/200/200", + "relationship": "지인", + "content": "한지민님의 메세지 내용 67", + "font": "Roboto", + "createdAt": "2023-07-31T01:08:53Z" + }, + { + "id": 84870, + "recipientId": 82677, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/420/200/200", + "relationship": "동료", + "content": "현빈님의 메세지 내용 46", + "font": "Roboto", + "createdAt": "2023-12-17T05:44:51Z" + } + ], + "reactionCount": 76, + "topReactions": [ + { + "id": 15262, + "emoji": "😀", + "count": 8 + }, + { + "id": 76672, + "emoji": "👍", + "count": 12 + }, + { + "id": 85829, + "emoji": "😀", + "count": 14 + }, + { + "id": 86733, + "emoji": "❤️", + "count": 13 + } + ] + }, + { + "id": 92597, + "name": "현빈", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/92597/600/400", + "createdAt": "2023-06-08T00:17:35Z", + "messageCount": 3, + "recentMessages": [ + { + "id": 32441, + "recipientId": 92597, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/130/200/200", + "relationship": "동료", + "content": "송혜교님의 메세지 내용 20", + "font": "Nanum Gothic", + "createdAt": "2023-03-13T15:52:33Z" + }, + { + "id": 30686, + "recipientId": 92597, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/301/200/200", + "relationship": "가족", + "content": "박서준님의 메세지 내용 76", + "font": "Roboto", + "createdAt": "2023-05-31T09:51:47Z" + }, + { + "id": 65036, + "recipientId": 92597, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/20/200/200", + "relationship": "가족", + "content": "전지현님의 메세지 내용 72", + "font": "Pretendard", + "createdAt": "2023-12-21T10:58:20Z" + } + ], + "reactionCount": 54, + "topReactions": [ + { + "id": 74781, + "emoji": "🎉", + "count": 3 + }, + { + "id": 8118, + "emoji": "😁", + "count": 19 + }, + { + "id": 42107, + "emoji": "🥹", + "count": 7 + } + ] + }, + { + "id": 86205, + "name": "최민수", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-11-27T17:51:50Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 96831, + "recipientId": 86205, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/348/200/200", + "relationship": "친구", + "content": "전지현님의 메세지 내용 44", + "font": "Roboto", + "createdAt": "2023-08-13T20:07:55Z" + }, + { + "id": 20859, + "recipientId": 86205, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/266/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 81", + "font": "Noto Sans", + "createdAt": "2023-04-17T18:16:14Z" + }, + { + "id": 55279, + "recipientId": 86205, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/483/200/200", + "relationship": "가족", + "content": "현빈님의 메세지 내용 69", + "font": "Noto Sans", + "createdAt": "2024-01-27T19:13:38Z" + } + ], + "reactionCount": 89, + "topReactions": [ + { + "id": 12830, + "emoji": "🥹", + "count": 5 + }, + { + "id": 70733, + "emoji": "😁", + "count": 8 + } + ] + }, + { + "id": 83780, + "name": "송혜교", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-02-24T11:43:37Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 10008, + "recipientId": 83780, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/464/200/200", + "relationship": "동료", + "content": "한지민님의 메세지 내용 84", + "font": "Roboto", + "createdAt": "2024-01-11T21:23:27Z" + }, + { + "id": 6414, + "recipientId": 83780, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/104/200/200", + "relationship": "지인", + "content": "전지현님의 메세지 내용 56", + "font": "Roboto", + "createdAt": "2023-01-11T02:47:15Z" + }, + { + "id": 5190, + "recipientId": 83780, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/119/200/200", + "relationship": "친구", + "content": "최민수님의 메세지 내용 2", + "font": "Pretendard", + "createdAt": "2023-04-24T17:49:24Z" + } + ], + "reactionCount": 81, + "topReactions": [ + { + "id": 1589, + "emoji": "🥹", + "count": 15 + }, + { + "id": 78183, + "emoji": "🎉", + "count": 19 + }, + { + "id": 22247, + "emoji": "🎉", + "count": 1 + }, + { + "id": 19112, + "emoji": "🥹", + "count": 17 + } + ] + }, + { + "id": 38229, + "name": "송혜교", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/38229/600/400", + "createdAt": "2023-01-30T14:18:54Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 51942, + "recipientId": 38229, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/134/200/200", + "relationship": "지인", + "content": "현빈님의 메세지 내용 54", + "font": "Nanum Gothic", + "createdAt": "2023-03-20T04:36:24Z" + }, + { + "id": 86324, + "recipientId": 38229, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/233/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 86", + "font": "Nanum Gothic", + "createdAt": "2023-10-10T17:45:30Z" + }, + { + "id": 90356, + "recipientId": 38229, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/229/200/200", + "relationship": "친구", + "content": "최민수님의 메세지 내용 59", + "font": "Nanum Gothic", + "createdAt": "2023-03-24T14:49:12Z" + } + ], + "reactionCount": 59, + "topReactions": [ + { + "id": 34874, + "emoji": "❤️", + "count": 15 + }, + { + "id": 26479, + "emoji": "😁", + "count": 1 + }, + { + "id": 35105, + "emoji": "🎉", + "count": 18 + }, + { + "id": 6384, + "emoji": "😀", + "count": 13 + }, + { + "id": 70298, + "emoji": "🥹", + "count": 9 + }, + { + "id": 48862, + "emoji": "😁", + "count": 11 + } + ] + }, + { + "id": 31714, + "name": "이병헌", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/31714/600/400", + "createdAt": "2023-01-13T08:26:56Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 13368, + "recipientId": 31714, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/274/200/200", + "relationship": "동료", + "content": "송혜교님의 메세지 내용 54", + "font": "Nanum Gothic", + "createdAt": "2023-08-29T23:09:43Z" + } + ], + "reactionCount": 15, + "topReactions": [ + { + "id": 84856, + "emoji": "😀", + "count": 2 + }, + { + "id": 37418, + "emoji": "😁", + "count": 16 + }, + { + "id": 68962, + "emoji": "🥹", + "count": 16 + }, + { + "id": 63309, + "emoji": "🥹", + "count": 8 + } + ] + }, + { + "id": 24976, + "name": "전지현", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-12-12T12:27:23Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 21316, + "recipientId": 24976, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/106/200/200", + "relationship": "지인", + "content": "이영준님의 메세지 내용 56", + "font": "Roboto", + "createdAt": "2023-01-09T20:33:19Z" + }, + { + "id": 58002, + "recipientId": 24976, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/183/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 81", + "font": "Roboto", + "createdAt": "2023-01-08T15:28:27Z" + }, + { + "id": 88820, + "recipientId": 24976, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/355/200/200", + "relationship": "동료", + "content": "이병헌님의 메세지 내용 72", + "font": "Pretendard", + "createdAt": "2023-12-02T16:28:28Z" + } + ], + "reactionCount": 14, + "topReactions": [ + { + "id": 23520, + "emoji": "😁", + "count": 1 + }, + { + "id": 1327, + "emoji": "🎉", + "count": 6 + }, + { + "id": 99333, + "emoji": "😀", + "count": 7 + }, + { + "id": 24221, + "emoji": "😁", + "count": 8 + }, + { + "id": 34796, + "emoji": "👍", + "count": 13 + }, + { + "id": 24544, + "emoji": "🎉", + "count": 5 + } + ] + }, + { + "id": 13246, + "name": "현빈", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/13246/600/400", + "createdAt": "2024-01-28T13:20:43Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 5106, + "recipientId": 13246, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/198/200/200", + "relationship": "동료", + "content": "현빈님의 메세지 내용 81", + "font": "Nanum Gothic", + "createdAt": "2023-08-15T19:24:32Z" + }, + { + "id": 14675, + "recipientId": 13246, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/378/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 100", + "font": "Nanum Gothic", + "createdAt": "2023-12-09T18:47:45Z" + }, + { + "id": 88634, + "recipientId": 13246, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/286/200/200", + "relationship": "가족", + "content": "김하은님의 메세지 내용 3", + "font": "Pretendard", + "createdAt": "2023-06-16T01:43:57Z" + } + ], + "reactionCount": 26, + "topReactions": [ + { + "id": 67233, + "emoji": "🥹", + "count": 18 + }, + { + "id": 15477, + "emoji": "😁", + "count": 6 + }, + { + "id": 52552, + "emoji": "😁", + "count": 2 + }, + { + "id": 4534, + "emoji": "❤️", + "count": 5 + }, + { + "id": 81700, + "emoji": "🎉", + "count": 5 + } + ] + }, + { + "id": 80427, + "name": "김하은", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-07-18T23:35:46Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 27419, + "recipientId": 80427, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/496/200/200", + "relationship": "지인", + "content": "김하은님의 메세지 내용 32", + "font": "Pretendard", + "createdAt": "2023-04-12T22:20:48Z" + }, + { + "id": 6424, + "recipientId": 80427, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/148/200/200", + "relationship": "동료", + "content": "이영준님의 메세지 내용 81", + "font": "Noto Sans", + "createdAt": "2024-01-17T02:57:29Z" + }, + { + "id": 80098, + "recipientId": 80427, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/163/200/200", + "relationship": "동료", + "content": "한지민님의 메세지 내용 100", + "font": "Noto Sans", + "createdAt": "2023-07-13T01:55:00Z" + } + ], + "reactionCount": 60, + "topReactions": [ + { + "id": 67321, + "emoji": "😀", + "count": 10 + }, + { + "id": 37472, + "emoji": "🥹", + "count": 12 + }, + { + "id": 38481, + "emoji": "😁", + "count": 5 + }, + { + "id": 10179, + "emoji": "😁", + "count": 14 + } + ] + }, + { + "id": 9191, + "name": "박서준", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/9191/600/400", + "createdAt": "2023-12-26T20:03:21Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 35658, + "recipientId": 9191, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/62/200/200", + "relationship": "동료", + "content": "이병헌님의 메세지 내용 27", + "font": "Nanum Gothic", + "createdAt": "2023-04-09T12:56:46Z" + }, + { + "id": 20743, + "recipientId": 9191, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/59/200/200", + "relationship": "동료", + "content": "송혜교님의 메세지 내용 23", + "font": "Noto Sans", + "createdAt": "2023-05-09T21:29:01Z" + }, + { + "id": 20041, + "recipientId": 9191, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/114/200/200", + "relationship": "가족", + "content": "이병헌님의 메세지 내용 72", + "font": "Pretendard", + "createdAt": "2023-11-11T12:43:30Z" + } + ], + "reactionCount": 90, + "topReactions": [ + { + "id": 46794, + "emoji": "🎉", + "count": 2 + }, + { + "id": 78569, + "emoji": "😁", + "count": 20 + }, + { + "id": 71969, + "emoji": "😀", + "count": 14 + }, + { + "id": 8787, + "emoji": "❤️", + "count": 10 + }, + { + "id": 56094, + "emoji": "🥹", + "count": 3 + }, + { + "id": 4661, + "emoji": "😁", + "count": 6 + } + ] + }, + { + "id": 80709, + "name": "전지현", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/80709/600/400", + "createdAt": "2023-10-26T20:03:42Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 29605, + "recipientId": 80709, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/86/200/200", + "relationship": "친구", + "content": "전지현님의 메세지 내용 27", + "font": "Pretendard", + "createdAt": "2023-07-06T04:37:31Z" + }, + { + "id": 50599, + "recipientId": 80709, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/117/200/200", + "relationship": "가족", + "content": "박서준님의 메세지 내용 12", + "font": "Pretendard", + "createdAt": "2023-06-10T14:25:31Z" + } + ], + "reactionCount": 53, + "topReactions": [ + { + "id": 33992, + "emoji": "🎉", + "count": 13 + } + ] + }, + { + "id": 625, + "name": "전지현", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/625/600/400", + "createdAt": "2023-12-14T02:55:26Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 59897, + "recipientId": 625, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/411/200/200", + "relationship": "동료", + "content": "전지현님의 메세지 내용 99", + "font": "Nanum Gothic", + "createdAt": "2023-03-12T00:35:57Z" + }, + { + "id": 53736, + "recipientId": 625, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/411/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 98", + "font": "Nanum Gothic", + "createdAt": "2023-06-06T17:47:12Z" + }, + { + "id": 9641, + "recipientId": 625, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/498/200/200", + "relationship": "지인", + "content": "김하은님의 메세지 내용 66", + "font": "Pretendard", + "createdAt": "2023-07-05T12:51:17Z" + } + ], + "reactionCount": 66, + "topReactions": [ + { + "id": 36713, + "emoji": "❤️", + "count": 2 + }, + { + "id": 89567, + "emoji": "🥹", + "count": 2 + }, + { + "id": 98915, + "emoji": "🥹", + "count": 7 + }, + { + "id": 6789, + "emoji": "😁", + "count": 10 + } + ] + }, + { + "id": 23417, + "name": "최민수", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/23417/600/400", + "createdAt": "2023-09-15T03:16:30Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 82536, + "recipientId": 23417, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/236/200/200", + "relationship": "동료", + "content": "정우성님의 메세지 내용 76", + "font": "Roboto", + "createdAt": "2023-03-05T16:15:27Z" + }, + { + "id": 22812, + "recipientId": 23417, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/441/200/200", + "relationship": "친구", + "content": "현빈님의 메세지 내용 10", + "font": "Pretendard", + "createdAt": "2023-07-09T04:44:48Z" + }, + { + "id": 53607, + "recipientId": 23417, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/402/200/200", + "relationship": "지인", + "content": "이병헌님의 메세지 내용 96", + "font": "Noto Sans", + "createdAt": "2023-06-28T04:25:20Z" + } + ], + "reactionCount": 42, + "topReactions": [ + { + "id": 2457, + "emoji": "👍", + "count": 10 + }, + { + "id": 86246, + "emoji": "❤️", + "count": 2 + }, + { + "id": 54698, + "emoji": "❤️", + "count": 7 + }, + { + "id": 72375, + "emoji": "😀", + "count": 2 + }, + { + "id": 7835, + "emoji": "😁", + "count": 1 + } + ] + }, + { + "id": 60892, + "name": "최민수", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/60892/600/400", + "createdAt": "2023-11-21T04:18:37Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 18337, + "recipientId": 60892, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/99/200/200", + "relationship": "동료", + "content": "송혜교님의 메세지 내용 47", + "font": "Nanum Gothic", + "createdAt": "2023-04-10T16:57:19Z" + }, + { + "id": 88221, + "recipientId": 60892, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/477/200/200", + "relationship": "친구", + "content": "현빈님의 메세지 내용 35", + "font": "Noto Sans", + "createdAt": "2023-05-10T18:53:49Z" + }, + { + "id": 97322, + "recipientId": 60892, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/146/200/200", + "relationship": "가족", + "content": "한지민님의 메세지 내용 17", + "font": "Pretendard", + "createdAt": "2023-09-10T05:52:40Z" + } + ], + "reactionCount": 51, + "topReactions": [ + { + "id": 60510, + "emoji": "😁", + "count": 5 + }, + { + "id": 183, + "emoji": "😀", + "count": 12 + }, + { + "id": 70387, + "emoji": "❤️", + "count": 5 + }, + { + "id": 5940, + "emoji": "🥹", + "count": 20 + }, + { + "id": 69316, + "emoji": "🎉", + "count": 2 + } + ] + }, + { + "id": 77216, + "name": "송혜교", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-03-12T09:36:47Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 20785, + "recipientId": 77216, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/163/200/200", + "relationship": "동료", + "content": "송혜교님의 메세지 내용 58", + "font": "Noto Sans", + "createdAt": "2023-07-17T16:37:49Z" + }, + { + "id": 1433, + "recipientId": 77216, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/379/200/200", + "relationship": "가족", + "content": "한지민님의 메세지 내용 21", + "font": "Pretendard", + "createdAt": "2023-08-26T07:59:50Z" + }, + { + "id": 8255, + "recipientId": 77216, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/492/200/200", + "relationship": "가족", + "content": "현빈님의 메세지 내용 85", + "font": "Nanum Gothic", + "createdAt": "2023-11-20T17:06:48Z" + } + ], + "reactionCount": 6, + "topReactions": [ + { + "id": 52593, + "emoji": "🥹", + "count": 1 + }, + { + "id": 49827, + "emoji": "🎉", + "count": 12 + }, + { + "id": 3837, + "emoji": "👍", + "count": 9 + } + ] + }, + { + "id": 48647, + "name": "현빈", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-11-16T13:18:03Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 76625, + "recipientId": 48647, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/256/200/200", + "relationship": "가족", + "content": "이병헌님의 메세지 내용 98", + "font": "Pretendard", + "createdAt": "2023-03-21T02:42:08Z" + }, + { + "id": 43638, + "recipientId": 48647, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/410/200/200", + "relationship": "가족", + "content": "현빈님의 메세지 내용 41", + "font": "Noto Sans", + "createdAt": "2023-04-24T22:09:02Z" + }, + { + "id": 26804, + "recipientId": 48647, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/347/200/200", + "relationship": "친구", + "content": "전지현님의 메세지 내용 88", + "font": "Pretendard", + "createdAt": "2024-01-08T19:39:50Z" + } + ], + "reactionCount": 28, + "topReactions": [ + { + "id": 38782, + "emoji": "🎉", + "count": 10 + }, + { + "id": 30497, + "emoji": "❤️", + "count": 20 + }, + { + "id": 65578, + "emoji": "😀", + "count": 11 + }, + { + "id": 54351, + "emoji": "❤️", + "count": 2 + } + ] + }, + { + "id": 7110, + "name": "전지현", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-10-20T12:41:27Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 90888, + "recipientId": 7110, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/19/200/200", + "relationship": "지인", + "content": "이병헌님의 메세지 내용 42", + "font": "Roboto", + "createdAt": "2023-09-16T18:15:50Z" + }, + { + "id": 11380, + "recipientId": 7110, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/373/200/200", + "relationship": "동료", + "content": "이영준님의 메세지 내용 42", + "font": "Roboto", + "createdAt": "2023-04-14T16:26:10Z" + }, + { + "id": 26575, + "recipientId": 7110, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/184/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 65", + "font": "Pretendard", + "createdAt": "2023-07-31T19:38:34Z" + } + ], + "reactionCount": 75, + "topReactions": [ + { + "id": 71539, + "emoji": "👍", + "count": 15 + }, + { + "id": 86386, + "emoji": "❤️", + "count": 4 + }, + { + "id": 81736, + "emoji": "🎉", + "count": 12 + }, + { + "id": 63021, + "emoji": "❤️", + "count": 13 + } + ] + }, + { + "id": 45995, + "name": "이영준", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-09-30T01:37:16Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 62949, + "recipientId": 45995, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/270/200/200", + "relationship": "가족", + "content": "김하은님의 메세지 내용 52", + "font": "Pretendard", + "createdAt": "2023-12-26T22:51:46Z" + }, + { + "id": 54691, + "recipientId": 45995, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/148/200/200", + "relationship": "가족", + "content": "전지현님의 메세지 내용 77", + "font": "Pretendard", + "createdAt": "2023-12-25T22:42:52Z" + }, + { + "id": 41428, + "recipientId": 45995, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/13/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 11", + "font": "Roboto", + "createdAt": "2023-04-15T01:57:19Z" + } + ], + "reactionCount": 52, + "topReactions": [ + { + "id": 21041, + "emoji": "❤️", + "count": 3 + }, + { + "id": 81901, + "emoji": "🎉", + "count": 20 + }, + { + "id": 3660, + "emoji": "🥹", + "count": 7 + } + ] + }, + { + "id": 75973, + "name": "이병헌", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/75973/600/400", + "createdAt": "2023-04-29T23:14:33Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 85401, + "recipientId": 75973, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/269/200/200", + "relationship": "동료", + "content": "이병헌님의 메세지 내용 90", + "font": "Noto Sans", + "createdAt": "2023-11-12T05:17:44Z" + }, + { + "id": 35095, + "recipientId": 75973, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/390/200/200", + "relationship": "친구", + "content": "송혜교님의 메세지 내용 74", + "font": "Roboto", + "createdAt": "2023-10-05T14:15:30Z" + }, + { + "id": 99991, + "recipientId": 75973, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/240/200/200", + "relationship": "지인", + "content": "김하은님의 메세지 내용 17", + "font": "Nanum Gothic", + "createdAt": "2023-09-17T18:51:27Z" + } + ], + "reactionCount": 27, + "topReactions": [ + { + "id": 98483, + "emoji": "🥹", + "count": 5 + }, + { + "id": 73979, + "emoji": "🥹", + "count": 7 + }, + { + "id": 14149, + "emoji": "🥹", + "count": 4 + }, + { + "id": 73714, + "emoji": "😁", + "count": 11 + } + ] + }, + { + "id": 61839, + "name": "최민수", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/61839/600/400", + "createdAt": "2023-08-11T13:58:13Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 76692, + "recipientId": 61839, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/257/200/200", + "relationship": "지인", + "content": "정우성님의 메세지 내용 71", + "font": "Roboto", + "createdAt": "2023-04-13T09:59:09Z" + }, + { + "id": 94381, + "recipientId": 61839, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/344/200/200", + "relationship": "가족", + "content": "이영준님의 메세지 내용 63", + "font": "Noto Sans", + "createdAt": "2023-03-28T05:18:11Z" + }, + { + "id": 56587, + "recipientId": 61839, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/194/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 92", + "font": "Pretendard", + "createdAt": "2023-02-13T15:44:01Z" + } + ], + "reactionCount": 54, + "topReactions": [ + { + "id": 84273, + "emoji": "🥹", + "count": 18 + }, + { + "id": 67980, + "emoji": "😀", + "count": 19 + }, + { + "id": 57293, + "emoji": "🥹", + "count": 9 + } + ] + }, + { + "id": 17028, + "name": "박서준", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-10-12T01:14:00Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 80146, + "recipientId": 17028, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/273/200/200", + "relationship": "가족", + "content": "정우성님의 메세지 내용 50", + "font": "Nanum Gothic", + "createdAt": "2023-08-20T23:27:16Z" + }, + { + "id": 45410, + "recipientId": 17028, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/371/200/200", + "relationship": "지인", + "content": "박서준님의 메세지 내용 22", + "font": "Nanum Gothic", + "createdAt": "2023-03-05T19:49:12Z" + }, + { + "id": 72881, + "recipientId": 17028, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/471/200/200", + "relationship": "친구", + "content": "전지현님의 메세지 내용 45", + "font": "Nanum Gothic", + "createdAt": "2024-01-21T18:46:39Z" + } + ], + "reactionCount": 66, + "topReactions": [ + { + "id": 48674, + "emoji": "😁", + "count": 16 + }, + { + "id": 8548, + "emoji": "😀", + "count": 6 + }, + { + "id": 43006, + "emoji": "😁", + "count": 15 + }, + { + "id": 6573, + "emoji": "😁", + "count": 6 + }, + { + "id": 57200, + "emoji": "😀", + "count": 1 + } + ] + }, + { + "id": 58041, + "name": "최민수", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/58041/600/400", + "createdAt": "2023-04-05T19:24:00Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 44629, + "recipientId": 58041, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/385/200/200", + "relationship": "가족", + "content": "한지민님의 메세지 내용 51", + "font": "Pretendard", + "createdAt": "2024-01-26T15:26:36Z" + }, + { + "id": 78779, + "recipientId": 58041, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/86/200/200", + "relationship": "가족", + "content": "정우성님의 메세지 내용 54", + "font": "Nanum Gothic", + "createdAt": "2023-04-15T11:17:51Z" + }, + { + "id": 48497, + "recipientId": 58041, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/17/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 56", + "font": "Roboto", + "createdAt": "2023-04-05T00:53:28Z" + } + ], + "reactionCount": 48, + "topReactions": [ + { + "id": 214, + "emoji": "👍", + "count": 3 + }, + { + "id": 16801, + "emoji": "😀", + "count": 1 + }, + { + "id": 64372, + "emoji": "❤️", + "count": 18 + }, + { + "id": 4933, + "emoji": "🎉", + "count": 4 + } + ] + }, + { + "id": 75495, + "name": "현빈", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-05-01T13:49:11Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 43732, + "recipientId": 75495, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/7/200/200", + "relationship": "지인", + "content": "박서준님의 메세지 내용 78", + "font": "Roboto", + "createdAt": "2023-02-07T09:31:01Z" + }, + { + "id": 49379, + "recipientId": 75495, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/332/200/200", + "relationship": "가족", + "content": "김하은님의 메세지 내용 21", + "font": "Roboto", + "createdAt": "2024-02-05T01:17:08Z" + }, + { + "id": 71393, + "recipientId": 75495, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/126/200/200", + "relationship": "가족", + "content": "이영준님의 메세지 내용 48", + "font": "Noto Sans", + "createdAt": "2023-01-26T06:27:51Z" + } + ], + "reactionCount": 55, + "topReactions": [ + { + "id": 1802, + "emoji": "😀", + "count": 10 + }, + { + "id": 94631, + "emoji": "🎉", + "count": 17 + }, + { + "id": 42577, + "emoji": "❤️", + "count": 6 + }, + { + "id": 83907, + "emoji": "🎉", + "count": 6 + } + ] + }, + { + "id": 87390, + "name": "이영준", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-05-14T14:22:59Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 78211, + "recipientId": 87390, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/382/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 5", + "font": "Noto Sans", + "createdAt": "2023-09-05T09:24:06Z" + }, + { + "id": 28440, + "recipientId": 87390, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/360/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 77", + "font": "Pretendard", + "createdAt": "2023-12-12T04:25:04Z" + }, + { + "id": 82273, + "recipientId": 87390, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/17/200/200", + "relationship": "지인", + "content": "이영준님의 메세지 내용 50", + "font": "Noto Sans", + "createdAt": "2024-01-03T08:25:32Z" + } + ], + "reactionCount": 6, + "topReactions": [ + { + "id": 14584, + "emoji": "👍", + "count": 16 + }, + { + "id": 64130, + "emoji": "🎉", + "count": 19 + }, + { + "id": 98800, + "emoji": "😀", + "count": 20 + }, + { + "id": 93562, + "emoji": "😁", + "count": 13 + } + ] + }, + { + "id": 38320, + "name": "송혜교", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/38320/600/400", + "createdAt": "2023-08-11T20:43:38Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 37599, + "recipientId": 38320, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/36/200/200", + "relationship": "친구", + "content": "송혜교님의 메세지 내용 46", + "font": "Noto Sans", + "createdAt": "2023-10-23T14:59:02Z" + }, + { + "id": 29674, + "recipientId": 38320, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/441/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 48", + "font": "Nanum Gothic", + "createdAt": "2023-02-06T21:23:13Z" + }, + { + "id": 32572, + "recipientId": 38320, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/197/200/200", + "relationship": "가족", + "content": "박서준님의 메세지 내용 38", + "font": "Nanum Gothic", + "createdAt": "2023-12-03T06:30:07Z" + } + ], + "reactionCount": 24, + "topReactions": [ + { + "id": 85440, + "emoji": "😀", + "count": 4 + }, + { + "id": 94784, + "emoji": "❤️", + "count": 3 + }, + { + "id": 65361, + "emoji": "👍", + "count": 12 + }, + { + "id": 74494, + "emoji": "🥹", + "count": 2 + }, + { + "id": 20433, + "emoji": "🥹", + "count": 2 + } + ] + }, + { + "id": 35660, + "name": "이영준", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-12-15T20:22:31Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 94600, + "recipientId": 35660, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/203/200/200", + "relationship": "지인", + "content": "한지민님의 메세지 내용 33", + "font": "Roboto", + "createdAt": "2023-02-08T07:18:43Z" + }, + { + "id": 55920, + "recipientId": 35660, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/386/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 98", + "font": "Nanum Gothic", + "createdAt": "2023-09-22T08:00:11Z" + }, + { + "id": 18674, + "recipientId": 35660, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/308/200/200", + "relationship": "친구", + "content": "송혜교님의 메세지 내용 9", + "font": "Nanum Gothic", + "createdAt": "2023-11-03T06:40:58Z" + } + ], + "reactionCount": 65, + "topReactions": [ + { + "id": 4983, + "emoji": "😀", + "count": 20 + }, + { + "id": 91060, + "emoji": "❤️", + "count": 2 + } + ] + }, + { + "id": 32314, + "name": "이병헌", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-06-09T07:16:23Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 89356, + "recipientId": 32314, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/104/200/200", + "relationship": "동료", + "content": "현빈님의 메세지 내용 25", + "font": "Nanum Gothic", + "createdAt": "2023-12-02T19:32:52Z" + }, + { + "id": 10034, + "recipientId": 32314, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/288/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 22", + "font": "Pretendard", + "createdAt": "2023-09-14T13:27:24Z" + }, + { + "id": 75054, + "recipientId": 32314, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/483/200/200", + "relationship": "가족", + "content": "김하은님의 메세지 내용 25", + "font": "Pretendard", + "createdAt": "2023-03-09T17:03:28Z" + } + ], + "reactionCount": 59, + "topReactions": [ + { + "id": 58698, + "emoji": "😀", + "count": 13 + } + ] + }, + { + "id": 43043, + "name": "송혜교", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/43043/600/400", + "createdAt": "2023-02-22T13:08:51Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 47574, + "recipientId": 43043, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/63/200/200", + "relationship": "친구", + "content": "현빈님의 메세지 내용 2", + "font": "Noto Sans", + "createdAt": "2023-08-29T05:01:20Z" + }, + { + "id": 38817, + "recipientId": 43043, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/439/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 21", + "font": "Noto Sans", + "createdAt": "2023-04-16T03:40:54Z" + }, + { + "id": 16978, + "recipientId": 43043, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/425/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 17", + "font": "Pretendard", + "createdAt": "2023-11-16T09:47:54Z" + } + ], + "reactionCount": 16, + "topReactions": [ + { + "id": 7801, + "emoji": "😁", + "count": 12 + }, + { + "id": 58961, + "emoji": "❤️", + "count": 16 + }, + { + "id": 59283, + "emoji": "🥹", + "count": 5 + } + ] + }, + { + "id": 45937, + "name": "김하은", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2024-01-22T12:24:12Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 5896, + "recipientId": 45937, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/38/200/200", + "relationship": "가족", + "content": "한지민님의 메세지 내용 44", + "font": "Pretendard", + "createdAt": "2023-12-13T13:33:23Z" + }, + { + "id": 49858, + "recipientId": 45937, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/367/200/200", + "relationship": "가족", + "content": "한지민님의 메세지 내용 7", + "font": "Roboto", + "createdAt": "2023-09-15T13:57:29Z" + }, + { + "id": 49667, + "recipientId": 45937, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/407/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 34", + "font": "Noto Sans", + "createdAt": "2023-07-28T02:57:58Z" + } + ], + "reactionCount": 37, + "topReactions": [ + { + "id": 11248, + "emoji": "❤️", + "count": 3 + } + ] + }, + { + "id": 63219, + "name": "이영준", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/63219/600/400", + "createdAt": "2023-06-12T11:10:34Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 75822, + "recipientId": 63219, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/119/200/200", + "relationship": "친구", + "content": "최민수님의 메세지 내용 59", + "font": "Roboto", + "createdAt": "2023-04-03T20:37:21Z" + }, + { + "id": 49459, + "recipientId": 63219, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/181/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 83", + "font": "Pretendard", + "createdAt": "2023-11-12T23:18:57Z" + }, + { + "id": 50489, + "recipientId": 63219, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/11/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 77", + "font": "Noto Sans", + "createdAt": "2023-11-27T08:16:32Z" + } + ], + "reactionCount": 17, + "topReactions": [ + { + "id": 78228, + "emoji": "🥹", + "count": 4 + }, + { + "id": 93441, + "emoji": "🥹", + "count": 10 + } + ] + }, + { + "id": 32218, + "name": "이병헌", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-07-22T22:33:51Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 68615, + "recipientId": 32218, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/279/200/200", + "relationship": "가족", + "content": "이영준님의 메세지 내용 35", + "font": "Nanum Gothic", + "createdAt": "2023-01-19T15:23:35Z" + }, + { + "id": 42475, + "recipientId": 32218, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/15/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 9", + "font": "Nanum Gothic", + "createdAt": "2023-10-23T06:35:16Z" + }, + { + "id": 84692, + "recipientId": 32218, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/335/200/200", + "relationship": "친구", + "content": "현빈님의 메세지 내용 43", + "font": "Noto Sans", + "createdAt": "2023-06-03T21:56:10Z" + } + ], + "reactionCount": 47, + "topReactions": [ + { + "id": 88844, + "emoji": "🎉", + "count": 16 + }, + { + "id": 58724, + "emoji": "👍", + "count": 19 + }, + { + "id": 26471, + "emoji": "👍", + "count": 5 + }, + { + "id": 39423, + "emoji": "😁", + "count": 15 + }, + { + "id": 68714, + "emoji": "👍", + "count": 6 + } + ] + }, + { + "id": 80991, + "name": "정우성", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-10-23T18:52:08Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 84011, + "recipientId": 80991, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/258/200/200", + "relationship": "지인", + "content": "전지현님의 메세지 내용 18", + "font": "Nanum Gothic", + "createdAt": "2023-06-07T13:22:14Z" + }, + { + "id": 35058, + "recipientId": 80991, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/223/200/200", + "relationship": "친구", + "content": "최민수님의 메세지 내용 70", + "font": "Pretendard", + "createdAt": "2023-01-22T04:44:31Z" + }, + { + "id": 9223, + "recipientId": 80991, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/474/200/200", + "relationship": "친구", + "content": "이영준님의 메세지 내용 97", + "font": "Nanum Gothic", + "createdAt": "2023-03-05T23:34:32Z" + } + ], + "reactionCount": 2, + "topReactions": [ + { + "id": 42141, + "emoji": "👍", + "count": 19 + } + ] + }, + { + "id": 1341, + "name": "송혜교", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-07-12T16:03:05Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 3046, + "recipientId": 1341, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/167/200/200", + "relationship": "친구", + "content": "현빈님의 메세지 내용 93", + "font": "Roboto", + "createdAt": "2023-11-10T18:21:23Z" + }, + { + "id": 47841, + "recipientId": 1341, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/186/200/200", + "relationship": "지인", + "content": "박서준님의 메세지 내용 51", + "font": "Noto Sans", + "createdAt": "2023-07-15T12:17:59Z" + }, + { + "id": 24988, + "recipientId": 1341, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/423/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 64", + "font": "Roboto", + "createdAt": "2023-01-06T05:53:05Z" + } + ], + "reactionCount": 95, + "topReactions": [ + { + "id": 39502, + "emoji": "🎉", + "count": 11 + } + ] + }, + { + "id": 6051, + "name": "정우성", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/6051/600/400", + "createdAt": "2023-11-10T15:09:44Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 7288, + "recipientId": 6051, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/156/200/200", + "relationship": "지인", + "content": "송혜교님의 메세지 내용 39", + "font": "Noto Sans", + "createdAt": "2023-07-23T06:22:45Z" + }, + { + "id": 13782, + "recipientId": 6051, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/433/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 100", + "font": "Pretendard", + "createdAt": "2023-02-11T22:46:47Z" + }, + { + "id": 33148, + "recipientId": 6051, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/442/200/200", + "relationship": "동료", + "content": "한지민님의 메세지 내용 35", + "font": "Nanum Gothic", + "createdAt": "2023-08-13T00:23:31Z" + } + ], + "reactionCount": 87, + "topReactions": [ + { + "id": 1723, + "emoji": "🎉", + "count": 3 + }, + { + "id": 7654, + "emoji": "😀", + "count": 8 + }, + { + "id": 29263, + "emoji": "😀", + "count": 4 + } + ] + }, + { + "id": 93438, + "name": "이병헌", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/93438/600/400", + "createdAt": "2023-04-02T11:00:53Z", + "messageCount": 3, + "recentMessages": [ + { + "id": 66472, + "recipientId": 93438, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/333/200/200", + "relationship": "가족", + "content": "전지현님의 메세지 내용 94", + "font": "Nanum Gothic", + "createdAt": "2023-03-26T16:14:53Z" + }, + { + "id": 6156, + "recipientId": 93438, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/109/200/200", + "relationship": "동료", + "content": "이병헌님의 메세지 내용 59", + "font": "Noto Sans", + "createdAt": "2023-01-24T10:30:39Z" + }, + { + "id": 45844, + "recipientId": 93438, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/182/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 33", + "font": "Noto Sans", + "createdAt": "2023-11-23T09:30:34Z" + } + ], + "reactionCount": 99, + "topReactions": [ + { + "id": 19288, + "emoji": "😁", + "count": 11 + } + ] + }, + { + "id": 44334, + "name": "이병헌", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/44334/600/400", + "createdAt": "2023-12-30T01:42:47Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 42994, + "recipientId": 44334, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/465/200/200", + "relationship": "동료", + "content": "정우성님의 메세지 내용 81", + "font": "Roboto", + "createdAt": "2023-02-14T10:13:11Z" + }, + { + "id": 56130, + "recipientId": 44334, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/227/200/200", + "relationship": "동료", + "content": "이영준님의 메세지 내용 25", + "font": "Roboto", + "createdAt": "2023-02-02T18:27:08Z" + }, + { + "id": 41595, + "recipientId": 44334, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/64/200/200", + "relationship": "친구", + "content": "전지현님의 메세지 내용 86", + "font": "Pretendard", + "createdAt": "2023-01-18T09:46:31Z" + } + ], + "reactionCount": 87, + "topReactions": [ + { + "id": 37061, + "emoji": "👍", + "count": 6 + }, + { + "id": 2287, + "emoji": "👍", + "count": 11 + }, + { + "id": 45099, + "emoji": "😀", + "count": 12 + }, + { + "id": 90256, + "emoji": "😁", + "count": 7 + }, + { + "id": 99885, + "emoji": "👍", + "count": 8 + }, + { + "id": 76279, + "emoji": "❤️", + "count": 12 + } + ] + }, + { + "id": 82732, + "name": "최민수", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-01-17T04:31:54Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 97297, + "recipientId": 82732, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/444/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 78", + "font": "Nanum Gothic", + "createdAt": "2023-02-09T10:16:50Z" + }, + { + "id": 71861, + "recipientId": 82732, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/498/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 55", + "font": "Roboto", + "createdAt": "2023-03-15T16:30:09Z" + }, + { + "id": 74035, + "recipientId": 82732, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/36/200/200", + "relationship": "가족", + "content": "박서준님의 메세지 내용 23", + "font": "Roboto", + "createdAt": "2024-01-21T23:20:59Z" + } + ], + "reactionCount": 70, + "topReactions": [ + { + "id": 17950, + "emoji": "🥹", + "count": 20 + } + ] + }, + { + "id": 44928, + "name": "이병헌", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-11-24T12:12:26Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 76155, + "recipientId": 44928, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/40/200/200", + "relationship": "동료", + "content": "전지현님의 메세지 내용 88", + "font": "Pretendard", + "createdAt": "2023-03-16T10:54:28Z" + } + ], + "reactionCount": 8, + "topReactions": [ + { + "id": 82489, + "emoji": "🥹", + "count": 7 + }, + { + "id": 41836, + "emoji": "🥹", + "count": 7 + }, + { + "id": 64846, + "emoji": "❤️", + "count": 9 + }, + { + "id": 50727, + "emoji": "❤️", + "count": 14 + } + ] + }, + { + "id": 94539, + "name": "최민수", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2024-01-11T07:24:22Z", + "messageCount": 3, + "recentMessages": [ + { + "id": 31761, + "recipientId": 94539, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/62/200/200", + "relationship": "가족", + "content": "이병헌님의 메세지 내용 53", + "font": "Pretendard", + "createdAt": "2023-04-17T18:23:36Z" + }, + { + "id": 6032, + "recipientId": 94539, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/230/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 76", + "font": "Noto Sans", + "createdAt": "2023-03-28T17:44:01Z" + }, + { + "id": 79432, + "recipientId": 94539, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/178/200/200", + "relationship": "동료", + "content": "정우성님의 메세지 내용 36", + "font": "Roboto", + "createdAt": "2023-05-31T20:44:54Z" + } + ], + "reactionCount": 92, + "topReactions": [ + { + "id": 73214, + "emoji": "👍", + "count": 14 + }, + { + "id": 314, + "emoji": "😀", + "count": 20 + } + ] + }, + { + "id": 91720, + "name": "한지민", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-12-15T09:41:38Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 44369, + "recipientId": 91720, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/306/200/200", + "relationship": "동료", + "content": "전지현님의 메세지 내용 1", + "font": "Roboto", + "createdAt": "2023-05-14T15:14:24Z" + }, + { + "id": 9488, + "recipientId": 91720, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/61/200/200", + "relationship": "지인", + "content": "한지민님의 메세지 내용 100", + "font": "Nanum Gothic", + "createdAt": "2023-02-20T18:02:40Z" + }, + { + "id": 44680, + "recipientId": 91720, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/40/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 57", + "font": "Roboto", + "createdAt": "2023-09-07T19:51:33Z" + } + ], + "reactionCount": 73, + "topReactions": [ + { + "id": 49624, + "emoji": "😁", + "count": 6 + }, + { + "id": 69914, + "emoji": "😁", + "count": 17 + }, + { + "id": 12300, + "emoji": "👍", + "count": 16 + }, + { + "id": 26416, + "emoji": "🎉", + "count": 12 + } + ] + }, + { + "id": 35251, + "name": "정우성", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-12-25T20:29:41Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 1090, + "recipientId": 35251, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/153/200/200", + "relationship": "동료", + "content": "최민수님의 메세지 내용 98", + "font": "Pretendard", + "createdAt": "2023-01-13T11:39:47Z" + }, + { + "id": 26846, + "recipientId": 35251, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/446/200/200", + "relationship": "가족", + "content": "한지민님의 메세지 내용 85", + "font": "Pretendard", + "createdAt": "2023-03-07T08:41:00Z" + }, + { + "id": 91912, + "recipientId": 35251, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/70/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 94", + "font": "Pretendard", + "createdAt": "2023-07-06T10:59:43Z" + } + ], + "reactionCount": 96, + "topReactions": [ + { + "id": 85370, + "emoji": "😀", + "count": 9 + } + ] + }, + { + "id": 16404, + "name": "정우성", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-02-23T07:55:55Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 89953, + "recipientId": 16404, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/4/200/200", + "relationship": "친구", + "content": "송혜교님의 메세지 내용 31", + "font": "Noto Sans", + "createdAt": "2023-11-18T03:28:41Z" + }, + { + "id": 44698, + "recipientId": 16404, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/343/200/200", + "relationship": "가족", + "content": "현빈님의 메세지 내용 48", + "font": "Noto Sans", + "createdAt": "2023-12-03T23:14:10Z" + }, + { + "id": 14294, + "recipientId": 16404, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/174/200/200", + "relationship": "친구", + "content": "전지현님의 메세지 내용 18", + "font": "Roboto", + "createdAt": "2023-11-22T08:04:12Z" + } + ], + "reactionCount": 76, + "topReactions": [ + { + "id": 20609, + "emoji": "😀", + "count": 4 + }, + { + "id": 24638, + "emoji": "❤️", + "count": 8 + }, + { + "id": 38365, + "emoji": "👍", + "count": 20 + }, + { + "id": 16361, + "emoji": "😀", + "count": 2 + }, + { + "id": 41186, + "emoji": "👍", + "count": 20 + } + ] + }, + { + "id": 50859, + "name": "한지민", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/50859/600/400", + "createdAt": "2023-03-29T03:53:06Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 77856, + "recipientId": 50859, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/153/200/200", + "relationship": "가족", + "content": "정우성님의 메세지 내용 43", + "font": "Nanum Gothic", + "createdAt": "2023-06-15T17:57:20Z" + } + ], + "reactionCount": 79, + "topReactions": [ + { + "id": 36218, + "emoji": "😀", + "count": 9 + } + ] + }, + { + "id": 21841, + "name": "정우성", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2024-01-24T03:56:41Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 24360, + "recipientId": 21841, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/454/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 45", + "font": "Nanum Gothic", + "createdAt": "2023-05-23T11:32:35Z" + }, + { + "id": 31827, + "recipientId": 21841, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/324/200/200", + "relationship": "친구", + "content": "박서준님의 메세지 내용 54", + "font": "Nanum Gothic", + "createdAt": "2023-04-07T21:22:40Z" + }, + { + "id": 42374, + "recipientId": 21841, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/296/200/200", + "relationship": "가족", + "content": "현빈님의 메세지 내용 42", + "font": "Roboto", + "createdAt": "2023-09-30T04:17:59Z" + } + ], + "reactionCount": 73, + "topReactions": [ + { + "id": 24875, + "emoji": "😀", + "count": 12 + }, + { + "id": 99067, + "emoji": "❤️", + "count": 20 + }, + { + "id": 24734, + "emoji": "❤️", + "count": 20 + }, + { + "id": 3733, + "emoji": "👍", + "count": 10 + }, + { + "id": 54558, + "emoji": "🥹", + "count": 11 + }, + { + "id": 21392, + "emoji": "🎉", + "count": 18 + } + ] + }, + { + "id": 76780, + "name": "한지민", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-03-09T13:34:00Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 51517, + "recipientId": 76780, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/379/200/200", + "relationship": "동료", + "content": "현빈님의 메세지 내용 45", + "font": "Pretendard", + "createdAt": "2023-02-16T02:02:14Z" + }, + { + "id": 60139, + "recipientId": 76780, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/233/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 65", + "font": "Nanum Gothic", + "createdAt": "2023-04-10T04:53:06Z" + } + ], + "reactionCount": 82, + "topReactions": [ + { + "id": 53064, + "emoji": "❤️", + "count": 4 + }, + { + "id": 84662, + "emoji": "🎉", + "count": 16 + }, + { + "id": 15519, + "emoji": "❤️", + "count": 19 + }, + { + "id": 75306, + "emoji": "❤️", + "count": 19 + }, + { + "id": 59498, + "emoji": "😀", + "count": 14 + } + ] + }, + { + "id": 8022, + "name": "한지민", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-09-10T18:36:50Z", + "messageCount": 3, + "recentMessages": [ + { + "id": 47963, + "recipientId": 8022, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/396/200/200", + "relationship": "가족", + "content": "이영준님의 메세지 내용 18", + "font": "Nanum Gothic", + "createdAt": "2023-12-03T16:01:09Z" + }, + { + "id": 2686, + "recipientId": 8022, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/310/200/200", + "relationship": "가족", + "content": "박서준님의 메세지 내용 24", + "font": "Roboto", + "createdAt": "2023-08-02T03:38:21Z" + }, + { + "id": 64093, + "recipientId": 8022, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/126/200/200", + "relationship": "가족", + "content": "전지현님의 메세지 내용 16", + "font": "Roboto", + "createdAt": "2023-02-25T20:36:10Z" + } + ], + "reactionCount": 57, + "topReactions": [ + { + "id": 67314, + "emoji": "🎉", + "count": 6 + }, + { + "id": 20708, + "emoji": "👍", + "count": 13 + }, + { + "id": 32217, + "emoji": "🥹", + "count": 8 + }, + { + "id": 59013, + "emoji": "😁", + "count": 9 + } + ] + }, + { + "id": 36777, + "name": "김하은", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/36777/600/400", + "createdAt": "2023-11-13T20:58:33Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 25834, + "recipientId": 36777, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/30/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 23", + "font": "Roboto", + "createdAt": "2023-09-22T02:37:47Z" + }, + { + "id": 18411, + "recipientId": 36777, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/445/200/200", + "relationship": "가족", + "content": "정우성님의 메세지 내용 64", + "font": "Roboto", + "createdAt": "2023-09-24T01:46:01Z" + }, + { + "id": 76753, + "recipientId": 36777, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/283/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 94", + "font": "Nanum Gothic", + "createdAt": "2023-07-19T00:26:10Z" + } + ], + "reactionCount": 47, + "topReactions": [ + { + "id": 81037, + "emoji": "🥹", + "count": 20 + }, + { + "id": 16358, + "emoji": "😁", + "count": 3 + }, + { + "id": 44167, + "emoji": "😀", + "count": 15 + }, + { + "id": 66141, + "emoji": "🎉", + "count": 19 + } + ] + }, + { + "id": 74659, + "name": "전지현", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-11-17T12:30:58Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 82067, + "recipientId": 74659, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/404/200/200", + "relationship": "지인", + "content": "박서준님의 메세지 내용 78", + "font": "Nanum Gothic", + "createdAt": "2024-01-18T12:11:24Z" + } + ], + "reactionCount": 43, + "topReactions": [ + { + "id": 17924, + "emoji": "😀", + "count": 12 + }, + { + "id": 49600, + "emoji": "😀", + "count": 11 + }, + { + "id": 11142, + "emoji": "🥹", + "count": 7 + } + ] + }, + { + "id": 43809, + "name": "현빈", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/43809/600/400", + "createdAt": "2023-10-03T16:37:43Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 55697, + "recipientId": 43809, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/412/200/200", + "relationship": "친구", + "content": "송혜교님의 메세지 내용 3", + "font": "Roboto", + "createdAt": "2023-03-06T06:54:25Z" + }, + { + "id": 41596, + "recipientId": 43809, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/439/200/200", + "relationship": "동료", + "content": "이병헌님의 메세지 내용 36", + "font": "Roboto", + "createdAt": "2023-02-12T07:13:07Z" + }, + { + "id": 65835, + "recipientId": 43809, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/87/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 89", + "font": "Roboto", + "createdAt": "2023-06-21T12:20:45Z" + } + ], + "reactionCount": 45, + "topReactions": [ + { + "id": 89452, + "emoji": "🥹", + "count": 11 + }, + { + "id": 83618, + "emoji": "😀", + "count": 12 + } + ] + }, + { + "id": 74443, + "name": "한지민", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2024-01-17T14:09:15Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 46450, + "recipientId": 74443, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/416/200/200", + "relationship": "가족", + "content": "현빈님의 메세지 내용 33", + "font": "Noto Sans", + "createdAt": "2024-02-01T01:10:37Z" + }, + { + "id": 11534, + "recipientId": 74443, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/129/200/200", + "relationship": "친구", + "content": "김하은님의 메세지 내용 27", + "font": "Roboto", + "createdAt": "2024-02-04T19:36:42Z" + }, + { + "id": 29956, + "recipientId": 74443, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/154/200/200", + "relationship": "지인", + "content": "이영준님의 메세지 내용 16", + "font": "Pretendard", + "createdAt": "2023-11-27T09:06:13Z" + } + ], + "reactionCount": 7, + "topReactions": [ + { + "id": 45551, + "emoji": "❤️", + "count": 19 + }, + { + "id": 57044, + "emoji": "😁", + "count": 1 + } + ] + }, + { + "id": 62125, + "name": "현빈", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/62125/600/400", + "createdAt": "2023-11-29T07:54:55Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 48839, + "recipientId": 62125, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/498/200/200", + "relationship": "가족", + "content": "이영준님의 메세지 내용 22", + "font": "Pretendard", + "createdAt": "2023-10-25T11:05:34Z" + }, + { + "id": 52003, + "recipientId": 62125, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/74/200/200", + "relationship": "가족", + "content": "전지현님의 메세지 내용 2", + "font": "Roboto", + "createdAt": "2023-11-20T16:46:22Z" + }, + { + "id": 62162, + "recipientId": 62125, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/293/200/200", + "relationship": "지인", + "content": "이병헌님의 메세지 내용 93", + "font": "Roboto", + "createdAt": "2023-04-29T23:05:56Z" + } + ], + "reactionCount": 75, + "topReactions": [ + { + "id": 11123, + "emoji": "🎉", + "count": 14 + } + ] + }, + { + "id": 32686, + "name": "정우성", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-09-25T19:47:20Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 25980, + "recipientId": 32686, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/361/200/200", + "relationship": "친구", + "content": "이영준님의 메세지 내용 13", + "font": "Noto Sans", + "createdAt": "2023-12-08T15:22:48Z" + }, + { + "id": 73942, + "recipientId": 32686, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/397/200/200", + "relationship": "지인", + "content": "박서준님의 메세지 내용 6", + "font": "Noto Sans", + "createdAt": "2023-01-24T00:32:12Z" + }, + { + "id": 85294, + "recipientId": 32686, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/46/200/200", + "relationship": "지인", + "content": "한지민님의 메세지 내용 38", + "font": "Noto Sans", + "createdAt": "2023-08-16T17:04:11Z" + } + ], + "reactionCount": 55, + "topReactions": [ + { + "id": 79847, + "emoji": "👍", + "count": 9 + }, + { + "id": 33325, + "emoji": "🎉", + "count": 6 + }, + { + "id": 19452, + "emoji": "😀", + "count": 4 + }, + { + "id": 70794, + "emoji": "🥹", + "count": 20 + }, + { + "id": 55957, + "emoji": "😀", + "count": 20 + }, + { + "id": 1762, + "emoji": "🎉", + "count": 14 + } + ] + }, + { + "id": 58844, + "name": "최민수", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-12-01T03:42:08Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 49248, + "recipientId": 58844, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/171/200/200", + "relationship": "동료", + "content": "한지민님의 메세지 내용 11", + "font": "Nanum Gothic", + "createdAt": "2023-03-24T16:30:51Z" + }, + { + "id": 32838, + "recipientId": 58844, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/22/200/200", + "relationship": "지인", + "content": "김하은님의 메세지 내용 29", + "font": "Nanum Gothic", + "createdAt": "2024-01-03T03:12:01Z" + }, + { + "id": 91516, + "recipientId": 58844, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/108/200/200", + "relationship": "가족", + "content": "이병헌님의 메세지 내용 82", + "font": "Pretendard", + "createdAt": "2023-08-27T12:05:46Z" + } + ], + "reactionCount": 20, + "topReactions": [ + { + "id": 81634, + "emoji": "😀", + "count": 5 + }, + { + "id": 88135, + "emoji": "🥹", + "count": 16 + }, + { + "id": 86465, + "emoji": "😀", + "count": 13 + }, + { + "id": 92893, + "emoji": "❤️", + "count": 3 + } + ] + }, + { + "id": 72437, + "name": "현빈", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/72437/600/400", + "createdAt": "2023-08-28T14:40:53Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 73936, + "recipientId": 72437, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/317/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 18", + "font": "Noto Sans", + "createdAt": "2023-04-04T14:53:21Z" + }, + { + "id": 29903, + "recipientId": 72437, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/106/200/200", + "relationship": "동료", + "content": "이병헌님의 메세지 내용 40", + "font": "Roboto", + "createdAt": "2023-04-29T16:49:48Z" + } + ], + "reactionCount": 98, + "topReactions": [ + { + "id": 70510, + "emoji": "🎉", + "count": 20 + }, + { + "id": 66505, + "emoji": "👍", + "count": 3 + }, + { + "id": 66557, + "emoji": "❤️", + "count": 12 + }, + { + "id": 61631, + "emoji": "😁", + "count": 20 + } + ] + }, + { + "id": 31124, + "name": "한지민", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-09-22T15:01:23Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 24005, + "recipientId": 31124, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/440/200/200", + "relationship": "친구", + "content": "이영준님의 메세지 내용 80", + "font": "Roboto", + "createdAt": "2023-12-17T16:17:25Z" + }, + { + "id": 68955, + "recipientId": 31124, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/6/200/200", + "relationship": "지인", + "content": "김하은님의 메세지 내용 85", + "font": "Roboto", + "createdAt": "2023-07-18T06:13:13Z" + }, + { + "id": 91691, + "recipientId": 31124, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/461/200/200", + "relationship": "지인", + "content": "이병헌님의 메세지 내용 53", + "font": "Roboto", + "createdAt": "2023-05-21T09:55:42Z" + } + ], + "reactionCount": 91, + "topReactions": [ + { + "id": 70597, + "emoji": "😁", + "count": 10 + }, + { + "id": 86461, + "emoji": "👍", + "count": 11 + } + ] + }, + { + "id": 73111, + "name": "이병헌", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-12-29T11:24:51Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 19737, + "recipientId": 73111, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/434/200/200", + "relationship": "동료", + "content": "이영준님의 메세지 내용 87", + "font": "Noto Sans", + "createdAt": "2023-02-10T04:25:44Z" + }, + { + "id": 24750, + "recipientId": 73111, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/52/200/200", + "relationship": "가족", + "content": "이영준님의 메세지 내용 49", + "font": "Roboto", + "createdAt": "2023-10-10T22:47:57Z" + } + ], + "reactionCount": 16, + "topReactions": [ + { + "id": 42626, + "emoji": "😀", + "count": 7 + }, + { + "id": 2933, + "emoji": "😁", + "count": 19 + }, + { + "id": 8592, + "emoji": "👍", + "count": 20 + }, + { + "id": 33974, + "emoji": "😀", + "count": 9 + } + ] + }, + { + "id": 44599, + "name": "최민수", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-12-01T19:25:38Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 77427, + "recipientId": 44599, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/9/200/200", + "relationship": "지인", + "content": "전지현님의 메세지 내용 7", + "font": "Noto Sans", + "createdAt": "2024-01-08T12:37:16Z" + }, + { + "id": 2974, + "recipientId": 44599, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/46/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 13", + "font": "Roboto", + "createdAt": "2023-11-11T07:56:34Z" + }, + { + "id": 31985, + "recipientId": 44599, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/340/200/200", + "relationship": "지인", + "content": "정우성님의 메세지 내용 27", + "font": "Pretendard", + "createdAt": "2023-12-03T01:18:34Z" + } + ], + "reactionCount": 54, + "topReactions": [ + { + "id": 69943, + "emoji": "🥹", + "count": 8 + }, + { + "id": 93387, + "emoji": "😀", + "count": 10 + }, + { + "id": 55895, + "emoji": "❤️", + "count": 12 + }, + { + "id": 1552, + "emoji": "🥹", + "count": 13 + }, + { + "id": 62897, + "emoji": "❤️", + "count": 8 + }, + { + "id": 11953, + "emoji": "👍", + "count": 9 + } + ] + }, + { + "id": 53998, + "name": "최민수", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/53998/600/400", + "createdAt": "2023-05-21T05:46:16Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 42481, + "recipientId": 53998, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/226/200/200", + "relationship": "동료", + "content": "정우성님의 메세지 내용 83", + "font": "Pretendard", + "createdAt": "2023-12-02T23:46:08Z" + }, + { + "id": 45560, + "recipientId": 53998, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/336/200/200", + "relationship": "가족", + "content": "전지현님의 메세지 내용 93", + "font": "Pretendard", + "createdAt": "2023-04-05T16:17:22Z" + }, + { + "id": 44511, + "recipientId": 53998, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/401/200/200", + "relationship": "가족", + "content": "이영준님의 메세지 내용 24", + "font": "Noto Sans", + "createdAt": "2023-12-30T08:26:11Z" + } + ], + "reactionCount": 99, + "topReactions": [ + { + "id": 26899, + "emoji": "🥹", + "count": 19 + }, + { + "id": 64192, + "emoji": "😀", + "count": 20 + }, + { + "id": 38049, + "emoji": "🥹", + "count": 12 + }, + { + "id": 3255, + "emoji": "❤️", + "count": 3 + }, + { + "id": 35106, + "emoji": "👍", + "count": 17 + } + ] + }, + { + "id": 89555, + "name": "정우성", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/89555/600/400", + "createdAt": "2023-11-04T11:24:31Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 75585, + "recipientId": 89555, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/82/200/200", + "relationship": "가족", + "content": "현빈님의 메세지 내용 79", + "font": "Noto Sans", + "createdAt": "2023-08-27T02:20:45Z" + }, + { + "id": 45846, + "recipientId": 89555, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/66/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 16", + "font": "Nanum Gothic", + "createdAt": "2023-12-16T12:24:17Z" + }, + { + "id": 78446, + "recipientId": 89555, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/162/200/200", + "relationship": "가족", + "content": "김하은님의 메세지 내용 43", + "font": "Roboto", + "createdAt": "2023-10-20T14:00:34Z" + } + ], + "reactionCount": 81, + "topReactions": [ + { + "id": 40481, + "emoji": "😁", + "count": 6 + }, + { + "id": 89819, + "emoji": "👍", + "count": 5 + }, + { + "id": 56551, + "emoji": "🎉", + "count": 8 + }, + { + "id": 90383, + "emoji": "🎉", + "count": 8 + }, + { + "id": 48052, + "emoji": "😁", + "count": 4 + }, + { + "id": 53141, + "emoji": "🎉", + "count": 10 + } + ] + }, + { + "id": 12891, + "name": "전지현", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/12891/600/400", + "createdAt": "2023-04-02T10:50:44Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 69504, + "recipientId": 12891, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/372/200/200", + "relationship": "지인", + "content": "김하은님의 메세지 내용 100", + "font": "Noto Sans", + "createdAt": "2023-06-24T18:34:35Z" + }, + { + "id": 16122, + "recipientId": 12891, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/384/200/200", + "relationship": "지인", + "content": "송혜교님의 메세지 내용 61", + "font": "Pretendard", + "createdAt": "2024-01-15T10:37:45Z" + }, + { + "id": 48360, + "recipientId": 12891, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/331/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 9", + "font": "Noto Sans", + "createdAt": "2024-01-22T14:41:55Z" + } + ], + "reactionCount": 91, + "topReactions": [ + { + "id": 22984, + "emoji": "😁", + "count": 2 + }, + { + "id": 38976, + "emoji": "😀", + "count": 1 + } + ] + }, + { + "id": 21026, + "name": "현빈", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/21026/600/400", + "createdAt": "2023-06-24T21:14:04Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 78110, + "recipientId": 21026, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/86/200/200", + "relationship": "동료", + "content": "정우성님의 메세지 내용 72", + "font": "Nanum Gothic", + "createdAt": "2023-10-03T05:53:18Z" + }, + { + "id": 17655, + "recipientId": 21026, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/24/200/200", + "relationship": "지인", + "content": "김하은님의 메세지 내용 99", + "font": "Noto Sans", + "createdAt": "2023-02-16T19:23:42Z" + } + ], + "reactionCount": 48, + "topReactions": [ + { + "id": 64931, + "emoji": "❤️", + "count": 5 + }, + { + "id": 32976, + "emoji": "🎉", + "count": 19 + } + ] + }, + { + "id": 72332, + "name": "이병헌", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/72332/600/400", + "createdAt": "2023-10-08T20:12:12Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 88347, + "recipientId": 72332, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/25/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 18", + "font": "Nanum Gothic", + "createdAt": "2023-07-12T05:02:22Z" + }, + { + "id": 18515, + "recipientId": 72332, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/259/200/200", + "relationship": "친구", + "content": "현빈님의 메세지 내용 35", + "font": "Nanum Gothic", + "createdAt": "2023-02-04T02:14:10Z" + }, + { + "id": 10191, + "recipientId": 72332, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/400/200/200", + "relationship": "지인", + "content": "전지현님의 메세지 내용 76", + "font": "Pretendard", + "createdAt": "2023-07-03T21:04:14Z" + } + ], + "reactionCount": 84, + "topReactions": [ + { + "id": 34056, + "emoji": "🎉", + "count": 9 + } + ] + }, + { + "id": 9856, + "name": "이영준", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-04-25T13:16:15Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 62780, + "recipientId": 9856, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/466/200/200", + "relationship": "친구", + "content": "최민수님의 메세지 내용 28", + "font": "Nanum Gothic", + "createdAt": "2024-01-09T20:20:07Z" + }, + { + "id": 87691, + "recipientId": 9856, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/219/200/200", + "relationship": "동료", + "content": "전지현님의 메세지 내용 11", + "font": "Pretendard", + "createdAt": "2023-09-13T03:47:51Z" + }, + { + "id": 33613, + "recipientId": 9856, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/231/200/200", + "relationship": "가족", + "content": "박서준님의 메세지 내용 14", + "font": "Nanum Gothic", + "createdAt": "2023-05-13T08:02:20Z" + } + ], + "reactionCount": 86, + "topReactions": [ + { + "id": 11941, + "emoji": "😀", + "count": 10 + } + ] + }, + { + "id": 6048, + "name": "한지민", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-11-21T11:02:16Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 47612, + "recipientId": 6048, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/97/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 72", + "font": "Pretendard", + "createdAt": "2023-12-11T12:42:57Z" + }, + { + "id": 50485, + "recipientId": 6048, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/84/200/200", + "relationship": "친구", + "content": "최민수님의 메세지 내용 24", + "font": "Nanum Gothic", + "createdAt": "2023-12-01T20:34:55Z" + }, + { + "id": 42372, + "recipientId": 6048, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/478/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 38", + "font": "Roboto", + "createdAt": "2023-09-10T14:19:59Z" + } + ], + "reactionCount": 93, + "topReactions": [ + { + "id": 85562, + "emoji": "👍", + "count": 14 + }, + { + "id": 19775, + "emoji": "❤️", + "count": 4 + }, + { + "id": 97219, + "emoji": "❤️", + "count": 18 + }, + { + "id": 77812, + "emoji": "🎉", + "count": 3 + } + ] + }, + { + "id": 7768, + "name": "송혜교", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/7768/600/400", + "createdAt": "2024-02-03T06:34:20Z", + "messageCount": 3, + "recentMessages": [ + { + "id": 91935, + "recipientId": 7768, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/196/200/200", + "relationship": "가족", + "content": "이영준님의 메세지 내용 39", + "font": "Noto Sans", + "createdAt": "2023-10-26T02:05:13Z" + }, + { + "id": 54283, + "recipientId": 7768, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/368/200/200", + "relationship": "가족", + "content": "이병헌님의 메세지 내용 8", + "font": "Nanum Gothic", + "createdAt": "2023-02-19T15:25:55Z" + }, + { + "id": 22996, + "recipientId": 7768, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/323/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 36", + "font": "Nanum Gothic", + "createdAt": "2023-05-07T10:13:46Z" + } + ], + "reactionCount": 17, + "topReactions": [ + { + "id": 56016, + "emoji": "😁", + "count": 7 + } + ] + }, + { + "id": 60032, + "name": "정우성", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/60032/600/400", + "createdAt": "2023-05-02T10:55:07Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 16669, + "recipientId": 60032, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/209/200/200", + "relationship": "친구", + "content": "이영준님의 메세지 내용 97", + "font": "Roboto", + "createdAt": "2023-10-20T20:11:37Z" + }, + { + "id": 91971, + "recipientId": 60032, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/494/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 6", + "font": "Nanum Gothic", + "createdAt": "2023-09-08T08:31:38Z" + }, + { + "id": 66344, + "recipientId": 60032, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/444/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 47", + "font": "Pretendard", + "createdAt": "2023-07-26T07:54:55Z" + } + ], + "reactionCount": 61, + "topReactions": [ + { + "id": 79749, + "emoji": "😀", + "count": 11 + } + ] + }, + { + "id": 90521, + "name": "김하은", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/90521/600/400", + "createdAt": "2023-04-23T15:43:22Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 84413, + "recipientId": 90521, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/266/200/200", + "relationship": "가족", + "content": "박서준님의 메세지 내용 66", + "font": "Nanum Gothic", + "createdAt": "2023-10-18T10:21:59Z" + } + ], + "reactionCount": 58, + "topReactions": [ + { + "id": 15557, + "emoji": "❤️", + "count": 1 + }, + { + "id": 87847, + "emoji": "❤️", + "count": 5 + } + ] + }, + { + "id": 88686, + "name": "김하은", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/88686/600/400", + "createdAt": "2023-10-03T13:17:00Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 94186, + "recipientId": 88686, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/271/200/200", + "relationship": "지인", + "content": "이영준님의 메세지 내용 5", + "font": "Nanum Gothic", + "createdAt": "2023-09-06T14:11:21Z" + } + ], + "reactionCount": 83, + "topReactions": [ + { + "id": 19026, + "emoji": "🎉", + "count": 9 + }, + { + "id": 66458, + "emoji": "🥹", + "count": 18 + }, + { + "id": 39586, + "emoji": "❤️", + "count": 7 + }, + { + "id": 19251, + "emoji": "🥹", + "count": 17 + }, + { + "id": 4095, + "emoji": "🥹", + "count": 13 + } + ] + }, + { + "id": 19057, + "name": "현빈", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/19057/600/400", + "createdAt": "2023-08-11T17:15:28Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 77529, + "recipientId": 19057, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/20/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 29", + "font": "Pretendard", + "createdAt": "2024-01-29T23:03:48Z" + }, + { + "id": 90459, + "recipientId": 19057, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/264/200/200", + "relationship": "친구", + "content": "김하은님의 메세지 내용 15", + "font": "Roboto", + "createdAt": "2023-08-14T06:22:29Z" + }, + { + "id": 34301, + "recipientId": 19057, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/172/200/200", + "relationship": "친구", + "content": "김하은님의 메세지 내용 66", + "font": "Noto Sans", + "createdAt": "2024-01-21T14:02:39Z" + } + ], + "reactionCount": 47, + "topReactions": [ + { + "id": 55806, + "emoji": "😀", + "count": 9 + }, + { + "id": 81344, + "emoji": "🎉", + "count": 20 + }, + { + "id": 23760, + "emoji": "😁", + "count": 7 + }, + { + "id": 95115, + "emoji": "❤️", + "count": 10 + }, + { + "id": 62637, + "emoji": "😀", + "count": 2 + } + ] + }, + { + "id": 27685, + "name": "김하은", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-12-05T11:32:51Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 47201, + "recipientId": 27685, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/309/200/200", + "relationship": "동료", + "content": "최민수님의 메세지 내용 20", + "font": "Pretendard", + "createdAt": "2023-09-27T00:49:21Z" + }, + { + "id": 62272, + "recipientId": 27685, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/63/200/200", + "relationship": "동료", + "content": "한지민님의 메세지 내용 7", + "font": "Roboto", + "createdAt": "2023-01-26T03:30:29Z" + }, + { + "id": 20963, + "recipientId": 27685, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/385/200/200", + "relationship": "친구", + "content": "김하은님의 메세지 내용 44", + "font": "Pretendard", + "createdAt": "2023-11-26T17:32:56Z" + } + ], + "reactionCount": 15, + "topReactions": [ + { + "id": 12348, + "emoji": "🎉", + "count": 8 + }, + { + "id": 54843, + "emoji": "👍", + "count": 15 + }, + { + "id": 79979, + "emoji": "👍", + "count": 1 + }, + { + "id": 20768, + "emoji": "👍", + "count": 20 + }, + { + "id": 16109, + "emoji": "❤️", + "count": 1 + }, + { + "id": 10264, + "emoji": "😁", + "count": 9 + } + ] + }, + { + "id": 27107, + "name": "이영준", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/27107/600/400", + "createdAt": "2023-12-02T07:20:10Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 97932, + "recipientId": 27107, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/497/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 78", + "font": "Roboto", + "createdAt": "2023-09-11T04:54:00Z" + } + ], + "reactionCount": 55, + "topReactions": [ + { + "id": 65130, + "emoji": "👍", + "count": 7 + }, + { + "id": 3875, + "emoji": "😁", + "count": 15 + }, + { + "id": 93476, + "emoji": "❤️", + "count": 16 + }, + { + "id": 22262, + "emoji": "🥹", + "count": 2 + } + ] + }, + { + "id": 5946, + "name": "이영준", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/5946/600/400", + "createdAt": "2024-01-08T03:36:35Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 66117, + "recipientId": 5946, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/453/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 70", + "font": "Nanum Gothic", + "createdAt": "2023-10-08T04:49:43Z" + }, + { + "id": 33590, + "recipientId": 5946, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/446/200/200", + "relationship": "지인", + "content": "정우성님의 메세지 내용 45", + "font": "Nanum Gothic", + "createdAt": "2023-02-24T20:46:51Z" + } + ], + "reactionCount": 80, + "topReactions": [ + { + "id": 90187, + "emoji": "😀", + "count": 6 + }, + { + "id": 26989, + "emoji": "🥹", + "count": 8 + }, + { + "id": 80780, + "emoji": "🥹", + "count": 15 + }, + { + "id": 4359, + "emoji": "🎉", + "count": 15 + }, + { + "id": 25620, + "emoji": "👍", + "count": 10 + } + ] + }, + { + "id": 28566, + "name": "정우성", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-11-09T11:10:28Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 19714, + "recipientId": 28566, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/177/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 25", + "font": "Pretendard", + "createdAt": "2023-07-21T02:56:53Z" + } + ], + "reactionCount": 4, + "topReactions": [ + { + "id": 71201, + "emoji": "😀", + "count": 5 + }, + { + "id": 4897, + "emoji": "🥹", + "count": 4 + }, + { + "id": 64978, + "emoji": "😁", + "count": 12 + }, + { + "id": 69162, + "emoji": "🥹", + "count": 1 + }, + { + "id": 99414, + "emoji": "😀", + "count": 5 + }, + { + "id": 2807, + "emoji": "🥹", + "count": 7 + } + ] + }, + { + "id": 84533, + "name": "김하은", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2024-01-08T03:10:08Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 25694, + "recipientId": 84533, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/96/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 36", + "font": "Pretendard", + "createdAt": "2023-01-14T06:23:45Z" + }, + { + "id": 89853, + "recipientId": 84533, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/52/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 28", + "font": "Nanum Gothic", + "createdAt": "2023-06-23T08:29:50Z" + }, + { + "id": 3101, + "recipientId": 84533, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/28/200/200", + "relationship": "가족", + "content": "현빈님의 메세지 내용 63", + "font": "Nanum Gothic", + "createdAt": "2024-01-12T05:42:09Z" + } + ], + "reactionCount": 23, + "topReactions": [ + { + "id": 7041, + "emoji": "😁", + "count": 6 + }, + { + "id": 19313, + "emoji": "😀", + "count": 1 + }, + { + "id": 22714, + "emoji": "👍", + "count": 12 + }, + { + "id": 12076, + "emoji": "👍", + "count": 18 + }, + { + "id": 8583, + "emoji": "🎉", + "count": 5 + } + ] + }, + { + "id": 96506, + "name": "박서준", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-06-09T15:04:25Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 48175, + "recipientId": 96506, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/145/200/200", + "relationship": "동료", + "content": "이병헌님의 메세지 내용 86", + "font": "Pretendard", + "createdAt": "2023-03-13T10:17:35Z" + }, + { + "id": 93664, + "recipientId": 96506, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/238/200/200", + "relationship": "친구", + "content": "전지현님의 메세지 내용 22", + "font": "Noto Sans", + "createdAt": "2023-12-31T04:01:30Z" + }, + { + "id": 17811, + "recipientId": 96506, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/87/200/200", + "relationship": "친구", + "content": "최민수님의 메세지 내용 26", + "font": "Noto Sans", + "createdAt": "2024-01-16T04:31:27Z" + } + ], + "reactionCount": 29, + "topReactions": [ + { + "id": 52114, + "emoji": "🥹", + "count": 8 + }, + { + "id": 93670, + "emoji": "🥹", + "count": 18 + }, + { + "id": 34535, + "emoji": "🎉", + "count": 1 + }, + { + "id": 34032, + "emoji": "🥹", + "count": 3 + }, + { + "id": 24268, + "emoji": "😁", + "count": 2 + } + ] + }, + { + "id": 83453, + "name": "김하은", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-08-02T05:41:33Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 62207, + "recipientId": 83453, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/181/200/200", + "relationship": "동료", + "content": "전지현님의 메세지 내용 88", + "font": "Roboto", + "createdAt": "2023-12-18T17:43:56Z" + }, + { + "id": 64882, + "recipientId": 83453, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/145/200/200", + "relationship": "친구", + "content": "이영준님의 메세지 내용 95", + "font": "Roboto", + "createdAt": "2023-10-19T03:30:01Z" + }, + { + "id": 51419, + "recipientId": 83453, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/161/200/200", + "relationship": "가족", + "content": "현빈님의 메세지 내용 98", + "font": "Roboto", + "createdAt": "2023-02-09T11:45:22Z" + } + ], + "reactionCount": 10, + "topReactions": [ + { + "id": 34005, + "emoji": "🎉", + "count": 7 + } + ] + }, + { + "id": 74991, + "name": "한지민", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/74991/600/400", + "createdAt": "2023-03-21T17:29:11Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 43900, + "recipientId": 74991, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/306/200/200", + "relationship": "지인", + "content": "정우성님의 메세지 내용 74", + "font": "Roboto", + "createdAt": "2024-01-11T12:45:15Z" + }, + { + "id": 23958, + "recipientId": 74991, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/14/200/200", + "relationship": "가족", + "content": "전지현님의 메세지 내용 84", + "font": "Pretendard", + "createdAt": "2023-05-03T21:07:40Z" + }, + { + "id": 89183, + "recipientId": 74991, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/355/200/200", + "relationship": "친구", + "content": "김하은님의 메세지 내용 91", + "font": "Pretendard", + "createdAt": "2023-04-27T03:48:45Z" + } + ], + "reactionCount": 45, + "topReactions": [ + { + "id": 30409, + "emoji": "🎉", + "count": 9 + }, + { + "id": 96020, + "emoji": "👍", + "count": 19 + } + ] + }, + { + "id": 10732, + "name": "현빈", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2024-01-29T01:17:08Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 28091, + "recipientId": 10732, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/214/200/200", + "relationship": "친구", + "content": "송혜교님의 메세지 내용 90", + "font": "Nanum Gothic", + "createdAt": "2023-02-16T06:24:10Z" + }, + { + "id": 96968, + "recipientId": 10732, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/334/200/200", + "relationship": "가족", + "content": "이영준님의 메세지 내용 86", + "font": "Nanum Gothic", + "createdAt": "2023-04-29T02:44:44Z" + }, + { + "id": 11805, + "recipientId": 10732, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/76/200/200", + "relationship": "지인", + "content": "이병헌님의 메세지 내용 48", + "font": "Nanum Gothic", + "createdAt": "2023-12-29T05:06:21Z" + } + ], + "reactionCount": 45, + "topReactions": [ + { + "id": 75995, + "emoji": "🎉", + "count": 14 + }, + { + "id": 83468, + "emoji": "👍", + "count": 6 + }, + { + "id": 3826, + "emoji": "🎉", + "count": 6 + }, + { + "id": 53081, + "emoji": "❤️", + "count": 14 + } + ] + }, + { + "id": 46305, + "name": "현빈", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/46305/600/400", + "createdAt": "2023-02-20T22:15:25Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 94045, + "recipientId": 46305, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/2/200/200", + "relationship": "지인", + "content": "현빈님의 메세지 내용 65", + "font": "Noto Sans", + "createdAt": "2023-02-05T06:10:36Z" + }, + { + "id": 27482, + "recipientId": 46305, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/443/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 4", + "font": "Noto Sans", + "createdAt": "2023-02-22T15:24:55Z" + }, + { + "id": 33966, + "recipientId": 46305, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/394/200/200", + "relationship": "가족", + "content": "이영준님의 메세지 내용 33", + "font": "Noto Sans", + "createdAt": "2023-05-08T01:31:25Z" + } + ], + "reactionCount": 99, + "topReactions": [ + { + "id": 22251, + "emoji": "👍", + "count": 13 + } + ] + }, + { + "id": 64061, + "name": "현빈", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-05-08T17:59:24Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 23840, + "recipientId": 64061, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/74/200/200", + "relationship": "지인", + "content": "이영준님의 메세지 내용 74", + "font": "Nanum Gothic", + "createdAt": "2023-07-23T08:30:41Z" + }, + { + "id": 94450, + "recipientId": 64061, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/353/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 61", + "font": "Pretendard", + "createdAt": "2023-12-02T06:48:01Z" + }, + { + "id": 14478, + "recipientId": 64061, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/435/200/200", + "relationship": "지인", + "content": "송혜교님의 메세지 내용 13", + "font": "Roboto", + "createdAt": "2023-02-11T15:00:07Z" + } + ], + "reactionCount": 9, + "topReactions": [ + { + "id": 16899, + "emoji": "🥹", + "count": 5 + } + ] + }, + { + "id": 15549, + "name": "이병헌", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-12-13T10:07:11Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 25725, + "recipientId": 15549, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/22/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 37", + "font": "Nanum Gothic", + "createdAt": "2023-06-08T04:48:57Z" + }, + { + "id": 60095, + "recipientId": 15549, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/425/200/200", + "relationship": "동료", + "content": "정우성님의 메세지 내용 83", + "font": "Noto Sans", + "createdAt": "2023-01-05T05:19:05Z" + }, + { + "id": 24093, + "recipientId": 15549, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/328/200/200", + "relationship": "동료", + "content": "현빈님의 메세지 내용 66", + "font": "Nanum Gothic", + "createdAt": "2023-06-17T11:09:48Z" + } + ], + "reactionCount": 72, + "topReactions": [ + { + "id": 71384, + "emoji": "👍", + "count": 8 + }, + { + "id": 23202, + "emoji": "👍", + "count": 19 + }, + { + "id": 98227, + "emoji": "👍", + "count": 15 + }, + { + "id": 17552, + "emoji": "🥹", + "count": 14 + } + ] + }, + { + "id": 84213, + "name": "송혜교", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/84213/600/400", + "createdAt": "2023-12-21T22:50:35Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 76650, + "recipientId": 84213, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/401/200/200", + "relationship": "동료", + "content": "최민수님의 메세지 내용 23", + "font": "Roboto", + "createdAt": "2023-11-24T00:40:50Z" + }, + { + "id": 67124, + "recipientId": 84213, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/482/200/200", + "relationship": "가족", + "content": "이병헌님의 메세지 내용 81", + "font": "Pretendard", + "createdAt": "2023-04-16T14:42:59Z" + }, + { + "id": 92607, + "recipientId": 84213, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/428/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 89", + "font": "Roboto", + "createdAt": "2023-02-24T01:40:42Z" + } + ], + "reactionCount": 5, + "topReactions": [ + { + "id": 84810, + "emoji": "😀", + "count": 13 + }, + { + "id": 42243, + "emoji": "🥹", + "count": 6 + }, + { + "id": 63560, + "emoji": "👍", + "count": 10 + }, + { + "id": 6972, + "emoji": "🥹", + "count": 4 + }, + { + "id": 32485, + "emoji": "😁", + "count": 1 + }, + { + "id": 29060, + "emoji": "😁", + "count": 10 + } + ] + }, + { + "id": 90495, + "name": "최민수", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/90495/600/400", + "createdAt": "2023-04-23T14:47:14Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 27573, + "recipientId": 90495, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/490/200/200", + "relationship": "가족", + "content": "이영준님의 메세지 내용 64", + "font": "Nanum Gothic", + "createdAt": "2023-06-17T05:10:47Z" + }, + { + "id": 96157, + "recipientId": 90495, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/75/200/200", + "relationship": "친구", + "content": "최민수님의 메세지 내용 30", + "font": "Noto Sans", + "createdAt": "2023-03-11T02:09:50Z" + }, + { + "id": 39533, + "recipientId": 90495, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/436/200/200", + "relationship": "동료", + "content": "이영준님의 메세지 내용 38", + "font": "Roboto", + "createdAt": "2023-03-15T20:24:49Z" + } + ], + "reactionCount": 0, + "topReactions": [ + { + "id": 99864, + "emoji": "🥹", + "count": 11 + } + ] + }, + { + "id": 83558, + "name": "한지민", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/83558/600/400", + "createdAt": "2023-03-30T04:18:29Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 91701, + "recipientId": 83558, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/169/200/200", + "relationship": "지인", + "content": "이병헌님의 메세지 내용 97", + "font": "Noto Sans", + "createdAt": "2023-11-22T09:50:03Z" + }, + { + "id": 23330, + "recipientId": 83558, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/8/200/200", + "relationship": "지인", + "content": "한지민님의 메세지 내용 77", + "font": "Noto Sans", + "createdAt": "2024-01-04T23:36:01Z" + }, + { + "id": 79589, + "recipientId": 83558, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/472/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 24", + "font": "Pretendard", + "createdAt": "2023-01-02T22:24:57Z" + } + ], + "reactionCount": 95, + "topReactions": [ + { + "id": 4780, + "emoji": "😀", + "count": 11 + }, + { + "id": 36370, + "emoji": "👍", + "count": 15 + }, + { + "id": 857, + "emoji": "😁", + "count": 11 + }, + { + "id": 68373, + "emoji": "😁", + "count": 17 + }, + { + "id": 86784, + "emoji": "❤️", + "count": 20 + } + ] + }, + { + "id": 66320, + "name": "전지현", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-02-20T16:11:28Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 2994, + "recipientId": 66320, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/84/200/200", + "relationship": "동료", + "content": "이영준님의 메세지 내용 2", + "font": "Nanum Gothic", + "createdAt": "2023-08-27T10:17:50Z" + }, + { + "id": 56137, + "recipientId": 66320, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/1/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 56", + "font": "Noto Sans", + "createdAt": "2023-08-10T23:57:30Z" + }, + { + "id": 53043, + "recipientId": 66320, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/48/200/200", + "relationship": "동료", + "content": "송혜교님의 메세지 내용 5", + "font": "Noto Sans", + "createdAt": "2024-01-18T11:22:58Z" + } + ], + "reactionCount": 63, + "topReactions": [ + { + "id": 48182, + "emoji": "😀", + "count": 16 + }, + { + "id": 5086, + "emoji": "😀", + "count": 9 + }, + { + "id": 3495, + "emoji": "❤️", + "count": 5 + }, + { + "id": 84837, + "emoji": "🥹", + "count": 6 + } + ] + }, + { + "id": 1220, + "name": "김하은", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/1220/600/400", + "createdAt": "2023-11-08T12:25:25Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 86215, + "recipientId": 1220, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/419/200/200", + "relationship": "가족", + "content": "이병헌님의 메세지 내용 25", + "font": "Pretendard", + "createdAt": "2023-05-10T21:59:12Z" + } + ], + "reactionCount": 14, + "topReactions": [ + { + "id": 11863, + "emoji": "👍", + "count": 16 + }, + { + "id": 36179, + "emoji": "🎉", + "count": 18 + } + ] + }, + { + "id": 53959, + "name": "이병헌", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/53959/600/400", + "createdAt": "2023-08-24T05:22:48Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 84022, + "recipientId": 53959, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/199/200/200", + "relationship": "지인", + "content": "현빈님의 메세지 내용 71", + "font": "Nanum Gothic", + "createdAt": "2024-01-27T22:35:29Z" + }, + { + "id": 29280, + "recipientId": 53959, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/415/200/200", + "relationship": "동료", + "content": "이영준님의 메세지 내용 73", + "font": "Nanum Gothic", + "createdAt": "2023-02-08T09:24:01Z" + }, + { + "id": 59151, + "recipientId": 53959, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/10/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 4", + "font": "Nanum Gothic", + "createdAt": "2023-03-11T07:04:18Z" + } + ], + "reactionCount": 24, + "topReactions": [ + { + "id": 23239, + "emoji": "🥹", + "count": 6 + }, + { + "id": 8346, + "emoji": "😀", + "count": 3 + }, + { + "id": 10520, + "emoji": "❤️", + "count": 9 + }, + { + "id": 92010, + "emoji": "😀", + "count": 9 + }, + { + "id": 33511, + "emoji": "🥹", + "count": 11 + }, + { + "id": 29961, + "emoji": "😀", + "count": 17 + } + ] + }, + { + "id": 21491, + "name": "박서준", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/21491/600/400", + "createdAt": "2023-01-10T01:44:28Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 84576, + "recipientId": 21491, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/409/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 59", + "font": "Pretendard", + "createdAt": "2023-11-01T08:41:35Z" + }, + { + "id": 18967, + "recipientId": 21491, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/330/200/200", + "relationship": "가족", + "content": "현빈님의 메세지 내용 86", + "font": "Pretendard", + "createdAt": "2024-01-30T16:01:34Z" + }, + { + "id": 89384, + "recipientId": 21491, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/467/200/200", + "relationship": "동료", + "content": "정우성님의 메세지 내용 88", + "font": "Nanum Gothic", + "createdAt": "2023-09-04T20:05:02Z" + } + ], + "reactionCount": 8, + "topReactions": [ + { + "id": 78078, + "emoji": "👍", + "count": 2 + }, + { + "id": 36649, + "emoji": "🎉", + "count": 6 + }, + { + "id": 92725, + "emoji": "❤️", + "count": 2 + } + ] + }, + { + "id": 51432, + "name": "이병헌", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/51432/600/400", + "createdAt": "2023-11-07T07:07:37Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 96527, + "recipientId": 51432, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/119/200/200", + "relationship": "친구", + "content": "이영준님의 메세지 내용 28", + "font": "Nanum Gothic", + "createdAt": "2023-12-01T00:14:54Z" + }, + { + "id": 33808, + "recipientId": 51432, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/478/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 8", + "font": "Pretendard", + "createdAt": "2023-04-04T10:06:15Z" + }, + { + "id": 65182, + "recipientId": 51432, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/417/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 65", + "font": "Noto Sans", + "createdAt": "2023-07-31T00:30:43Z" + } + ], + "reactionCount": 12, + "topReactions": [ + { + "id": 45279, + "emoji": "🥹", + "count": 4 + }, + { + "id": 59474, + "emoji": "👍", + "count": 11 + }, + { + "id": 61205, + "emoji": "👍", + "count": 20 + }, + { + "id": 69208, + "emoji": "😀", + "count": 11 + }, + { + "id": 47277, + "emoji": "🎉", + "count": 13 + } + ] + }, + { + "id": 401, + "name": "전지현", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/401/600/400", + "createdAt": "2024-01-28T02:15:08Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 36776, + "recipientId": 401, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/194/200/200", + "relationship": "친구", + "content": "현빈님의 메세지 내용 6", + "font": "Pretendard", + "createdAt": "2023-10-03T09:11:41Z" + }, + { + "id": 62441, + "recipientId": 401, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/276/200/200", + "relationship": "지인", + "content": "현빈님의 메세지 내용 83", + "font": "Nanum Gothic", + "createdAt": "2023-07-27T15:25:12Z" + }, + { + "id": 50507, + "recipientId": 401, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/174/200/200", + "relationship": "동료", + "content": "이영준님의 메세지 내용 71", + "font": "Nanum Gothic", + "createdAt": "2023-08-26T17:23:07Z" + } + ], + "reactionCount": 96, + "topReactions": [ + { + "id": 49415, + "emoji": "😀", + "count": 16 + } + ] + }, + { + "id": 46242, + "name": "송혜교", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/46242/600/400", + "createdAt": "2023-11-05T16:41:50Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 60128, + "recipientId": 46242, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/149/200/200", + "relationship": "지인", + "content": "김하은님의 메세지 내용 97", + "font": "Roboto", + "createdAt": "2023-09-25T08:24:21Z" + } + ], + "reactionCount": 61, + "topReactions": [ + { + "id": 78077, + "emoji": "❤️", + "count": 15 + }, + { + "id": 81214, + "emoji": "🥹", + "count": 6 + }, + { + "id": 17360, + "emoji": "❤️", + "count": 19 + }, + { + "id": 21652, + "emoji": "🥹", + "count": 4 + } + ] + }, + { + "id": 55794, + "name": "전지현", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/55794/600/400", + "createdAt": "2023-05-13T18:46:52Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 2249, + "recipientId": 55794, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/443/200/200", + "relationship": "가족", + "content": "이영준님의 메세지 내용 70", + "font": "Roboto", + "createdAt": "2023-05-25T22:41:35Z" + }, + { + "id": 71265, + "recipientId": 55794, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/18/200/200", + "relationship": "친구", + "content": "송혜교님의 메세지 내용 47", + "font": "Roboto", + "createdAt": "2023-04-15T12:50:11Z" + }, + { + "id": 18226, + "recipientId": 55794, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/173/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 35", + "font": "Pretendard", + "createdAt": "2023-02-21T23:19:58Z" + } + ], + "reactionCount": 77, + "topReactions": [ + { + "id": 52469, + "emoji": "❤️", + "count": 16 + } + ] + }, + { + "id": 14085, + "name": "박서준", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/14085/600/400", + "createdAt": "2023-09-25T12:01:08Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 25819, + "recipientId": 14085, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/222/200/200", + "relationship": "가족", + "content": "전지현님의 메세지 내용 39", + "font": "Roboto", + "createdAt": "2023-08-12T06:36:32Z" + }, + { + "id": 73459, + "recipientId": 14085, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/160/200/200", + "relationship": "지인", + "content": "전지현님의 메세지 내용 89", + "font": "Roboto", + "createdAt": "2023-08-08T03:12:04Z" + }, + { + "id": 11457, + "recipientId": 14085, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/151/200/200", + "relationship": "지인", + "content": "현빈님의 메세지 내용 23", + "font": "Roboto", + "createdAt": "2023-01-11T18:53:34Z" + } + ], + "reactionCount": 33, + "topReactions": [ + { + "id": 41010, + "emoji": "🥹", + "count": 14 + } + ] + }, + { + "id": 96101, + "name": "송혜교", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/96101/600/400", + "createdAt": "2023-05-16T19:22:33Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 8754, + "recipientId": 96101, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/31/200/200", + "relationship": "동료", + "content": "전지현님의 메세지 내용 8", + "font": "Nanum Gothic", + "createdAt": "2024-01-30T09:22:34Z" + }, + { + "id": 83212, + "recipientId": 96101, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/276/200/200", + "relationship": "동료", + "content": "현빈님의 메세지 내용 10", + "font": "Pretendard", + "createdAt": "2023-11-29T06:01:50Z" + }, + { + "id": 97718, + "recipientId": 96101, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/76/200/200", + "relationship": "동료", + "content": "전지현님의 메세지 내용 93", + "font": "Pretendard", + "createdAt": "2023-07-19T21:00:40Z" + } + ], + "reactionCount": 86, + "topReactions": [ + { + "id": 42848, + "emoji": "🥹", + "count": 4 + }, + { + "id": 30829, + "emoji": "🎉", + "count": 5 + }, + { + "id": 89207, + "emoji": "😁", + "count": 11 + }, + { + "id": 82766, + "emoji": "😀", + "count": 7 + }, + { + "id": 95876, + "emoji": "🎉", + "count": 6 + } + ] + }, + { + "id": 34177, + "name": "송혜교", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/34177/600/400", + "createdAt": "2023-01-14T02:09:25Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 67802, + "recipientId": 34177, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/498/200/200", + "relationship": "가족", + "content": "정우성님의 메세지 내용 23", + "font": "Pretendard", + "createdAt": "2023-05-17T08:09:24Z" + }, + { + "id": 71447, + "recipientId": 34177, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/372/200/200", + "relationship": "친구", + "content": "최민수님의 메세지 내용 52", + "font": "Nanum Gothic", + "createdAt": "2023-06-17T03:43:25Z" + }, + { + "id": 55931, + "recipientId": 34177, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/385/200/200", + "relationship": "가족", + "content": "한지민님의 메세지 내용 89", + "font": "Noto Sans", + "createdAt": "2023-01-13T07:49:49Z" + } + ], + "reactionCount": 43, + "topReactions": [ + { + "id": 70355, + "emoji": "🎉", + "count": 8 + }, + { + "id": 23001, + "emoji": "😁", + "count": 16 + }, + { + "id": 16865, + "emoji": "🎉", + "count": 20 + }, + { + "id": 85383, + "emoji": "👍", + "count": 1 + }, + { + "id": 62476, + "emoji": "👍", + "count": 2 + }, + { + "id": 25834, + "emoji": "👍", + "count": 1 + } + ] + }, + { + "id": 36016, + "name": "정우성", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-11-15T11:01:43Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 36042, + "recipientId": 36016, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/140/200/200", + "relationship": "지인", + "content": "현빈님의 메세지 내용 42", + "font": "Noto Sans", + "createdAt": "2023-04-26T16:56:26Z" + }, + { + "id": 98913, + "recipientId": 36016, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/439/200/200", + "relationship": "동료", + "content": "이영준님의 메세지 내용 98", + "font": "Roboto", + "createdAt": "2023-04-04T05:29:41Z" + } + ], + "reactionCount": 51, + "topReactions": [ + { + "id": 79191, + "emoji": "😀", + "count": 17 + }, + { + "id": 99981, + "emoji": "😀", + "count": 7 + }, + { + "id": 77927, + "emoji": "🎉", + "count": 4 + } + ] + }, + { + "id": 43594, + "name": "김하은", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-11-09T19:23:06Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 42515, + "recipientId": 43594, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/458/200/200", + "relationship": "동료", + "content": "최민수님의 메세지 내용 27", + "font": "Nanum Gothic", + "createdAt": "2023-08-31T23:26:56Z" + }, + { + "id": 13825, + "recipientId": 43594, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/331/200/200", + "relationship": "지인", + "content": "한지민님의 메세지 내용 29", + "font": "Noto Sans", + "createdAt": "2023-12-05T11:12:30Z" + }, + { + "id": 5602, + "recipientId": 43594, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/430/200/200", + "relationship": "친구", + "content": "김하은님의 메세지 내용 99", + "font": "Pretendard", + "createdAt": "2023-05-05T13:59:19Z" + } + ], + "reactionCount": 13, + "topReactions": [ + { + "id": 22643, + "emoji": "👍", + "count": 19 + }, + { + "id": 77117, + "emoji": "😁", + "count": 8 + }, + { + "id": 35930, + "emoji": "❤️", + "count": 8 + }, + { + "id": 86858, + "emoji": "🎉", + "count": 16 + } + ] + }, + { + "id": 73798, + "name": "한지민", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/73798/600/400", + "createdAt": "2023-11-07T13:40:42Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 33420, + "recipientId": 73798, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/297/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 34", + "font": "Roboto", + "createdAt": "2023-04-26T15:23:15Z" + }, + { + "id": 93059, + "recipientId": 73798, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/252/200/200", + "relationship": "지인", + "content": "이병헌님의 메세지 내용 99", + "font": "Roboto", + "createdAt": "2023-11-21T09:01:45Z" + }, + { + "id": 56278, + "recipientId": 73798, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/102/200/200", + "relationship": "지인", + "content": "송혜교님의 메세지 내용 9", + "font": "Roboto", + "createdAt": "2024-01-17T01:00:57Z" + } + ], + "reactionCount": 71, + "topReactions": [ + { + "id": 31784, + "emoji": "😁", + "count": 6 + }, + { + "id": 52139, + "emoji": "🥹", + "count": 7 + }, + { + "id": 20530, + "emoji": "😁", + "count": 9 + }, + { + "id": 12585, + "emoji": "👍", + "count": 11 + }, + { + "id": 6677, + "emoji": "❤️", + "count": 6 + } + ] + }, + { + "id": 36247, + "name": "전지현", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-03-31T09:45:14Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 7590, + "recipientId": 36247, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/419/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 79", + "font": "Roboto", + "createdAt": "2023-12-24T23:43:44Z" + }, + { + "id": 93972, + "recipientId": 36247, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/239/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 75", + "font": "Roboto", + "createdAt": "2024-01-29T06:48:53Z" + }, + { + "id": 50155, + "recipientId": 36247, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/24/200/200", + "relationship": "지인", + "content": "한지민님의 메세지 내용 5", + "font": "Pretendard", + "createdAt": "2023-09-29T15:59:52Z" + } + ], + "reactionCount": 53, + "topReactions": [ + { + "id": 16359, + "emoji": "😁", + "count": 4 + }, + { + "id": 63702, + "emoji": "😁", + "count": 11 + }, + { + "id": 74672, + "emoji": "😁", + "count": 18 + } + ] + }, + { + "id": 3992, + "name": "전지현", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-01-07T22:06:39Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 92492, + "recipientId": 3992, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/20/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 70", + "font": "Noto Sans", + "createdAt": "2023-05-09T01:45:03Z" + }, + { + "id": 33941, + "recipientId": 3992, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/364/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 93", + "font": "Pretendard", + "createdAt": "2023-02-13T23:03:26Z" + }, + { + "id": 86140, + "recipientId": 3992, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/276/200/200", + "relationship": "친구", + "content": "현빈님의 메세지 내용 22", + "font": "Pretendard", + "createdAt": "2023-05-26T22:01:31Z" + } + ], + "reactionCount": 28, + "topReactions": [ + { + "id": 59388, + "emoji": "🎉", + "count": 4 + } + ] + }, + { + "id": 55254, + "name": "이영준", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-04-20T01:09:02Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 34003, + "recipientId": 55254, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/482/200/200", + "relationship": "가족", + "content": "한지민님의 메세지 내용 83", + "font": "Nanum Gothic", + "createdAt": "2023-07-15T10:19:57Z" + }, + { + "id": 79633, + "recipientId": 55254, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/187/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 63", + "font": "Roboto", + "createdAt": "2023-11-14T17:55:45Z" + }, + { + "id": 10233, + "recipientId": 55254, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/491/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 26", + "font": "Roboto", + "createdAt": "2023-06-23T02:56:08Z" + } + ], + "reactionCount": 43, + "topReactions": [ + { + "id": 3962, + "emoji": "🥹", + "count": 17 + } + ] + }, + { + "id": 63758, + "name": "정우성", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-06-21T03:01:01Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 90458, + "recipientId": 63758, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/111/200/200", + "relationship": "동료", + "content": "정우성님의 메세지 내용 49", + "font": "Nanum Gothic", + "createdAt": "2023-05-12T19:29:28Z" + }, + { + "id": 89359, + "recipientId": 63758, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/401/200/200", + "relationship": "지인", + "content": "이병헌님의 메세지 내용 53", + "font": "Roboto", + "createdAt": "2023-05-10T19:04:15Z" + }, + { + "id": 57663, + "recipientId": 63758, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/215/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 87", + "font": "Roboto", + "createdAt": "2023-05-27T20:40:23Z" + } + ], + "reactionCount": 56, + "topReactions": [ + { + "id": 52289, + "emoji": "😁", + "count": 7 + } + ] + }, + { + "id": 63073, + "name": "최민수", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-07-13T16:42:26Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 60054, + "recipientId": 63073, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/46/200/200", + "relationship": "지인", + "content": "전지현님의 메세지 내용 69", + "font": "Noto Sans", + "createdAt": "2023-01-01T10:21:56Z" + } + ], + "reactionCount": 69, + "topReactions": [ + { + "id": 75660, + "emoji": "🥹", + "count": 13 + }, + { + "id": 30629, + "emoji": "❤️", + "count": 6 + } + ] + }, + { + "id": 66658, + "name": "최민수", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/66658/600/400", + "createdAt": "2023-07-23T23:50:37Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 25811, + "recipientId": 66658, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/417/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 98", + "font": "Roboto", + "createdAt": "2023-06-18T13:53:21Z" + }, + { + "id": 7862, + "recipientId": 66658, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/188/200/200", + "relationship": "지인", + "content": "이영준님의 메세지 내용 8", + "font": "Nanum Gothic", + "createdAt": "2023-07-07T23:55:45Z" + }, + { + "id": 16602, + "recipientId": 66658, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/446/200/200", + "relationship": "지인", + "content": "박서준님의 메세지 내용 44", + "font": "Pretendard", + "createdAt": "2023-03-24T18:20:49Z" + } + ], + "reactionCount": 26, + "topReactions": [ + { + "id": 68634, + "emoji": "👍", + "count": 16 + }, + { + "id": 74041, + "emoji": "🥹", + "count": 12 + }, + { + "id": 834, + "emoji": "🥹", + "count": 5 + } + ] + }, + { + "id": 63096, + "name": "이병헌", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/63096/600/400", + "createdAt": "2023-08-25T09:30:08Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 72995, + "recipientId": 63096, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/368/200/200", + "relationship": "동료", + "content": "이병헌님의 메세지 내용 44", + "font": "Pretendard", + "createdAt": "2023-10-07T18:41:59Z" + }, + { + "id": 54115, + "recipientId": 63096, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/335/200/200", + "relationship": "친구", + "content": "박서준님의 메세지 내용 41", + "font": "Roboto", + "createdAt": "2023-11-02T10:19:13Z" + }, + { + "id": 56992, + "recipientId": 63096, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/482/200/200", + "relationship": "친구", + "content": "최민수님의 메세지 내용 30", + "font": "Pretendard", + "createdAt": "2023-12-30T21:02:26Z" + } + ], + "reactionCount": 90, + "topReactions": [ + { + "id": 30117, + "emoji": "🎉", + "count": 14 + }, + { + "id": 52187, + "emoji": "👍", + "count": 6 + }, + { + "id": 18011, + "emoji": "🎉", + "count": 17 + } + ] + }, + { + "id": 13289, + "name": "박서준", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-12-04T12:58:18Z", + "messageCount": 3, + "recentMessages": [ + { + "id": 44494, + "recipientId": 13289, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/118/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 64", + "font": "Nanum Gothic", + "createdAt": "2024-01-29T16:37:33Z" + }, + { + "id": 13927, + "recipientId": 13289, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/328/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 31", + "font": "Noto Sans", + "createdAt": "2023-02-23T01:04:06Z" + }, + { + "id": 11952, + "recipientId": 13289, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/205/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 11", + "font": "Nanum Gothic", + "createdAt": "2023-05-25T08:12:10Z" + } + ], + "reactionCount": 20, + "topReactions": [ + { + "id": 27582, + "emoji": "🥹", + "count": 5 + }, + { + "id": 7453, + "emoji": "😁", + "count": 15 + }, + { + "id": 32011, + "emoji": "🥹", + "count": 14 + }, + { + "id": 18525, + "emoji": "🎉", + "count": 8 + }, + { + "id": 15768, + "emoji": "😀", + "count": 19 + }, + { + "id": 14938, + "emoji": "👍", + "count": 6 + } + ] + }, + { + "id": 39580, + "name": "송혜교", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/39580/600/400", + "createdAt": "2023-08-16T00:55:39Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 27255, + "recipientId": 39580, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/195/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 1", + "font": "Roboto", + "createdAt": "2023-01-01T19:38:10Z" + }, + { + "id": 63506, + "recipientId": 39580, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/120/200/200", + "relationship": "동료", + "content": "현빈님의 메세지 내용 13", + "font": "Nanum Gothic", + "createdAt": "2023-09-14T22:10:26Z" + }, + { + "id": 55735, + "recipientId": 39580, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/437/200/200", + "relationship": "친구", + "content": "현빈님의 메세지 내용 54", + "font": "Nanum Gothic", + "createdAt": "2023-09-07T03:32:34Z" + } + ], + "reactionCount": 63, + "topReactions": [ + { + "id": 75593, + "emoji": "🎉", + "count": 17 + }, + { + "id": 86152, + "emoji": "👍", + "count": 18 + }, + { + "id": 94679, + "emoji": "❤️", + "count": 19 + }, + { + "id": 93225, + "emoji": "😁", + "count": 3 + }, + { + "id": 50484, + "emoji": "🎉", + "count": 9 + }, + { + "id": 97858, + "emoji": "👍", + "count": 2 + } + ] + }, + { + "id": 57125, + "name": "전지현", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-02-18T07:04:21Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 91193, + "recipientId": 57125, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/448/200/200", + "relationship": "동료", + "content": "송혜교님의 메세지 내용 49", + "font": "Pretendard", + "createdAt": "2023-06-20T16:12:07Z" + }, + { + "id": 77931, + "recipientId": 57125, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/486/200/200", + "relationship": "지인", + "content": "한지민님의 메세지 내용 94", + "font": "Nanum Gothic", + "createdAt": "2023-12-29T17:04:41Z" + }, + { + "id": 41786, + "recipientId": 57125, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/39/200/200", + "relationship": "친구", + "content": "이영준님의 메세지 내용 84", + "font": "Pretendard", + "createdAt": "2023-07-15T19:00:07Z" + } + ], + "reactionCount": 98, + "topReactions": [ + { + "id": 11291, + "emoji": "🥹", + "count": 9 + }, + { + "id": 71787, + "emoji": "😀", + "count": 19 + } + ] + }, + { + "id": 94817, + "name": "최민수", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/94817/600/400", + "createdAt": "2023-05-07T10:26:03Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 84068, + "recipientId": 94817, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/186/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 35", + "font": "Nanum Gothic", + "createdAt": "2023-10-16T23:50:30Z" + }, + { + "id": 16638, + "recipientId": 94817, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/11/200/200", + "relationship": "친구", + "content": "김하은님의 메세지 내용 51", + "font": "Roboto", + "createdAt": "2023-12-31T02:34:22Z" + }, + { + "id": 19857, + "recipientId": 94817, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/364/200/200", + "relationship": "동료", + "content": "전지현님의 메세지 내용 87", + "font": "Pretendard", + "createdAt": "2023-04-01T17:28:06Z" + } + ], + "reactionCount": 69, + "topReactions": [ + { + "id": 29485, + "emoji": "😁", + "count": 16 + }, + { + "id": 51258, + "emoji": "😁", + "count": 14 + }, + { + "id": 24027, + "emoji": "😁", + "count": 18 + }, + { + "id": 86629, + "emoji": "😀", + "count": 4 + } + ] + }, + { + "id": 8900, + "name": "박서준", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/8900/600/400", + "createdAt": "2023-08-06T08:59:01Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 54900, + "recipientId": 8900, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/448/200/200", + "relationship": "지인", + "content": "현빈님의 메세지 내용 91", + "font": "Pretendard", + "createdAt": "2023-10-16T00:46:38Z" + } + ], + "reactionCount": 52, + "topReactions": [ + { + "id": 78028, + "emoji": "👍", + "count": 7 + }, + { + "id": 81658, + "emoji": "👍", + "count": 8 + }, + { + "id": 99396, + "emoji": "❤️", + "count": 1 + }, + { + "id": 91845, + "emoji": "🎉", + "count": 4 + }, + { + "id": 95208, + "emoji": "👍", + "count": 5 + } + ] + }, + { + "id": 3922, + "name": "박서준", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/3922/600/400", + "createdAt": "2023-10-23T08:41:22Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 99355, + "recipientId": 3922, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/125/200/200", + "relationship": "친구", + "content": "전지현님의 메세지 내용 62", + "font": "Pretendard", + "createdAt": "2023-09-14T05:24:27Z" + }, + { + "id": 34171, + "recipientId": 3922, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/154/200/200", + "relationship": "친구", + "content": "이영준님의 메세지 내용 28", + "font": "Pretendard", + "createdAt": "2023-08-04T22:53:11Z" + } + ], + "reactionCount": 55, + "topReactions": [ + { + "id": 63963, + "emoji": "😀", + "count": 11 + }, + { + "id": 26888, + "emoji": "😀", + "count": 14 + }, + { + "id": 5147, + "emoji": "😁", + "count": 15 + }, + { + "id": 47112, + "emoji": "❤️", + "count": 7 + } + ] + }, + { + "id": 66190, + "name": "전지현", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-07-08T04:47:00Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 17000, + "recipientId": 66190, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/498/200/200", + "relationship": "동료", + "content": "이영준님의 메세지 내용 26", + "font": "Nanum Gothic", + "createdAt": "2023-07-12T15:08:11Z" + }, + { + "id": 65326, + "recipientId": 66190, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/286/200/200", + "relationship": "동료", + "content": "한지민님의 메세지 내용 43", + "font": "Noto Sans", + "createdAt": "2023-04-14T16:41:19Z" + }, + { + "id": 33150, + "recipientId": 66190, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/26/200/200", + "relationship": "지인", + "content": "이병헌님의 메세지 내용 47", + "font": "Roboto", + "createdAt": "2024-01-22T00:03:15Z" + } + ], + "reactionCount": 29, + "topReactions": [ + { + "id": 30808, + "emoji": "🥹", + "count": 20 + }, + { + "id": 18642, + "emoji": "😀", + "count": 9 + } + ] + }, + { + "id": 68635, + "name": "이병헌", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-10-22T10:14:45Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 97206, + "recipientId": 68635, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/26/200/200", + "relationship": "친구", + "content": "김하은님의 메세지 내용 2", + "font": "Roboto", + "createdAt": "2023-08-28T16:03:45Z" + }, + { + "id": 37796, + "recipientId": 68635, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/203/200/200", + "relationship": "친구", + "content": "박서준님의 메세지 내용 68", + "font": "Pretendard", + "createdAt": "2023-01-17T12:45:37Z" + }, + { + "id": 40502, + "recipientId": 68635, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/40/200/200", + "relationship": "지인", + "content": "송혜교님의 메세지 내용 71", + "font": "Roboto", + "createdAt": "2023-05-14T12:47:53Z" + } + ], + "reactionCount": 18, + "topReactions": [ + { + "id": 98726, + "emoji": "😀", + "count": 15 + }, + { + "id": 65169, + "emoji": "🥹", + "count": 3 + }, + { + "id": 8481, + "emoji": "🥹", + "count": 12 + } + ] + }, + { + "id": 52236, + "name": "현빈", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2024-01-07T08:24:21Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 8378, + "recipientId": 52236, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/383/200/200", + "relationship": "동료", + "content": "이병헌님의 메세지 내용 53", + "font": "Pretendard", + "createdAt": "2023-12-03T19:03:51Z" + } + ], + "reactionCount": 48, + "topReactions": [ + { + "id": 89637, + "emoji": "😀", + "count": 8 + } + ] + }, + { + "id": 81115, + "name": "전지현", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/81115/600/400", + "createdAt": "2023-06-05T18:41:55Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 97959, + "recipientId": 81115, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/187/200/200", + "relationship": "지인", + "content": "정우성님의 메세지 내용 26", + "font": "Roboto", + "createdAt": "2023-05-31T04:49:25Z" + }, + { + "id": 14027, + "recipientId": 81115, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/400/200/200", + "relationship": "가족", + "content": "이병헌님의 메세지 내용 48", + "font": "Noto Sans", + "createdAt": "2023-09-18T14:09:01Z" + }, + { + "id": 44822, + "recipientId": 81115, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/72/200/200", + "relationship": "동료", + "content": "송혜교님의 메세지 내용 69", + "font": "Roboto", + "createdAt": "2023-01-23T11:25:20Z" + } + ], + "reactionCount": 93, + "topReactions": [ + { + "id": 89132, + "emoji": "🎉", + "count": 18 + } + ] + }, + { + "id": 10154, + "name": "전지현", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/10154/600/400", + "createdAt": "2023-06-12T22:34:51Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 60424, + "recipientId": 10154, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/403/200/200", + "relationship": "지인", + "content": "박서준님의 메세지 내용 75", + "font": "Nanum Gothic", + "createdAt": "2023-12-05T21:36:47Z" + }, + { + "id": 95935, + "recipientId": 10154, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/400/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 12", + "font": "Pretendard", + "createdAt": "2023-04-29T17:49:22Z" + }, + { + "id": 21882, + "recipientId": 10154, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/384/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 22", + "font": "Noto Sans", + "createdAt": "2023-07-08T02:01:05Z" + } + ], + "reactionCount": 93, + "topReactions": [ + { + "id": 21925, + "emoji": "😀", + "count": 4 + } + ] + }, + { + "id": 13587, + "name": "송혜교", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/13587/600/400", + "createdAt": "2023-12-29T20:05:55Z", + "messageCount": 3, + "recentMessages": [ + { + "id": 27566, + "recipientId": 13587, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/368/200/200", + "relationship": "지인", + "content": "박서준님의 메세지 내용 6", + "font": "Nanum Gothic", + "createdAt": "2023-10-20T11:16:20Z" + }, + { + "id": 2019, + "recipientId": 13587, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/478/200/200", + "relationship": "동료", + "content": "송혜교님의 메세지 내용 26", + "font": "Noto Sans", + "createdAt": "2023-08-01T07:45:11Z" + }, + { + "id": 54173, + "recipientId": 13587, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/284/200/200", + "relationship": "동료", + "content": "한지민님의 메세지 내용 41", + "font": "Nanum Gothic", + "createdAt": "2023-02-02T17:16:38Z" + } + ], + "reactionCount": 10, + "topReactions": [ + { + "id": 71407, + "emoji": "😁", + "count": 11 + } + ] + }, + { + "id": 1309, + "name": "김하은", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/1309/600/400", + "createdAt": "2023-08-30T03:31:58Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 76069, + "recipientId": 1309, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/59/200/200", + "relationship": "친구", + "content": "전지현님의 메세지 내용 64", + "font": "Pretendard", + "createdAt": "2023-08-15T14:13:51Z" + }, + { + "id": 57299, + "recipientId": 1309, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/23/200/200", + "relationship": "가족", + "content": "전지현님의 메세지 내용 2", + "font": "Roboto", + "createdAt": "2023-09-25T10:40:09Z" + }, + { + "id": 83909, + "recipientId": 1309, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/355/200/200", + "relationship": "가족", + "content": "현빈님의 메세지 내용 53", + "font": "Roboto", + "createdAt": "2023-05-08T18:45:38Z" + } + ], + "reactionCount": 30, + "topReactions": [ + { + "id": 45061, + "emoji": "❤️", + "count": 20 + }, + { + "id": 40818, + "emoji": "❤️", + "count": 20 + }, + { + "id": 86400, + "emoji": "🥹", + "count": 3 + }, + { + "id": 90349, + "emoji": "🥹", + "count": 1 + }, + { + "id": 307, + "emoji": "😁", + "count": 9 + } + ] + }, + { + "id": 60, + "name": "현빈", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/60/600/400", + "createdAt": "2023-07-09T12:28:11Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 74309, + "recipientId": 60, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/65/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 96", + "font": "Noto Sans", + "createdAt": "2023-08-25T21:47:15Z" + }, + { + "id": 94122, + "recipientId": 60, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/141/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 57", + "font": "Roboto", + "createdAt": "2023-09-05T23:47:09Z" + }, + { + "id": 16314, + "recipientId": 60, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/345/200/200", + "relationship": "동료", + "content": "이병헌님의 메세지 내용 52", + "font": "Roboto", + "createdAt": "2023-03-07T04:55:33Z" + } + ], + "reactionCount": 50, + "topReactions": [ + { + "id": 58906, + "emoji": "😀", + "count": 1 + }, + { + "id": 50471, + "emoji": "🎉", + "count": 7 + } + ] + }, + { + "id": 66554, + "name": "현빈", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/66554/600/400", + "createdAt": "2023-02-08T20:35:33Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 66047, + "recipientId": 66554, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/500/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 92", + "font": "Pretendard", + "createdAt": "2023-04-08T22:14:02Z" + }, + { + "id": 81467, + "recipientId": 66554, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/487/200/200", + "relationship": "가족", + "content": "이병헌님의 메세지 내용 17", + "font": "Nanum Gothic", + "createdAt": "2023-03-16T05:19:39Z" + }, + { + "id": 63910, + "recipientId": 66554, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/348/200/200", + "relationship": "지인", + "content": "정우성님의 메세지 내용 66", + "font": "Nanum Gothic", + "createdAt": "2023-08-22T16:52:48Z" + } + ], + "reactionCount": 78, + "topReactions": [ + { + "id": 11998, + "emoji": "😀", + "count": 1 + }, + { + "id": 43630, + "emoji": "❤️", + "count": 5 + }, + { + "id": 4909, + "emoji": "🥹", + "count": 10 + }, + { + "id": 15023, + "emoji": "😁", + "count": 4 + } + ] + }, + { + "id": 50312, + "name": "현빈", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-02-27T12:29:12Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 33254, + "recipientId": 50312, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/460/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 22", + "font": "Nanum Gothic", + "createdAt": "2023-04-14T03:51:21Z" + }, + { + "id": 19330, + "recipientId": 50312, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/435/200/200", + "relationship": "가족", + "content": "전지현님의 메세지 내용 14", + "font": "Pretendard", + "createdAt": "2023-03-07T02:10:58Z" + }, + { + "id": 15393, + "recipientId": 50312, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/59/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 12", + "font": "Nanum Gothic", + "createdAt": "2023-01-11T22:57:14Z" + } + ], + "reactionCount": 97, + "topReactions": [ + { + "id": 73411, + "emoji": "❤️", + "count": 14 + }, + { + "id": 26879, + "emoji": "🥹", + "count": 9 + } + ] + }, + { + "id": 33720, + "name": "송혜교", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-07-18T19:49:30Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 81755, + "recipientId": 33720, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/338/200/200", + "relationship": "친구", + "content": "최민수님의 메세지 내용 25", + "font": "Nanum Gothic", + "createdAt": "2024-01-25T12:37:51Z" + } + ], + "reactionCount": 41, + "topReactions": [ + { + "id": 69423, + "emoji": "🥹", + "count": 19 + }, + { + "id": 37533, + "emoji": "🎉", + "count": 10 + }, + { + "id": 73552, + "emoji": "😁", + "count": 5 + }, + { + "id": 58186, + "emoji": "🥹", + "count": 8 + }, + { + "id": 26741, + "emoji": "😁", + "count": 18 + }, + { + "id": 8330, + "emoji": "❤️", + "count": 6 + } + ] + }, + { + "id": 89805, + "name": "전지현", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/89805/600/400", + "createdAt": "2023-08-19T06:07:50Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 7586, + "recipientId": 89805, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/442/200/200", + "relationship": "가족", + "content": "이영준님의 메세지 내용 63", + "font": "Pretendard", + "createdAt": "2023-01-04T13:08:22Z" + }, + { + "id": 86570, + "recipientId": 89805, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/258/200/200", + "relationship": "동료", + "content": "현빈님의 메세지 내용 10", + "font": "Roboto", + "createdAt": "2023-08-21T15:47:23Z" + } + ], + "reactionCount": 35, + "topReactions": [ + { + "id": 44310, + "emoji": "🥹", + "count": 4 + }, + { + "id": 10011, + "emoji": "❤️", + "count": 6 + }, + { + "id": 8641, + "emoji": "🥹", + "count": 4 + } + ] + }, + { + "id": 31459, + "name": "최민수", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/31459/600/400", + "createdAt": "2023-06-23T11:39:38Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 98356, + "recipientId": 31459, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/139/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 14", + "font": "Nanum Gothic", + "createdAt": "2023-03-11T09:10:45Z" + }, + { + "id": 37388, + "recipientId": 31459, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/355/200/200", + "relationship": "친구", + "content": "박서준님의 메세지 내용 57", + "font": "Nanum Gothic", + "createdAt": "2023-02-22T09:31:25Z" + }, + { + "id": 19962, + "recipientId": 31459, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/80/200/200", + "relationship": "동료", + "content": "이병헌님의 메세지 내용 11", + "font": "Nanum Gothic", + "createdAt": "2023-11-26T04:31:20Z" + } + ], + "reactionCount": 21, + "topReactions": [ + { + "id": 4005, + "emoji": "😀", + "count": 7 + } + ] + }, + { + "id": 98283, + "name": "최민수", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/98283/600/400", + "createdAt": "2023-07-15T05:18:24Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 30487, + "recipientId": 98283, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/228/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 61", + "font": "Nanum Gothic", + "createdAt": "2023-12-02T07:23:57Z" + }, + { + "id": 46260, + "recipientId": 98283, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/362/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 2", + "font": "Roboto", + "createdAt": "2024-01-05T15:10:35Z" + }, + { + "id": 21359, + "recipientId": 98283, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/309/200/200", + "relationship": "지인", + "content": "김하은님의 메세지 내용 25", + "font": "Roboto", + "createdAt": "2023-12-23T15:06:51Z" + } + ], + "reactionCount": 5, + "topReactions": [ + { + "id": 5588, + "emoji": "❤️", + "count": 5 + }, + { + "id": 98400, + "emoji": "🥹", + "count": 13 + }, + { + "id": 5484, + "emoji": "❤️", + "count": 16 + }, + { + "id": 40058, + "emoji": "🎉", + "count": 2 + }, + { + "id": 51056, + "emoji": "👍", + "count": 14 + }, + { + "id": 31995, + "emoji": "🎉", + "count": 12 + } + ] + }, + { + "id": 37766, + "name": "현빈", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-02-25T16:44:40Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 12013, + "recipientId": 37766, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/343/200/200", + "relationship": "지인", + "content": "이영준님의 메세지 내용 33", + "font": "Nanum Gothic", + "createdAt": "2024-01-27T17:03:16Z" + }, + { + "id": 63267, + "recipientId": 37766, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/318/200/200", + "relationship": "가족", + "content": "현빈님의 메세지 내용 37", + "font": "Nanum Gothic", + "createdAt": "2023-10-30T06:35:37Z" + }, + { + "id": 32221, + "recipientId": 37766, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/254/200/200", + "relationship": "지인", + "content": "김하은님의 메세지 내용 51", + "font": "Nanum Gothic", + "createdAt": "2023-05-22T08:02:04Z" + } + ], + "reactionCount": 6, + "topReactions": [ + { + "id": 51742, + "emoji": "🥹", + "count": 6 + }, + { + "id": 48690, + "emoji": "🎉", + "count": 2 + }, + { + "id": 50705, + "emoji": "😀", + "count": 14 + }, + { + "id": 8991, + "emoji": "😀", + "count": 10 + }, + { + "id": 12174, + "emoji": "🥹", + "count": 9 + }, + { + "id": 10137, + "emoji": "😀", + "count": 10 + } + ] + }, + { + "id": 55770, + "name": "김하은", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/55770/600/400", + "createdAt": "2023-08-08T18:49:27Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 98997, + "recipientId": 55770, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/310/200/200", + "relationship": "지인", + "content": "정우성님의 메세지 내용 76", + "font": "Pretendard", + "createdAt": "2023-12-28T10:22:01Z" + }, + { + "id": 52895, + "recipientId": 55770, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/192/200/200", + "relationship": "가족", + "content": "이영준님의 메세지 내용 58", + "font": "Pretendard", + "createdAt": "2024-01-11T11:32:14Z" + }, + { + "id": 45725, + "recipientId": 55770, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/188/200/200", + "relationship": "친구", + "content": "이영준님의 메세지 내용 29", + "font": "Roboto", + "createdAt": "2023-07-13T20:07:35Z" + } + ], + "reactionCount": 90, + "topReactions": [ + { + "id": 16362, + "emoji": "😁", + "count": 14 + }, + { + "id": 6576, + "emoji": "🥹", + "count": 14 + }, + { + "id": 78222, + "emoji": "🎉", + "count": 1 + }, + { + "id": 62128, + "emoji": "😁", + "count": 18 + } + ] + }, + { + "id": 41885, + "name": "송혜교", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-09-29T17:30:26Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 3980, + "recipientId": 41885, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/124/200/200", + "relationship": "지인", + "content": "전지현님의 메세지 내용 53", + "font": "Nanum Gothic", + "createdAt": "2023-02-11T20:10:45Z" + }, + { + "id": 24156, + "recipientId": 41885, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/360/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 14", + "font": "Noto Sans", + "createdAt": "2023-07-13T21:35:18Z" + }, + { + "id": 88059, + "recipientId": 41885, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/182/200/200", + "relationship": "지인", + "content": "현빈님의 메세지 내용 33", + "font": "Pretendard", + "createdAt": "2023-08-04T15:40:39Z" + } + ], + "reactionCount": 9, + "topReactions": [ + { + "id": 31604, + "emoji": "😀", + "count": 15 + }, + { + "id": 7967, + "emoji": "😁", + "count": 2 + }, + { + "id": 52857, + "emoji": "🥹", + "count": 14 + }, + { + "id": 52766, + "emoji": "😀", + "count": 13 + } + ] + }, + { + "id": 11840, + "name": "송혜교", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/11840/600/400", + "createdAt": "2024-01-31T05:35:10Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 15003, + "recipientId": 11840, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/98/200/200", + "relationship": "지인", + "content": "김하은님의 메세지 내용 76", + "font": "Noto Sans", + "createdAt": "2023-07-19T06:37:06Z" + }, + { + "id": 11159, + "recipientId": 11840, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/7/200/200", + "relationship": "지인", + "content": "김하은님의 메세지 내용 99", + "font": "Noto Sans", + "createdAt": "2023-02-04T05:57:58Z" + }, + { + "id": 11261, + "recipientId": 11840, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/444/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 43", + "font": "Nanum Gothic", + "createdAt": "2023-03-31T14:51:43Z" + } + ], + "reactionCount": 21, + "topReactions": [ + { + "id": 13179, + "emoji": "🎉", + "count": 3 + }, + { + "id": 5003, + "emoji": "🥹", + "count": 1 + }, + { + "id": 37584, + "emoji": "🥹", + "count": 4 + }, + { + "id": 63440, + "emoji": "🎉", + "count": 4 + } + ] + }, + { + "id": 84895, + "name": "한지민", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/84895/600/400", + "createdAt": "2023-04-23T06:14:19Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 94574, + "recipientId": 84895, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/3/200/200", + "relationship": "지인", + "content": "이영준님의 메세지 내용 13", + "font": "Noto Sans", + "createdAt": "2023-01-18T07:30:08Z" + } + ], + "reactionCount": 37, + "topReactions": [ + { + "id": 1985, + "emoji": "👍", + "count": 9 + }, + { + "id": 65556, + "emoji": "❤️", + "count": 7 + }, + { + "id": 96682, + "emoji": "😁", + "count": 9 + }, + { + "id": 49044, + "emoji": "🎉", + "count": 13 + }, + { + "id": 76158, + "emoji": "❤️", + "count": 7 + } + ] + }, + { + "id": 74955, + "name": "현빈", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/74955/600/400", + "createdAt": "2023-03-01T11:31:01Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 27531, + "recipientId": 74955, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/466/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 17", + "font": "Noto Sans", + "createdAt": "2023-09-22T15:59:45Z" + } + ], + "reactionCount": 33, + "topReactions": [ + { + "id": 38198, + "emoji": "😁", + "count": 5 + }, + { + "id": 75156, + "emoji": "🥹", + "count": 11 + }, + { + "id": 85523, + "emoji": "🥹", + "count": 4 + }, + { + "id": 68198, + "emoji": "🎉", + "count": 5 + }, + { + "id": 91, + "emoji": "😁", + "count": 9 + }, + { + "id": 249, + "emoji": "😀", + "count": 4 + } + ] + }, + { + "id": 91125, + "name": "이영준", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/91125/600/400", + "createdAt": "2023-01-25T16:51:01Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 81022, + "recipientId": 91125, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/157/200/200", + "relationship": "친구", + "content": "이영준님의 메세지 내용 90", + "font": "Noto Sans", + "createdAt": "2023-09-19T23:00:03Z" + }, + { + "id": 51294, + "recipientId": 91125, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/284/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 26", + "font": "Noto Sans", + "createdAt": "2024-01-29T11:52:15Z" + } + ], + "reactionCount": 28, + "topReactions": [ + { + "id": 13204, + "emoji": "😀", + "count": 13 + }, + { + "id": 16155, + "emoji": "🎉", + "count": 19 + }, + { + "id": 68608, + "emoji": "😀", + "count": 18 + }, + { + "id": 78848, + "emoji": "😀", + "count": 18 + }, + { + "id": 4799, + "emoji": "👍", + "count": 12 + } + ] + }, + { + "id": 57687, + "name": "한지민", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/57687/600/400", + "createdAt": "2023-11-07T02:40:34Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 12712, + "recipientId": 57687, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/148/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 27", + "font": "Roboto", + "createdAt": "2023-11-26T12:14:09Z" + }, + { + "id": 28850, + "recipientId": 57687, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/109/200/200", + "relationship": "친구", + "content": "현빈님의 메세지 내용 79", + "font": "Roboto", + "createdAt": "2023-11-16T14:25:15Z" + }, + { + "id": 91115, + "recipientId": 57687, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/335/200/200", + "relationship": "지인", + "content": "현빈님의 메세지 내용 88", + "font": "Nanum Gothic", + "createdAt": "2023-12-06T16:17:35Z" + } + ], + "reactionCount": 100, + "topReactions": [ + { + "id": 72646, + "emoji": "❤️", + "count": 5 + } + ] + }, + { + "id": 52082, + "name": "박서준", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-12-05T11:50:03Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 34872, + "recipientId": 52082, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/314/200/200", + "relationship": "지인", + "content": "한지민님의 메세지 내용 79", + "font": "Pretendard", + "createdAt": "2023-06-29T10:39:24Z" + }, + { + "id": 11518, + "recipientId": 52082, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/337/200/200", + "relationship": "지인", + "content": "현빈님의 메세지 내용 82", + "font": "Pretendard", + "createdAt": "2023-01-14T11:17:39Z" + }, + { + "id": 34015, + "recipientId": 52082, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/162/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 42", + "font": "Roboto", + "createdAt": "2023-09-22T11:36:35Z" + } + ], + "reactionCount": 72, + "topReactions": [ + { + "id": 37949, + "emoji": "❤️", + "count": 10 + }, + { + "id": 46408, + "emoji": "😀", + "count": 1 + } + ] + }, + { + "id": 39017, + "name": "정우성", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/39017/600/400", + "createdAt": "2024-01-28T05:11:05Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 45901, + "recipientId": 39017, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/221/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 37", + "font": "Roboto", + "createdAt": "2023-04-24T18:45:37Z" + }, + { + "id": 86974, + "recipientId": 39017, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/96/200/200", + "relationship": "가족", + "content": "한지민님의 메세지 내용 97", + "font": "Nanum Gothic", + "createdAt": "2024-01-06T07:57:03Z" + } + ], + "reactionCount": 100, + "topReactions": [ + { + "id": 51363, + "emoji": "😀", + "count": 9 + } + ] + }, + { + "id": 46642, + "name": "전지현", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2024-01-27T23:23:34Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 86564, + "recipientId": 46642, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/36/200/200", + "relationship": "지인", + "content": "이병헌님의 메세지 내용 78", + "font": "Noto Sans", + "createdAt": "2023-09-23T23:48:17Z" + }, + { + "id": 46880, + "recipientId": 46642, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/453/200/200", + "relationship": "가족", + "content": "이병헌님의 메세지 내용 92", + "font": "Noto Sans", + "createdAt": "2023-06-07T09:44:08Z" + }, + { + "id": 79147, + "recipientId": 46642, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/425/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 45", + "font": "Noto Sans", + "createdAt": "2023-07-14T00:41:05Z" + } + ], + "reactionCount": 24, + "topReactions": [ + { + "id": 50493, + "emoji": "🥹", + "count": 10 + }, + { + "id": 14174, + "emoji": "❤️", + "count": 7 + }, + { + "id": 8164, + "emoji": "😀", + "count": 14 + }, + { + "id": 59391, + "emoji": "😁", + "count": 12 + }, + { + "id": 503, + "emoji": "❤️", + "count": 14 + }, + { + "id": 96571, + "emoji": "❤️", + "count": 7 + } + ] + }, + { + "id": 27652, + "name": "송혜교", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-01-26T14:15:49Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 36699, + "recipientId": 27652, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/323/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 56", + "font": "Noto Sans", + "createdAt": "2023-08-24T00:21:48Z" + }, + { + "id": 75023, + "recipientId": 27652, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/442/200/200", + "relationship": "가족", + "content": "김하은님의 메세지 내용 56", + "font": "Roboto", + "createdAt": "2023-02-11T12:51:39Z" + }, + { + "id": 31848, + "recipientId": 27652, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/273/200/200", + "relationship": "친구", + "content": "최민수님의 메세지 내용 84", + "font": "Nanum Gothic", + "createdAt": "2023-12-04T00:48:02Z" + } + ], + "reactionCount": 93, + "topReactions": [ + { + "id": 90352, + "emoji": "😁", + "count": 1 + } + ] + }, + { + "id": 93469, + "name": "이병헌", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/93469/600/400", + "createdAt": "2023-08-05T08:37:01Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 13315, + "recipientId": 93469, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/407/200/200", + "relationship": "지인", + "content": "한지민님의 메세지 내용 15", + "font": "Noto Sans", + "createdAt": "2023-07-27T04:45:59Z" + }, + { + "id": 29127, + "recipientId": 93469, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/206/200/200", + "relationship": "동료", + "content": "한지민님의 메세지 내용 61", + "font": "Pretendard", + "createdAt": "2023-12-08T16:05:47Z" + }, + { + "id": 40814, + "recipientId": 93469, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/176/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 72", + "font": "Noto Sans", + "createdAt": "2023-04-25T05:08:02Z" + } + ], + "reactionCount": 84, + "topReactions": [ + { + "id": 89622, + "emoji": "🎉", + "count": 13 + }, + { + "id": 63069, + "emoji": "🎉", + "count": 4 + }, + { + "id": 24110, + "emoji": "😀", + "count": 4 + }, + { + "id": 67263, + "emoji": "👍", + "count": 12 + } + ] + }, + { + "id": 45950, + "name": "이병헌", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/45950/600/400", + "createdAt": "2023-04-24T21:39:46Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 25018, + "recipientId": 45950, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/422/200/200", + "relationship": "가족", + "content": "한지민님의 메세지 내용 66", + "font": "Noto Sans", + "createdAt": "2024-02-01T13:50:42Z" + }, + { + "id": 24874, + "recipientId": 45950, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/55/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 32", + "font": "Pretendard", + "createdAt": "2023-09-13T01:51:09Z" + }, + { + "id": 27922, + "recipientId": 45950, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/167/200/200", + "relationship": "동료", + "content": "송혜교님의 메세지 내용 76", + "font": "Nanum Gothic", + "createdAt": "2023-01-10T17:10:48Z" + } + ], + "reactionCount": 45, + "topReactions": [ + { + "id": 39540, + "emoji": "🎉", + "count": 13 + } + ] + }, + { + "id": 92578, + "name": "현빈", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-06-01T11:14:03Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 41959, + "recipientId": 92578, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/160/200/200", + "relationship": "지인", + "content": "전지현님의 메세지 내용 4", + "font": "Nanum Gothic", + "createdAt": "2023-08-16T02:51:30Z" + }, + { + "id": 1530, + "recipientId": 92578, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/438/200/200", + "relationship": "동료", + "content": "현빈님의 메세지 내용 59", + "font": "Roboto", + "createdAt": "2023-03-12T23:02:00Z" + }, + { + "id": 65787, + "recipientId": 92578, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/184/200/200", + "relationship": "가족", + "content": "이영준님의 메세지 내용 88", + "font": "Nanum Gothic", + "createdAt": "2023-05-13T21:14:10Z" + } + ], + "reactionCount": 84, + "topReactions": [ + { + "id": 12098, + "emoji": "👍", + "count": 9 + }, + { + "id": 54057, + "emoji": "😀", + "count": 9 + }, + { + "id": 45620, + "emoji": "👍", + "count": 3 + } + ] + }, + { + "id": 987, + "name": "이영준", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/987/600/400", + "createdAt": "2023-08-21T17:47:59Z", + "messageCount": 3, + "recentMessages": [ + { + "id": 67695, + "recipientId": 987, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/108/200/200", + "relationship": "동료", + "content": "현빈님의 메세지 내용 28", + "font": "Noto Sans", + "createdAt": "2023-06-19T07:08:12Z" + }, + { + "id": 78843, + "recipientId": 987, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/129/200/200", + "relationship": "동료", + "content": "이영준님의 메세지 내용 19", + "font": "Nanum Gothic", + "createdAt": "2023-09-22T16:14:47Z" + }, + { + "id": 1843, + "recipientId": 987, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/495/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 70", + "font": "Roboto", + "createdAt": "2023-07-04T06:42:44Z" + } + ], + "reactionCount": 72, + "topReactions": [ + { + "id": 76463, + "emoji": "😁", + "count": 15 + }, + { + "id": 25167, + "emoji": "🎉", + "count": 19 + }, + { + "id": 5479, + "emoji": "🥹", + "count": 2 + }, + { + "id": 92981, + "emoji": "😀", + "count": 17 + }, + { + "id": 85208, + "emoji": "😁", + "count": 10 + }, + { + "id": 61758, + "emoji": "👍", + "count": 8 + } + ] + }, + { + "id": 99277, + "name": "한지민", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-03-08T21:42:42Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 18287, + "recipientId": 99277, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/355/200/200", + "relationship": "지인", + "content": "전지현님의 메세지 내용 63", + "font": "Nanum Gothic", + "createdAt": "2023-02-21T08:53:40Z" + }, + { + "id": 40708, + "recipientId": 99277, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/255/200/200", + "relationship": "동료", + "content": "정우성님의 메세지 내용 48", + "font": "Noto Sans", + "createdAt": "2023-01-25T02:33:40Z" + }, + { + "id": 96884, + "recipientId": 99277, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/362/200/200", + "relationship": "가족", + "content": "정우성님의 메세지 내용 31", + "font": "Nanum Gothic", + "createdAt": "2024-02-01T10:45:29Z" + } + ], + "reactionCount": 70, + "topReactions": [ + { + "id": 11095, + "emoji": "😁", + "count": 1 + }, + { + "id": 76832, + "emoji": "👍", + "count": 1 + }, + { + "id": 65012, + "emoji": "🥹", + "count": 7 + }, + { + "id": 65074, + "emoji": "🎉", + "count": 2 + } + ] + }, + { + "id": 47918, + "name": "최민수", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2024-01-06T11:36:10Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 39350, + "recipientId": 47918, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/404/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 80", + "font": "Pretendard", + "createdAt": "2023-07-04T05:30:48Z" + }, + { + "id": 90854, + "recipientId": 47918, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/278/200/200", + "relationship": "동료", + "content": "최민수님의 메세지 내용 4", + "font": "Pretendard", + "createdAt": "2024-01-27T06:10:05Z" + }, + { + "id": 98946, + "recipientId": 47918, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/199/200/200", + "relationship": "지인", + "content": "김하은님의 메세지 내용 47", + "font": "Nanum Gothic", + "createdAt": "2023-08-20T22:18:43Z" + } + ], + "reactionCount": 34, + "topReactions": [ + { + "id": 17825, + "emoji": "🎉", + "count": 10 + }, + { + "id": 85431, + "emoji": "❤️", + "count": 1 + } + ] + }, + { + "id": 60144, + "name": "송혜교", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-03-27T21:09:40Z", + "messageCount": 3, + "recentMessages": [ + { + "id": 48501, + "recipientId": 60144, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/499/200/200", + "relationship": "지인", + "content": "박서준님의 메세지 내용 90", + "font": "Roboto", + "createdAt": "2023-08-30T23:42:40Z" + }, + { + "id": 32650, + "recipientId": 60144, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/196/200/200", + "relationship": "지인", + "content": "전지현님의 메세지 내용 16", + "font": "Roboto", + "createdAt": "2023-03-07T02:31:44Z" + }, + { + "id": 90329, + "recipientId": 60144, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/500/200/200", + "relationship": "친구", + "content": "김하은님의 메세지 내용 70", + "font": "Nanum Gothic", + "createdAt": "2023-11-02T05:53:11Z" + } + ], + "reactionCount": 4, + "topReactions": [ + { + "id": 50561, + "emoji": "❤️", + "count": 15 + }, + { + "id": 80082, + "emoji": "🎉", + "count": 18 + } + ] + }, + { + "id": 53261, + "name": "송혜교", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/53261/600/400", + "createdAt": "2023-03-11T22:52:07Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 16001, + "recipientId": 53261, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/161/200/200", + "relationship": "지인", + "content": "현빈님의 메세지 내용 31", + "font": "Pretendard", + "createdAt": "2023-03-14T11:20:15Z" + }, + { + "id": 67474, + "recipientId": 53261, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/221/200/200", + "relationship": "지인", + "content": "송혜교님의 메세지 내용 58", + "font": "Roboto", + "createdAt": "2023-09-04T17:56:53Z" + }, + { + "id": 88691, + "recipientId": 53261, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/197/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 49", + "font": "Pretendard", + "createdAt": "2023-07-18T12:09:53Z" + } + ], + "reactionCount": 41, + "topReactions": [ + { + "id": 26308, + "emoji": "🥹", + "count": 6 + }, + { + "id": 63793, + "emoji": "👍", + "count": 11 + }, + { + "id": 52541, + "emoji": "🎉", + "count": 4 + }, + { + "id": 83299, + "emoji": "😀", + "count": 9 + }, + { + "id": 85136, + "emoji": "🥹", + "count": 7 + }, + { + "id": 889, + "emoji": "👍", + "count": 7 + } + ] + }, + { + "id": 74042, + "name": "이영준", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/74042/600/400", + "createdAt": "2023-05-01T20:10:57Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 94808, + "recipientId": 74042, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/421/200/200", + "relationship": "지인", + "content": "김하은님의 메세지 내용 85", + "font": "Pretendard", + "createdAt": "2024-02-01T06:54:16Z" + }, + { + "id": 31960, + "recipientId": 74042, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/40/200/200", + "relationship": "동료", + "content": "최민수님의 메세지 내용 33", + "font": "Nanum Gothic", + "createdAt": "2023-02-21T23:07:24Z" + }, + { + "id": 19007, + "recipientId": 74042, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/445/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 44", + "font": "Nanum Gothic", + "createdAt": "2024-01-30T06:37:25Z" + } + ], + "reactionCount": 70, + "topReactions": [ + { + "id": 40083, + "emoji": "👍", + "count": 5 + }, + { + "id": 46868, + "emoji": "😀", + "count": 4 + }, + { + "id": 9028, + "emoji": "😀", + "count": 12 + }, + { + "id": 33264, + "emoji": "😁", + "count": 2 + }, + { + "id": 5936, + "emoji": "❤️", + "count": 13 + } + ] + }, + { + "id": 30047, + "name": "한지민", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/30047/600/400", + "createdAt": "2023-03-31T10:47:33Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 46241, + "recipientId": 30047, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/397/200/200", + "relationship": "동료", + "content": "이병헌님의 메세지 내용 64", + "font": "Roboto", + "createdAt": "2023-04-12T04:50:45Z" + }, + { + "id": 55605, + "recipientId": 30047, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/324/200/200", + "relationship": "가족", + "content": "전지현님의 메세지 내용 74", + "font": "Pretendard", + "createdAt": "2023-06-30T12:07:28Z" + }, + { + "id": 20989, + "recipientId": 30047, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/66/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 53", + "font": "Nanum Gothic", + "createdAt": "2023-05-09T11:38:40Z" + } + ], + "reactionCount": 55, + "topReactions": [ + { + "id": 35861, + "emoji": "👍", + "count": 20 + }, + { + "id": 3537, + "emoji": "🎉", + "count": 19 + }, + { + "id": 95822, + "emoji": "😀", + "count": 11 + }, + { + "id": 70453, + "emoji": "❤️", + "count": 10 + }, + { + "id": 12985, + "emoji": "🥹", + "count": 18 + }, + { + "id": 22095, + "emoji": "😀", + "count": 1 + } + ] + }, + { + "id": 96238, + "name": "송혜교", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-11-25T14:18:28Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 67172, + "recipientId": 96238, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/384/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 98", + "font": "Nanum Gothic", + "createdAt": "2023-12-23T18:55:16Z" + }, + { + "id": 14364, + "recipientId": 96238, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/113/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 47", + "font": "Noto Sans", + "createdAt": "2023-01-18T00:09:07Z" + }, + { + "id": 73112, + "recipientId": 96238, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/283/200/200", + "relationship": "친구", + "content": "김하은님의 메세지 내용 10", + "font": "Pretendard", + "createdAt": "2023-05-27T11:38:52Z" + } + ], + "reactionCount": 96, + "topReactions": [ + { + "id": 55075, + "emoji": "❤️", + "count": 3 + }, + { + "id": 35577, + "emoji": "🎉", + "count": 19 + } + ] + }, + { + "id": 69917, + "name": "현빈", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-09-07T23:34:46Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 9243, + "recipientId": 69917, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/239/200/200", + "relationship": "지인", + "content": "전지현님의 메세지 내용 60", + "font": "Pretendard", + "createdAt": "2023-12-28T01:45:57Z" + }, + { + "id": 98887, + "recipientId": 69917, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/215/200/200", + "relationship": "동료", + "content": "전지현님의 메세지 내용 91", + "font": "Pretendard", + "createdAt": "2023-11-11T18:02:57Z" + }, + { + "id": 75801, + "recipientId": 69917, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/395/200/200", + "relationship": "가족", + "content": "전지현님의 메세지 내용 48", + "font": "Pretendard", + "createdAt": "2023-08-09T15:37:56Z" + } + ], + "reactionCount": 43, + "topReactions": [ + { + "id": 5861, + "emoji": "🎉", + "count": 13 + }, + { + "id": 44343, + "emoji": "🥹", + "count": 12 + }, + { + "id": 43982, + "emoji": "🎉", + "count": 14 + }, + { + "id": 4963, + "emoji": "🎉", + "count": 6 + } + ] + }, + { + "id": 5650, + "name": "정우성", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/5650/600/400", + "createdAt": "2023-01-04T06:22:01Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 83293, + "recipientId": 5650, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/74/200/200", + "relationship": "동료", + "content": "전지현님의 메세지 내용 2", + "font": "Pretendard", + "createdAt": "2023-05-23T03:26:03Z" + } + ], + "reactionCount": 71, + "topReactions": [ + { + "id": 99348, + "emoji": "😁", + "count": 10 + }, + { + "id": 52447, + "emoji": "🎉", + "count": 19 + }, + { + "id": 16678, + "emoji": "😁", + "count": 1 + } + ] + }, + { + "id": 97770, + "name": "정우성", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-07-20T04:19:16Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 24717, + "recipientId": 97770, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/23/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 18", + "font": "Pretendard", + "createdAt": "2023-11-06T09:19:20Z" + }, + { + "id": 24145, + "recipientId": 97770, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/495/200/200", + "relationship": "지인", + "content": "이영준님의 메세지 내용 21", + "font": "Noto Sans", + "createdAt": "2023-10-18T14:16:27Z" + }, + { + "id": 223, + "recipientId": 97770, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/135/200/200", + "relationship": "지인", + "content": "정우성님의 메세지 내용 50", + "font": "Nanum Gothic", + "createdAt": "2024-01-26T11:24:46Z" + } + ], + "reactionCount": 32, + "topReactions": [ + { + "id": 20504, + "emoji": "🥹", + "count": 16 + }, + { + "id": 54171, + "emoji": "😁", + "count": 12 + }, + { + "id": 73446, + "emoji": "😁", + "count": 6 + }, + { + "id": 11616, + "emoji": "🎉", + "count": 7 + }, + { + "id": 95136, + "emoji": "🥹", + "count": 5 + } + ] + }, + { + "id": 4150, + "name": "전지현", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-02-04T22:57:07Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 72918, + "recipientId": 4150, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/397/200/200", + "relationship": "친구", + "content": "현빈님의 메세지 내용 33", + "font": "Noto Sans", + "createdAt": "2023-08-24T09:46:19Z" + }, + { + "id": 84168, + "recipientId": 4150, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/409/200/200", + "relationship": "동료", + "content": "이영준님의 메세지 내용 67", + "font": "Noto Sans", + "createdAt": "2023-05-15T01:03:21Z" + }, + { + "id": 71121, + "recipientId": 4150, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/333/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 81", + "font": "Noto Sans", + "createdAt": "2023-10-09T10:58:43Z" + } + ], + "reactionCount": 31, + "topReactions": [ + { + "id": 57710, + "emoji": "😀", + "count": 2 + }, + { + "id": 8909, + "emoji": "🥹", + "count": 2 + }, + { + "id": 28098, + "emoji": "🥹", + "count": 9 + } + ] + }, + { + "id": 44091, + "name": "이병헌", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/44091/600/400", + "createdAt": "2023-06-17T19:51:45Z", + "messageCount": 3, + "recentMessages": [ + { + "id": 90872, + "recipientId": 44091, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/432/200/200", + "relationship": "친구", + "content": "현빈님의 메세지 내용 71", + "font": "Noto Sans", + "createdAt": "2023-10-15T12:57:15Z" + }, + { + "id": 73008, + "recipientId": 44091, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/85/200/200", + "relationship": "가족", + "content": "현빈님의 메세지 내용 90", + "font": "Pretendard", + "createdAt": "2023-04-07T01:47:17Z" + }, + { + "id": 36229, + "recipientId": 44091, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/170/200/200", + "relationship": "동료", + "content": "이영준님의 메세지 내용 14", + "font": "Roboto", + "createdAt": "2023-04-30T21:52:02Z" + } + ], + "reactionCount": 73, + "topReactions": [ + { + "id": 53118, + "emoji": "😁", + "count": 1 + } + ] + }, + { + "id": 54206, + "name": "현빈", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/54206/600/400", + "createdAt": "2023-08-11T12:31:06Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 9945, + "recipientId": 54206, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/203/200/200", + "relationship": "가족", + "content": "김하은님의 메세지 내용 34", + "font": "Noto Sans", + "createdAt": "2023-02-22T00:16:51Z" + }, + { + "id": 35953, + "recipientId": 54206, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/13/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 42", + "font": "Pretendard", + "createdAt": "2023-03-14T13:18:54Z" + }, + { + "id": 28726, + "recipientId": 54206, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/95/200/200", + "relationship": "동료", + "content": "한지민님의 메세지 내용 42", + "font": "Pretendard", + "createdAt": "2023-03-03T06:17:34Z" + } + ], + "reactionCount": 70, + "topReactions": [ + { + "id": 60136, + "emoji": "😀", + "count": 7 + }, + { + "id": 45903, + "emoji": "🥹", + "count": 17 + }, + { + "id": 38212, + "emoji": "😀", + "count": 18 + }, + { + "id": 59414, + "emoji": "🥹", + "count": 5 + } + ] + }, + { + "id": 68370, + "name": "이영준", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-11-10T06:53:35Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 7950, + "recipientId": 68370, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/468/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 76", + "font": "Noto Sans", + "createdAt": "2023-05-28T16:55:31Z" + }, + { + "id": 41779, + "recipientId": 68370, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/495/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 66", + "font": "Roboto", + "createdAt": "2024-01-11T01:55:42Z" + }, + { + "id": 18889, + "recipientId": 68370, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/208/200/200", + "relationship": "가족", + "content": "한지민님의 메세지 내용 9", + "font": "Pretendard", + "createdAt": "2023-06-23T17:19:26Z" + } + ], + "reactionCount": 9, + "topReactions": [ + { + "id": 19392, + "emoji": "😁", + "count": 18 + }, + { + "id": 13700, + "emoji": "❤️", + "count": 12 + }, + { + "id": 50701, + "emoji": "😁", + "count": 6 + }, + { + "id": 28314, + "emoji": "❤️", + "count": 15 + }, + { + "id": 65318, + "emoji": "🥹", + "count": 19 + } + ] + }, + { + "id": 76323, + "name": "이영준", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-06-11T11:07:28Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 76226, + "recipientId": 76323, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/180/200/200", + "relationship": "지인", + "content": "한지민님의 메세지 내용 11", + "font": "Roboto", + "createdAt": "2023-11-14T15:14:43Z" + }, + { + "id": 18283, + "recipientId": 76323, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/269/200/200", + "relationship": "가족", + "content": "이영준님의 메세지 내용 42", + "font": "Noto Sans", + "createdAt": "2023-11-18T21:30:13Z" + }, + { + "id": 69571, + "recipientId": 76323, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/382/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 73", + "font": "Roboto", + "createdAt": "2023-08-26T00:28:35Z" + } + ], + "reactionCount": 43, + "topReactions": [ + { + "id": 38169, + "emoji": "🥹", + "count": 6 + } + ] + }, + { + "id": 84073, + "name": "박서준", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-06-30T13:11:38Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 19945, + "recipientId": 84073, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/32/200/200", + "relationship": "지인", + "content": "전지현님의 메세지 내용 56", + "font": "Roboto", + "createdAt": "2023-10-19T03:38:48Z" + } + ], + "reactionCount": 36, + "topReactions": [ + { + "id": 51242, + "emoji": "👍", + "count": 3 + }, + { + "id": 23565, + "emoji": "❤️", + "count": 8 + }, + { + "id": 37031, + "emoji": "🥹", + "count": 17 + }, + { + "id": 78779, + "emoji": "❤️", + "count": 9 + } + ] + }, + { + "id": 14176, + "name": "송혜교", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/14176/600/400", + "createdAt": "2023-07-14T11:33:05Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 80228, + "recipientId": 14176, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/221/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 44", + "font": "Nanum Gothic", + "createdAt": "2023-11-19T19:29:11Z" + }, + { + "id": 37, + "recipientId": 14176, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/289/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 69", + "font": "Pretendard", + "createdAt": "2023-05-30T17:54:20Z" + }, + { + "id": 63293, + "recipientId": 14176, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/438/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 27", + "font": "Pretendard", + "createdAt": "2024-01-28T13:46:13Z" + } + ], + "reactionCount": 31, + "topReactions": [ + { + "id": 50319, + "emoji": "😁", + "count": 20 + }, + { + "id": 44923, + "emoji": "🥹", + "count": 16 + }, + { + "id": 54729, + "emoji": "👍", + "count": 1 + }, + { + "id": 82072, + "emoji": "🎉", + "count": 11 + }, + { + "id": 10911, + "emoji": "😁", + "count": 2 + } + ] + }, + { + "id": 63278, + "name": "전지현", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/63278/600/400", + "createdAt": "2023-09-08T13:46:48Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 5278, + "recipientId": 63278, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/59/200/200", + "relationship": "친구", + "content": "김하은님의 메세지 내용 53", + "font": "Noto Sans", + "createdAt": "2023-06-01T20:26:14Z" + }, + { + "id": 26283, + "recipientId": 63278, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/460/200/200", + "relationship": "지인", + "content": "송혜교님의 메세지 내용 41", + "font": "Pretendard", + "createdAt": "2023-09-26T17:49:04Z" + }, + { + "id": 74629, + "recipientId": 63278, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/241/200/200", + "relationship": "친구", + "content": "전지현님의 메세지 내용 13", + "font": "Roboto", + "createdAt": "2023-10-28T13:39:12Z" + } + ], + "reactionCount": 48, + "topReactions": [ + { + "id": 55639, + "emoji": "😁", + "count": 2 + }, + { + "id": 98809, + "emoji": "❤️", + "count": 2 + }, + { + "id": 69046, + "emoji": "👍", + "count": 2 + } + ] + }, + { + "id": 35291, + "name": "이영준", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2024-01-23T21:03:45Z", + "messageCount": 3, + "recentMessages": [ + { + "id": 54804, + "recipientId": 35291, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/373/200/200", + "relationship": "가족", + "content": "현빈님의 메세지 내용 8", + "font": "Noto Sans", + "createdAt": "2023-04-14T15:39:03Z" + }, + { + "id": 20544, + "recipientId": 35291, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/296/200/200", + "relationship": "가족", + "content": "현빈님의 메세지 내용 9", + "font": "Noto Sans", + "createdAt": "2023-11-15T13:00:19Z" + }, + { + "id": 30666, + "recipientId": 35291, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/399/200/200", + "relationship": "친구", + "content": "송혜교님의 메세지 내용 88", + "font": "Noto Sans", + "createdAt": "2023-12-23T00:45:32Z" + } + ], + "reactionCount": 100, + "topReactions": [ + { + "id": 4687, + "emoji": "❤️", + "count": 9 + } + ] + }, + { + "id": 3038, + "name": "현빈", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/3038/600/400", + "createdAt": "2023-06-27T03:39:55Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 95652, + "recipientId": 3038, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/450/200/200", + "relationship": "가족", + "content": "김하은님의 메세지 내용 45", + "font": "Roboto", + "createdAt": "2023-02-19T01:18:56Z" + }, + { + "id": 52296, + "recipientId": 3038, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/131/200/200", + "relationship": "가족", + "content": "현빈님의 메세지 내용 41", + "font": "Noto Sans", + "createdAt": "2023-07-15T18:02:58Z" + }, + { + "id": 55396, + "recipientId": 3038, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/146/200/200", + "relationship": "친구", + "content": "송혜교님의 메세지 내용 58", + "font": "Nanum Gothic", + "createdAt": "2023-03-26T23:08:07Z" + } + ], + "reactionCount": 54, + "topReactions": [ + { + "id": 5609, + "emoji": "🎉", + "count": 3 + }, + { + "id": 93922, + "emoji": "😁", + "count": 19 + } + ] + }, + { + "id": 62965, + "name": "한지민", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-01-16T23:39:19Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 10114, + "recipientId": 62965, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/281/200/200", + "relationship": "가족", + "content": "전지현님의 메세지 내용 40", + "font": "Nanum Gothic", + "createdAt": "2023-09-27T11:32:49Z" + }, + { + "id": 58525, + "recipientId": 62965, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/103/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 1", + "font": "Noto Sans", + "createdAt": "2023-04-24T14:22:46Z" + }, + { + "id": 20887, + "recipientId": 62965, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/318/200/200", + "relationship": "가족", + "content": "이영준님의 메세지 내용 36", + "font": "Pretendard", + "createdAt": "2023-05-07T12:50:11Z" + } + ], + "reactionCount": 74, + "topReactions": [ + { + "id": 29181, + "emoji": "😁", + "count": 2 + } + ] + }, + { + "id": 61614, + "name": "송혜교", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2024-01-27T06:28:36Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 86114, + "recipientId": 61614, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/1/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 48", + "font": "Noto Sans", + "createdAt": "2023-11-16T04:24:55Z" + }, + { + "id": 12648, + "recipientId": 61614, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/291/200/200", + "relationship": "가족", + "content": "전지현님의 메세지 내용 14", + "font": "Nanum Gothic", + "createdAt": "2023-05-26T04:21:47Z" + }, + { + "id": 36957, + "recipientId": 61614, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/356/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 26", + "font": "Pretendard", + "createdAt": "2023-02-09T04:44:09Z" + } + ], + "reactionCount": 43, + "topReactions": [ + { + "id": 96270, + "emoji": "😁", + "count": 8 + }, + { + "id": 86470, + "emoji": "👍", + "count": 20 + }, + { + "id": 73582, + "emoji": "😁", + "count": 18 + } + ] + }, + { + "id": 69902, + "name": "송혜교", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/69902/600/400", + "createdAt": "2024-01-18T11:46:07Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 9049, + "recipientId": 69902, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/185/200/200", + "relationship": "동료", + "content": "전지현님의 메세지 내용 57", + "font": "Nanum Gothic", + "createdAt": "2023-09-26T03:46:33Z" + }, + { + "id": 54860, + "recipientId": 69902, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/322/200/200", + "relationship": "친구", + "content": "김하은님의 메세지 내용 46", + "font": "Pretendard", + "createdAt": "2023-03-14T16:52:38Z" + }, + { + "id": 46217, + "recipientId": 69902, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/307/200/200", + "relationship": "가족", + "content": "박서준님의 메세지 내용 89", + "font": "Roboto", + "createdAt": "2023-12-09T06:45:19Z" + } + ], + "reactionCount": 59, + "topReactions": [ + { + "id": 10874, + "emoji": "❤️", + "count": 20 + }, + { + "id": 9648, + "emoji": "🥹", + "count": 8 + }, + { + "id": 90543, + "emoji": "👍", + "count": 3 + } + ] + }, + { + "id": 31146, + "name": "이병헌", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-09-27T13:42:38Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 55285, + "recipientId": 31146, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/175/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 1", + "font": "Pretendard", + "createdAt": "2024-01-20T10:25:39Z" + } + ], + "reactionCount": 88, + "topReactions": [ + { + "id": 90630, + "emoji": "🥹", + "count": 8 + }, + { + "id": 31427, + "emoji": "🎉", + "count": 13 + }, + { + "id": 40617, + "emoji": "🎉", + "count": 19 + }, + { + "id": 21215, + "emoji": "🎉", + "count": 1 + }, + { + "id": 10418, + "emoji": "😀", + "count": 10 + } + ] + }, + { + "id": 99123, + "name": "김하은", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-06-15T07:28:57Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 80875, + "recipientId": 99123, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/42/200/200", + "relationship": "동료", + "content": "이병헌님의 메세지 내용 14", + "font": "Roboto", + "createdAt": "2023-11-30T19:44:40Z" + }, + { + "id": 55841, + "recipientId": 99123, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/377/200/200", + "relationship": "지인", + "content": "한지민님의 메세지 내용 80", + "font": "Roboto", + "createdAt": "2023-10-22T05:25:33Z" + }, + { + "id": 10401, + "recipientId": 99123, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/289/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 29", + "font": "Roboto", + "createdAt": "2023-04-03T21:19:09Z" + } + ], + "reactionCount": 80, + "topReactions": [ + { + "id": 24281, + "emoji": "😁", + "count": 12 + }, + { + "id": 56612, + "emoji": "❤️", + "count": 8 + } + ] + }, + { + "id": 23460, + "name": "전지현", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/23460/600/400", + "createdAt": "2023-11-01T19:37:56Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 6131, + "recipientId": 23460, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/223/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 60", + "font": "Nanum Gothic", + "createdAt": "2023-06-21T09:22:34Z" + }, + { + "id": 99333, + "recipientId": 23460, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/43/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 100", + "font": "Pretendard", + "createdAt": "2023-10-17T20:43:17Z" + }, + { + "id": 15452, + "recipientId": 23460, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/357/200/200", + "relationship": "가족", + "content": "전지현님의 메세지 내용 72", + "font": "Pretendard", + "createdAt": "2023-10-12T19:29:28Z" + } + ], + "reactionCount": 83, + "topReactions": [ + { + "id": 41395, + "emoji": "❤️", + "count": 3 + }, + { + "id": 71463, + "emoji": "😁", + "count": 14 + }, + { + "id": 43684, + "emoji": "🎉", + "count": 20 + } + ] + }, + { + "id": 16143, + "name": "박서준", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/16143/600/400", + "createdAt": "2023-01-04T22:33:04Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 29397, + "recipientId": 16143, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/42/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 18", + "font": "Pretendard", + "createdAt": "2023-10-28T19:38:42Z" + }, + { + "id": 61587, + "recipientId": 16143, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/355/200/200", + "relationship": "가족", + "content": "정우성님의 메세지 내용 12", + "font": "Noto Sans", + "createdAt": "2023-10-08T06:13:32Z" + }, + { + "id": 9237, + "recipientId": 16143, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/437/200/200", + "relationship": "지인", + "content": "이병헌님의 메세지 내용 14", + "font": "Pretendard", + "createdAt": "2023-03-17T21:44:08Z" + } + ], + "reactionCount": 77, + "topReactions": [ + { + "id": 18467, + "emoji": "👍", + "count": 17 + }, + { + "id": 28382, + "emoji": "😀", + "count": 1 + }, + { + "id": 94572, + "emoji": "❤️", + "count": 1 + }, + { + "id": 63127, + "emoji": "🥹", + "count": 16 + } + ] + }, + { + "id": 68350, + "name": "송혜교", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/68350/600/400", + "createdAt": "2023-03-04T17:34:20Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 34771, + "recipientId": 68350, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/133/200/200", + "relationship": "가족", + "content": "정우성님의 메세지 내용 74", + "font": "Roboto", + "createdAt": "2023-08-04T20:53:43Z" + }, + { + "id": 3254, + "recipientId": 68350, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/10/200/200", + "relationship": "가족", + "content": "한지민님의 메세지 내용 14", + "font": "Nanum Gothic", + "createdAt": "2023-10-10T20:43:09Z" + }, + { + "id": 57267, + "recipientId": 68350, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/183/200/200", + "relationship": "지인", + "content": "송혜교님의 메세지 내용 82", + "font": "Nanum Gothic", + "createdAt": "2023-02-14T21:40:55Z" + } + ], + "reactionCount": 61, + "topReactions": [ + { + "id": 99369, + "emoji": "👍", + "count": 6 + } + ] + }, + { + "id": 98422, + "name": "한지민", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-07-31T00:35:56Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 25200, + "recipientId": 98422, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/380/200/200", + "relationship": "지인", + "content": "현빈님의 메세지 내용 46", + "font": "Nanum Gothic", + "createdAt": "2023-02-10T09:22:21Z" + }, + { + "id": 12390, + "recipientId": 98422, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/70/200/200", + "relationship": "지인", + "content": "김하은님의 메세지 내용 31", + "font": "Noto Sans", + "createdAt": "2023-03-27T15:05:54Z" + }, + { + "id": 31892, + "recipientId": 98422, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/8/200/200", + "relationship": "지인", + "content": "이병헌님의 메세지 내용 43", + "font": "Pretendard", + "createdAt": "2023-09-02T03:23:20Z" + } + ], + "reactionCount": 6, + "topReactions": [ + { + "id": 99679, + "emoji": "👍", + "count": 1 + }, + { + "id": 42127, + "emoji": "👍", + "count": 20 + }, + { + "id": 49549, + "emoji": "😀", + "count": 5 + } + ] + }, + { + "id": 53532, + "name": "이영준", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-12-08T09:44:53Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 33230, + "recipientId": 53532, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/231/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 27", + "font": "Pretendard", + "createdAt": "2023-12-05T13:46:34Z" + }, + { + "id": 85445, + "recipientId": 53532, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/363/200/200", + "relationship": "지인", + "content": "이병헌님의 메세지 내용 51", + "font": "Noto Sans", + "createdAt": "2023-09-23T11:29:56Z" + }, + { + "id": 5528, + "recipientId": 53532, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/376/200/200", + "relationship": "가족", + "content": "김하은님의 메세지 내용 72", + "font": "Pretendard", + "createdAt": "2023-05-22T16:07:40Z" + } + ], + "reactionCount": 59, + "topReactions": [ + { + "id": 23496, + "emoji": "❤️", + "count": 18 + }, + { + "id": 81866, + "emoji": "👍", + "count": 10 + }, + { + "id": 17757, + "emoji": "🥹", + "count": 10 + }, + { + "id": 39750, + "emoji": "🥹", + "count": 16 + }, + { + "id": 24933, + "emoji": "😁", + "count": 12 + }, + { + "id": 26409, + "emoji": "❤️", + "count": 19 + } + ] + }, + { + "id": 93792, + "name": "김하은", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-10-03T23:01:03Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 86518, + "recipientId": 93792, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/204/200/200", + "relationship": "지인", + "content": "이병헌님의 메세지 내용 9", + "font": "Roboto", + "createdAt": "2023-01-22T13:44:09Z" + }, + { + "id": 99933, + "recipientId": 93792, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/36/200/200", + "relationship": "친구", + "content": "박서준님의 메세지 내용 47", + "font": "Roboto", + "createdAt": "2023-12-15T23:06:01Z" + }, + { + "id": 9752, + "recipientId": 93792, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/171/200/200", + "relationship": "동료", + "content": "이병헌님의 메세지 내용 68", + "font": "Roboto", + "createdAt": "2023-02-15T23:39:35Z" + } + ], + "reactionCount": 52, + "topReactions": [ + { + "id": 4867, + "emoji": "❤️", + "count": 19 + }, + { + "id": 39233, + "emoji": "🥹", + "count": 20 + }, + { + "id": 20026, + "emoji": "❤️", + "count": 19 + }, + { + "id": 72595, + "emoji": "👍", + "count": 13 + }, + { + "id": 13775, + "emoji": "🥹", + "count": 17 + } + ] + }, + { + "id": 12242, + "name": "송혜교", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-08-08T18:28:39Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 60783, + "recipientId": 12242, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/367/200/200", + "relationship": "친구", + "content": "박서준님의 메세지 내용 41", + "font": "Roboto", + "createdAt": "2023-08-22T03:44:05Z" + }, + { + "id": 10949, + "recipientId": 12242, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/309/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 18", + "font": "Roboto", + "createdAt": "2023-04-22T04:41:36Z" + }, + { + "id": 84648, + "recipientId": 12242, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/112/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 4", + "font": "Pretendard", + "createdAt": "2024-01-06T11:37:10Z" + } + ], + "reactionCount": 61, + "topReactions": [ + { + "id": 84557, + "emoji": "😀", + "count": 20 + }, + { + "id": 77673, + "emoji": "😀", + "count": 12 + }, + { + "id": 99493, + "emoji": "❤️", + "count": 13 + }, + { + "id": 67646, + "emoji": "🥹", + "count": 4 + }, + { + "id": 54419, + "emoji": "❤️", + "count": 12 + }, + { + "id": 2038, + "emoji": "🎉", + "count": 1 + } + ] + }, + { + "id": 89238, + "name": "현빈", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-07-30T22:16:57Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 80184, + "recipientId": 89238, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/280/200/200", + "relationship": "친구", + "content": "이영준님의 메세지 내용 79", + "font": "Pretendard", + "createdAt": "2023-08-21T11:18:34Z" + }, + { + "id": 47050, + "recipientId": 89238, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/484/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 55", + "font": "Nanum Gothic", + "createdAt": "2023-11-26T01:02:24Z" + } + ], + "reactionCount": 31, + "topReactions": [ + { + "id": 72384, + "emoji": "🎉", + "count": 10 + }, + { + "id": 24751, + "emoji": "👍", + "count": 2 + } + ] + }, + { + "id": 76148, + "name": "김하은", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/76148/600/400", + "createdAt": "2023-09-05T06:37:33Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 6882, + "recipientId": 76148, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/124/200/200", + "relationship": "지인", + "content": "송혜교님의 메세지 내용 35", + "font": "Noto Sans", + "createdAt": "2024-01-24T04:11:44Z" + }, + { + "id": 35816, + "recipientId": 76148, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/488/200/200", + "relationship": "가족", + "content": "이병헌님의 메세지 내용 96", + "font": "Nanum Gothic", + "createdAt": "2023-04-09T14:21:56Z" + } + ], + "reactionCount": 3, + "topReactions": [ + { + "id": 24742, + "emoji": "🥹", + "count": 11 + }, + { + "id": 31827, + "emoji": "👍", + "count": 6 + }, + { + "id": 12947, + "emoji": "🎉", + "count": 5 + }, + { + "id": 40799, + "emoji": "🎉", + "count": 3 + } + ] + }, + { + "id": 30844, + "name": "한지민", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/30844/600/400", + "createdAt": "2023-10-28T15:58:37Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 80665, + "recipientId": 30844, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/114/200/200", + "relationship": "지인", + "content": "이영준님의 메세지 내용 46", + "font": "Pretendard", + "createdAt": "2024-01-04T21:06:58Z" + }, + { + "id": 51843, + "recipientId": 30844, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/494/200/200", + "relationship": "친구", + "content": "이영준님의 메세지 내용 47", + "font": "Noto Sans", + "createdAt": "2023-03-25T15:03:22Z" + } + ], + "reactionCount": 50, + "topReactions": [ + { + "id": 99751, + "emoji": "❤️", + "count": 16 + } + ] + }, + { + "id": 38642, + "name": "정우성", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/38642/600/400", + "createdAt": "2023-12-23T15:10:53Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 76780, + "recipientId": 38642, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/253/200/200", + "relationship": "가족", + "content": "이병헌님의 메세지 내용 24", + "font": "Nanum Gothic", + "createdAt": "2023-07-12T11:54:03Z" + }, + { + "id": 97730, + "recipientId": 38642, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/24/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 89", + "font": "Nanum Gothic", + "createdAt": "2023-01-10T18:45:35Z" + }, + { + "id": 64400, + "recipientId": 38642, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/47/200/200", + "relationship": "가족", + "content": "박서준님의 메세지 내용 21", + "font": "Roboto", + "createdAt": "2023-04-13T02:41:12Z" + } + ], + "reactionCount": 29, + "topReactions": [ + { + "id": 96587, + "emoji": "😁", + "count": 16 + }, + { + "id": 33006, + "emoji": "🎉", + "count": 8 + }, + { + "id": 4665, + "emoji": "🎉", + "count": 3 + }, + { + "id": 6761, + "emoji": "😀", + "count": 7 + } + ] + }, + { + "id": 19180, + "name": "한지민", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-03-17T02:54:43Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 99404, + "recipientId": 19180, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/72/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 34", + "font": "Noto Sans", + "createdAt": "2023-12-31T06:59:44Z" + }, + { + "id": 40694, + "recipientId": 19180, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/466/200/200", + "relationship": "동료", + "content": "이영준님의 메세지 내용 85", + "font": "Nanum Gothic", + "createdAt": "2023-05-15T12:04:48Z" + } + ], + "reactionCount": 29, + "topReactions": [ + { + "id": 85255, + "emoji": "😀", + "count": 10 + } + ] + }, + { + "id": 56954, + "name": "이영준", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-07-08T16:30:01Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 77321, + "recipientId": 56954, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/486/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 71", + "font": "Pretendard", + "createdAt": "2024-01-10T14:52:33Z" + }, + { + "id": 48997, + "recipientId": 56954, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/128/200/200", + "relationship": "친구", + "content": "현빈님의 메세지 내용 8", + "font": "Pretendard", + "createdAt": "2023-10-26T08:26:46Z" + }, + { + "id": 39251, + "recipientId": 56954, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/491/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 63", + "font": "Roboto", + "createdAt": "2023-06-07T05:35:20Z" + } + ], + "reactionCount": 15, + "topReactions": [ + { + "id": 93584, + "emoji": "🥹", + "count": 17 + }, + { + "id": 64509, + "emoji": "🥹", + "count": 7 + }, + { + "id": 26383, + "emoji": "❤️", + "count": 11 + }, + { + "id": 18223, + "emoji": "🥹", + "count": 6 + } + ] + }, + { + "id": 69809, + "name": "김하은", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/69809/600/400", + "createdAt": "2023-12-17T10:40:55Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 99531, + "recipientId": 69809, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/454/200/200", + "relationship": "지인", + "content": "이영준님의 메세지 내용 11", + "font": "Pretendard", + "createdAt": "2023-12-21T11:49:22Z" + }, + { + "id": 50525, + "recipientId": 69809, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/426/200/200", + "relationship": "지인", + "content": "박서준님의 메세지 내용 67", + "font": "Pretendard", + "createdAt": "2023-10-31T11:25:46Z" + } + ], + "reactionCount": 91, + "topReactions": [ + { + "id": 12819, + "emoji": "🎉", + "count": 16 + }, + { + "id": 51793, + "emoji": "❤️", + "count": 8 + }, + { + "id": 47344, + "emoji": "❤️", + "count": 9 + } + ] + }, + { + "id": 55884, + "name": "전지현", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/55884/600/400", + "createdAt": "2023-05-07T09:10:12Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 78207, + "recipientId": 55884, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/155/200/200", + "relationship": "지인", + "content": "이병헌님의 메세지 내용 87", + "font": "Pretendard", + "createdAt": "2023-06-01T07:21:37Z" + }, + { + "id": 52755, + "recipientId": 55884, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/148/200/200", + "relationship": "친구", + "content": "최민수님의 메세지 내용 76", + "font": "Pretendard", + "createdAt": "2023-11-02T00:07:24Z" + }, + { + "id": 96898, + "recipientId": 55884, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/468/200/200", + "relationship": "동료", + "content": "전지현님의 메세지 내용 21", + "font": "Nanum Gothic", + "createdAt": "2023-02-17T02:04:29Z" + } + ], + "reactionCount": 53, + "topReactions": [ + { + "id": 48355, + "emoji": "👍", + "count": 6 + }, + { + "id": 38418, + "emoji": "👍", + "count": 13 + }, + { + "id": 7995, + "emoji": "😀", + "count": 20 + }, + { + "id": 55879, + "emoji": "🥹", + "count": 5 + } + ] + }, + { + "id": 65809, + "name": "최민수", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-01-13T12:44:51Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 2300, + "recipientId": 65809, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/358/200/200", + "relationship": "지인", + "content": "이병헌님의 메세지 내용 60", + "font": "Roboto", + "createdAt": "2023-05-12T09:25:19Z" + }, + { + "id": 77937, + "recipientId": 65809, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/415/200/200", + "relationship": "지인", + "content": "정우성님의 메세지 내용 31", + "font": "Pretendard", + "createdAt": "2023-01-20T00:38:18Z" + }, + { + "id": 23083, + "recipientId": 65809, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/239/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 30", + "font": "Nanum Gothic", + "createdAt": "2023-01-16T00:10:43Z" + } + ], + "reactionCount": 93, + "topReactions": [ + { + "id": 51783, + "emoji": "🎉", + "count": 10 + }, + { + "id": 37523, + "emoji": "❤️", + "count": 19 + }, + { + "id": 58371, + "emoji": "😁", + "count": 16 + }, + { + "id": 83933, + "emoji": "😀", + "count": 10 + }, + { + "id": 67432, + "emoji": "❤️", + "count": 17 + }, + { + "id": 37226, + "emoji": "😀", + "count": 15 + } + ] + }, + { + "id": 47549, + "name": "김하은", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-11-16T19:12:33Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 12155, + "recipientId": 47549, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/247/200/200", + "relationship": "지인", + "content": "이병헌님의 메세지 내용 80", + "font": "Pretendard", + "createdAt": "2023-03-09T22:19:14Z" + }, + { + "id": 97085, + "recipientId": 47549, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/468/200/200", + "relationship": "친구", + "content": "이영준님의 메세지 내용 24", + "font": "Pretendard", + "createdAt": "2023-05-15T13:22:05Z" + }, + { + "id": 38570, + "recipientId": 47549, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/485/200/200", + "relationship": "동료", + "content": "이영준님의 메세지 내용 42", + "font": "Nanum Gothic", + "createdAt": "2024-01-05T09:02:07Z" + } + ], + "reactionCount": 73, + "topReactions": [ + { + "id": 6824, + "emoji": "🎉", + "count": 1 + }, + { + "id": 77828, + "emoji": "😀", + "count": 14 + }, + { + "id": 10712, + "emoji": "🥹", + "count": 8 + }, + { + "id": 14431, + "emoji": "❤️", + "count": 5 + }, + { + "id": 41886, + "emoji": "🎉", + "count": 15 + }, + { + "id": 38043, + "emoji": "❤️", + "count": 7 + } + ] + }, + { + "id": 7135, + "name": "이영준", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/7135/600/400", + "createdAt": "2024-02-02T00:26:07Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 77121, + "recipientId": 7135, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/494/200/200", + "relationship": "지인", + "content": "정우성님의 메세지 내용 47", + "font": "Nanum Gothic", + "createdAt": "2023-12-03T15:32:07Z" + }, + { + "id": 38873, + "recipientId": 7135, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/166/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 52", + "font": "Nanum Gothic", + "createdAt": "2023-12-30T01:58:20Z" + }, + { + "id": 64811, + "recipientId": 7135, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/184/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 9", + "font": "Roboto", + "createdAt": "2023-10-17T00:36:13Z" + } + ], + "reactionCount": 80, + "topReactions": [ + { + "id": 73068, + "emoji": "😁", + "count": 14 + } + ] + }, + { + "id": 83536, + "name": "이영준", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2024-02-02T17:56:51Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 76208, + "recipientId": 83536, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/12/200/200", + "relationship": "동료", + "content": "최민수님의 메세지 내용 1", + "font": "Noto Sans", + "createdAt": "2023-11-26T03:41:54Z" + }, + { + "id": 43421, + "recipientId": 83536, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/66/200/200", + "relationship": "가족", + "content": "정우성님의 메세지 내용 99", + "font": "Roboto", + "createdAt": "2023-01-23T15:07:50Z" + }, + { + "id": 78732, + "recipientId": 83536, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/385/200/200", + "relationship": "동료", + "content": "전지현님의 메세지 내용 41", + "font": "Pretendard", + "createdAt": "2023-08-24T20:58:06Z" + } + ], + "reactionCount": 0, + "topReactions": [ + { + "id": 64631, + "emoji": "❤️", + "count": 7 + }, + { + "id": 15818, + "emoji": "❤️", + "count": 6 + }, + { + "id": 96523, + "emoji": "❤️", + "count": 3 + }, + { + "id": 87388, + "emoji": "🎉", + "count": 19 + }, + { + "id": 64648, + "emoji": "👍", + "count": 4 + } + ] + }, + { + "id": 61585, + "name": "한지민", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/61585/600/400", + "createdAt": "2023-11-08T05:35:02Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 27357, + "recipientId": 61585, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/165/200/200", + "relationship": "가족", + "content": "정우성님의 메세지 내용 31", + "font": "Pretendard", + "createdAt": "2023-09-11T11:00:09Z" + }, + { + "id": 67752, + "recipientId": 61585, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/316/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 77", + "font": "Pretendard", + "createdAt": "2023-10-11T21:08:05Z" + }, + { + "id": 39794, + "recipientId": 61585, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/247/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 9", + "font": "Roboto", + "createdAt": "2023-06-17T12:32:47Z" + } + ], + "reactionCount": 54, + "topReactions": [ + { + "id": 38019, + "emoji": "😀", + "count": 5 + }, + { + "id": 97709, + "emoji": "😁", + "count": 17 + }, + { + "id": 46872, + "emoji": "👍", + "count": 1 + } + ] + }, + { + "id": 4404, + "name": "전지현", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/4404/600/400", + "createdAt": "2023-12-06T02:26:16Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 6292, + "recipientId": 4404, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/252/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 51", + "font": "Noto Sans", + "createdAt": "2023-01-23T16:41:53Z" + }, + { + "id": 61157, + "recipientId": 4404, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/109/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 95", + "font": "Roboto", + "createdAt": "2023-02-23T01:59:59Z" + }, + { + "id": 82143, + "recipientId": 4404, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/156/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 45", + "font": "Roboto", + "createdAt": "2023-11-05T04:40:09Z" + } + ], + "reactionCount": 2, + "topReactions": [ + { + "id": 10319, + "emoji": "🥹", + "count": 19 + }, + { + "id": 88672, + "emoji": "🎉", + "count": 18 + } + ] + }, + { + "id": 82511, + "name": "최민수", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-03-20T04:58:27Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 26463, + "recipientId": 82511, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/71/200/200", + "relationship": "지인", + "content": "이영준님의 메세지 내용 76", + "font": "Pretendard", + "createdAt": "2023-12-01T01:16:39Z" + }, + { + "id": 2416, + "recipientId": 82511, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/268/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 24", + "font": "Noto Sans", + "createdAt": "2024-01-04T09:08:19Z" + }, + { + "id": 50351, + "recipientId": 82511, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/389/200/200", + "relationship": "가족", + "content": "전지현님의 메세지 내용 9", + "font": "Nanum Gothic", + "createdAt": "2023-03-28T23:52:37Z" + } + ], + "reactionCount": 56, + "topReactions": [ + { + "id": 82148, + "emoji": "😀", + "count": 5 + }, + { + "id": 99162, + "emoji": "😀", + "count": 20 + }, + { + "id": 60338, + "emoji": "🎉", + "count": 20 + }, + { + "id": 99668, + "emoji": "👍", + "count": 10 + } + ] + }, + { + "id": 80845, + "name": "현빈", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/80845/600/400", + "createdAt": "2023-09-23T05:25:24Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 59713, + "recipientId": 80845, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/85/200/200", + "relationship": "지인", + "content": "현빈님의 메세지 내용 90", + "font": "Noto Sans", + "createdAt": "2023-07-28T08:33:36Z" + }, + { + "id": 74833, + "recipientId": 80845, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/497/200/200", + "relationship": "동료", + "content": "정우성님의 메세지 내용 82", + "font": "Noto Sans", + "createdAt": "2024-01-15T11:55:15Z" + }, + { + "id": 44164, + "recipientId": 80845, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/135/200/200", + "relationship": "동료", + "content": "최민수님의 메세지 내용 40", + "font": "Nanum Gothic", + "createdAt": "2023-09-13T20:47:57Z" + } + ], + "reactionCount": 4, + "topReactions": [ + { + "id": 2410, + "emoji": "👍", + "count": 7 + }, + { + "id": 46152, + "emoji": "😀", + "count": 4 + }, + { + "id": 98175, + "emoji": "🎉", + "count": 1 + } + ] + }, + { + "id": 11012, + "name": "최민수", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/11012/600/400", + "createdAt": "2023-09-24T11:28:28Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 4989, + "recipientId": 11012, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/380/200/200", + "relationship": "동료", + "content": "현빈님의 메세지 내용 51", + "font": "Pretendard", + "createdAt": "2023-01-09T06:31:52Z" + }, + { + "id": 49460, + "recipientId": 11012, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/87/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 7", + "font": "Noto Sans", + "createdAt": "2023-11-01T20:42:58Z" + }, + { + "id": 33477, + "recipientId": 11012, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/499/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 100", + "font": "Nanum Gothic", + "createdAt": "2023-12-19T22:24:58Z" + } + ], + "reactionCount": 24, + "topReactions": [ + { + "id": 8056, + "emoji": "🥹", + "count": 17 + }, + { + "id": 73087, + "emoji": "❤️", + "count": 2 + } + ] + }, + { + "id": 6792, + "name": "송혜교", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-11-20T08:02:43Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 30090, + "recipientId": 6792, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/140/200/200", + "relationship": "지인", + "content": "송혜교님의 메세지 내용 5", + "font": "Roboto", + "createdAt": "2023-01-30T10:59:51Z" + }, + { + "id": 55978, + "recipientId": 6792, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/461/200/200", + "relationship": "지인", + "content": "전지현님의 메세지 내용 59", + "font": "Nanum Gothic", + "createdAt": "2023-10-23T19:12:56Z" + } + ], + "reactionCount": 31, + "topReactions": [ + { + "id": 58447, + "emoji": "😁", + "count": 18 + } + ] + }, + { + "id": 34708, + "name": "송혜교", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/34708/600/400", + "createdAt": "2023-02-10T16:28:04Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 6194, + "recipientId": 34708, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/317/200/200", + "relationship": "지인", + "content": "전지현님의 메세지 내용 47", + "font": "Pretendard", + "createdAt": "2023-06-08T17:46:33Z" + }, + { + "id": 25345, + "recipientId": 34708, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/457/200/200", + "relationship": "동료", + "content": "정우성님의 메세지 내용 87", + "font": "Nanum Gothic", + "createdAt": "2023-02-18T22:02:01Z" + }, + { + "id": 84170, + "recipientId": 34708, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/327/200/200", + "relationship": "가족", + "content": "한지민님의 메세지 내용 70", + "font": "Nanum Gothic", + "createdAt": "2023-05-02T00:06:39Z" + } + ], + "reactionCount": 28, + "topReactions": [ + { + "id": 18524, + "emoji": "🎉", + "count": 5 + }, + { + "id": 46949, + "emoji": "😁", + "count": 16 + }, + { + "id": 76510, + "emoji": "😁", + "count": 12 + }, + { + "id": 81605, + "emoji": "😀", + "count": 19 + }, + { + "id": 66745, + "emoji": "🎉", + "count": 13 + } + ] + }, + { + "id": 21977, + "name": "현빈", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/21977/600/400", + "createdAt": "2024-02-05T18:34:45Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 75340, + "recipientId": 21977, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/86/200/200", + "relationship": "친구", + "content": "송혜교님의 메세지 내용 45", + "font": "Roboto", + "createdAt": "2024-01-09T13:48:43Z" + }, + { + "id": 65322, + "recipientId": 21977, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/156/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 79", + "font": "Nanum Gothic", + "createdAt": "2023-09-13T04:30:55Z" + } + ], + "reactionCount": 76, + "topReactions": [ + { + "id": 11821, + "emoji": "😀", + "count": 15 + }, + { + "id": 35147, + "emoji": "😁", + "count": 1 + }, + { + "id": 34644, + "emoji": "🎉", + "count": 5 + } + ] + }, + { + "id": 67245, + "name": "김하은", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-03-05T11:29:45Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 37649, + "recipientId": 67245, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/160/200/200", + "relationship": "지인", + "content": "이병헌님의 메세지 내용 84", + "font": "Roboto", + "createdAt": "2023-05-09T12:36:18Z" + }, + { + "id": 98235, + "recipientId": 67245, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/320/200/200", + "relationship": "동료", + "content": "송혜교님의 메세지 내용 65", + "font": "Nanum Gothic", + "createdAt": "2023-07-11T12:57:47Z" + }, + { + "id": 922, + "recipientId": 67245, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/147/200/200", + "relationship": "지인", + "content": "전지현님의 메세지 내용 12", + "font": "Noto Sans", + "createdAt": "2023-10-05T12:35:41Z" + } + ], + "reactionCount": 35, + "topReactions": [ + { + "id": 59116, + "emoji": "🥹", + "count": 1 + }, + { + "id": 49749, + "emoji": "😀", + "count": 6 + }, + { + "id": 9760, + "emoji": "❤️", + "count": 20 + }, + { + "id": 29620, + "emoji": "😀", + "count": 17 + }, + { + "id": 93360, + "emoji": "🥹", + "count": 5 + }, + { + "id": 55285, + "emoji": "🎉", + "count": 6 + } + ] + }, + { + "id": 60427, + "name": "정우성", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/60427/600/400", + "createdAt": "2023-01-14T01:31:34Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 14341, + "recipientId": 60427, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/68/200/200", + "relationship": "가족", + "content": "이영준님의 메세지 내용 5", + "font": "Pretendard", + "createdAt": "2023-09-09T16:01:13Z" + }, + { + "id": 54177, + "recipientId": 60427, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/499/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 9", + "font": "Noto Sans", + "createdAt": "2023-03-18T17:17:13Z" + }, + { + "id": 10188, + "recipientId": 60427, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/146/200/200", + "relationship": "친구", + "content": "이영준님의 메세지 내용 34", + "font": "Nanum Gothic", + "createdAt": "2023-07-27T13:26:34Z" + } + ], + "reactionCount": 66, + "topReactions": [ + { + "id": 93016, + "emoji": "❤️", + "count": 5 + }, + { + "id": 41560, + "emoji": "👍", + "count": 8 + }, + { + "id": 62205, + "emoji": "👍", + "count": 17 + }, + { + "id": 98001, + "emoji": "🥹", + "count": 4 + } + ] + }, + { + "id": 38317, + "name": "한지민", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/38317/600/400", + "createdAt": "2023-04-20T23:35:17Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 65804, + "recipientId": 38317, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/232/200/200", + "relationship": "친구", + "content": "최민수님의 메세지 내용 90", + "font": "Noto Sans", + "createdAt": "2023-04-13T15:24:49Z" + }, + { + "id": 57545, + "recipientId": 38317, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/58/200/200", + "relationship": "친구", + "content": "송혜교님의 메세지 내용 14", + "font": "Pretendard", + "createdAt": "2023-08-15T18:35:26Z" + } + ], + "reactionCount": 100, + "topReactions": [ + { + "id": 18600, + "emoji": "😁", + "count": 20 + }, + { + "id": 69649, + "emoji": "🥹", + "count": 14 + }, + { + "id": 61872, + "emoji": "🎉", + "count": 12 + }, + { + "id": 53627, + "emoji": "👍", + "count": 3 + }, + { + "id": 97051, + "emoji": "❤️", + "count": 17 + }, + { + "id": 91070, + "emoji": "🥹", + "count": 19 + } + ] + }, + { + "id": 14109, + "name": "박서준", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/14109/600/400", + "createdAt": "2023-06-01T08:10:27Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 78694, + "recipientId": 14109, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/359/200/200", + "relationship": "가족", + "content": "현빈님의 메세지 내용 93", + "font": "Nanum Gothic", + "createdAt": "2024-01-07T06:47:25Z" + }, + { + "id": 98673, + "recipientId": 14109, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/291/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 2", + "font": "Roboto", + "createdAt": "2023-04-22T16:18:34Z" + }, + { + "id": 48915, + "recipientId": 14109, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/254/200/200", + "relationship": "동료", + "content": "최민수님의 메세지 내용 7", + "font": "Noto Sans", + "createdAt": "2024-01-25T22:34:40Z" + } + ], + "reactionCount": 6, + "topReactions": [ + { + "id": 61471, + "emoji": "❤️", + "count": 17 + }, + { + "id": 3871, + "emoji": "👍", + "count": 2 + }, + { + "id": 72869, + "emoji": "😀", + "count": 8 + } + ] + }, + { + "id": 50811, + "name": "이영준", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/50811/600/400", + "createdAt": "2023-10-02T05:46:37Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 87970, + "recipientId": 50811, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/28/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 73", + "font": "Noto Sans", + "createdAt": "2023-05-27T00:59:12Z" + }, + { + "id": 27538, + "recipientId": 50811, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/256/200/200", + "relationship": "지인", + "content": "송혜교님의 메세지 내용 5", + "font": "Nanum Gothic", + "createdAt": "2023-12-22T09:44:50Z" + }, + { + "id": 73753, + "recipientId": 50811, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/148/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 39", + "font": "Noto Sans", + "createdAt": "2023-04-26T05:07:35Z" + } + ], + "reactionCount": 65, + "topReactions": [ + { + "id": 92606, + "emoji": "😁", + "count": 4 + }, + { + "id": 38991, + "emoji": "👍", + "count": 8 + }, + { + "id": 59355, + "emoji": "🥹", + "count": 3 + }, + { + "id": 54969, + "emoji": "🥹", + "count": 6 + }, + { + "id": 33347, + "emoji": "🥹", + "count": 8 + }, + { + "id": 92921, + "emoji": "🎉", + "count": 13 + } + ] + }, + { + "id": 6155, + "name": "전지현", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/seed/6155/600/400", + "createdAt": "2023-07-14T13:41:34Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 3243, + "recipientId": 6155, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/318/200/200", + "relationship": "동료", + "content": "정우성님의 메세지 내용 52", + "font": "Noto Sans", + "createdAt": "2023-08-11T03:36:35Z" + } + ], + "reactionCount": 83, + "topReactions": [ + { + "id": 30441, + "emoji": "❤️", + "count": 1 + }, + { + "id": 39751, + "emoji": "😁", + "count": 20 + }, + { + "id": 53520, + "emoji": "😀", + "count": 20 + }, + { + "id": 10975, + "emoji": "👍", + "count": 7 + } + ] + }, + { + "id": 56213, + "name": "현빈", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-09-15T20:40:35Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 73057, + "recipientId": 56213, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/33/200/200", + "relationship": "지인", + "content": "박서준님의 메세지 내용 81", + "font": "Roboto", + "createdAt": "2023-07-25T17:44:57Z" + }, + { + "id": 89592, + "recipientId": 56213, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/310/200/200", + "relationship": "동료", + "content": "정우성님의 메세지 내용 33", + "font": "Nanum Gothic", + "createdAt": "2023-07-16T12:03:19Z" + }, + { + "id": 94221, + "recipientId": 56213, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/264/200/200", + "relationship": "친구", + "content": "김하은님의 메세지 내용 8", + "font": "Roboto", + "createdAt": "2023-04-24T04:50:36Z" + } + ], + "reactionCount": 46, + "topReactions": [ + { + "id": 62030, + "emoji": "🎉", + "count": 15 + }, + { + "id": 97843, + "emoji": "🎉", + "count": 10 + }, + { + "id": 93058, + "emoji": "😁", + "count": 4 + } + ] + }, + { + "id": 87423, + "name": "한지민", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-07-30T00:10:08Z", + "messageCount": 3, + "recentMessages": [ + { + "id": 71070, + "recipientId": 87423, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/29/200/200", + "relationship": "동료", + "content": "정우성님의 메세지 내용 2", + "font": "Noto Sans", + "createdAt": "2023-06-05T10:27:47Z" + }, + { + "id": 38287, + "recipientId": 87423, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/259/200/200", + "relationship": "지인", + "content": "한지민님의 메세지 내용 51", + "font": "Pretendard", + "createdAt": "2023-10-27T10:50:10Z" + }, + { + "id": 92441, + "recipientId": 87423, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/98/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 89", + "font": "Pretendard", + "createdAt": "2023-11-23T15:03:42Z" + } + ], + "reactionCount": 74, + "topReactions": [ + { + "id": 48788, + "emoji": "🎉", + "count": 3 + }, + { + "id": 40394, + "emoji": "🥹", + "count": 18 + }, + { + "id": 22994, + "emoji": "😁", + "count": 16 + }, + { + "id": 46587, + "emoji": "🎉", + "count": 17 + }, + { + "id": 83614, + "emoji": "🥹", + "count": 13 + } + ] + }, + { + "id": 37498, + "name": "박서준", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/37498/600/400", + "createdAt": "2023-08-19T22:44:58Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 7778, + "recipientId": 37498, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/202/200/200", + "relationship": "가족", + "content": "이병헌님의 메세지 내용 24", + "font": "Pretendard", + "createdAt": "2023-12-27T07:03:22Z" + }, + { + "id": 50047, + "recipientId": 37498, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/448/200/200", + "relationship": "지인", + "content": "한지민님의 메세지 내용 34", + "font": "Noto Sans", + "createdAt": "2023-06-01T01:56:52Z" + }, + { + "id": 849, + "recipientId": 37498, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/319/200/200", + "relationship": "가족", + "content": "김하은님의 메세지 내용 99", + "font": "Roboto", + "createdAt": "2023-04-16T07:26:51Z" + } + ], + "reactionCount": 86, + "topReactions": [ + { + "id": 3081, + "emoji": "❤️", + "count": 15 + }, + { + "id": 5953, + "emoji": "😁", + "count": 9 + }, + { + "id": 28198, + "emoji": "😀", + "count": 2 + }, + { + "id": 89135, + "emoji": "👍", + "count": 5 + } + ] + }, + { + "id": 804, + "name": "김하은", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/804/600/400", + "createdAt": "2023-12-31T06:48:26Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 92345, + "recipientId": 804, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/119/200/200", + "relationship": "동료", + "content": "최민수님의 메세지 내용 82", + "font": "Pretendard", + "createdAt": "2023-08-19T15:47:19Z" + }, + { + "id": 18005, + "recipientId": 804, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/53/200/200", + "relationship": "친구", + "content": "최민수님의 메세지 내용 96", + "font": "Pretendard", + "createdAt": "2023-05-22T23:53:08Z" + } + ], + "reactionCount": 44, + "topReactions": [ + { + "id": 5603, + "emoji": "👍", + "count": 5 + } + ] + }, + { + "id": 27292, + "name": "김하은", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/27292/600/400", + "createdAt": "2023-12-02T16:16:54Z", + "messageCount": 4, + "recentMessages": [ + { + "id": 14570, + "recipientId": 27292, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/145/200/200", + "relationship": "지인", + "content": "이영준님의 메세지 내용 41", + "font": "Noto Sans", + "createdAt": "2023-05-31T17:54:46Z" + }, + { + "id": 73005, + "recipientId": 27292, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/471/200/200", + "relationship": "동료", + "content": "최민수님의 메세지 내용 43", + "font": "Nanum Gothic", + "createdAt": "2023-11-03T09:06:00Z" + }, + { + "id": 67991, + "recipientId": 27292, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/499/200/200", + "relationship": "지인", + "content": "정우성님의 메세지 내용 42", + "font": "Pretendard", + "createdAt": "2024-02-05T04:43:27Z" + } + ], + "reactionCount": 19, + "topReactions": [ + { + "id": 56372, + "emoji": "😁", + "count": 2 + }, + { + "id": 27688, + "emoji": "😀", + "count": 12 + }, + { + "id": 41479, + "emoji": "😁", + "count": 9 + }, + { + "id": 84278, + "emoji": "👍", + "count": 1 + }, + { + "id": 10391, + "emoji": "❤️", + "count": 15 + }, + { + "id": 47486, + "emoji": "👍", + "count": 14 + } + ] + }, + { + "id": 42364, + "name": "송혜교", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/42364/600/400", + "createdAt": "2023-10-24T15:14:56Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 62241, + "recipientId": 42364, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/165/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 17", + "font": "Roboto", + "createdAt": "2023-01-16T13:07:22Z" + }, + { + "id": 35391, + "recipientId": 42364, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/261/200/200", + "relationship": "가족", + "content": "박서준님의 메세지 내용 91", + "font": "Roboto", + "createdAt": "2023-11-27T15:42:27Z" + }, + { + "id": 82773, + "recipientId": 42364, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/343/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 31", + "font": "Nanum Gothic", + "createdAt": "2024-01-31T07:30:06Z" + } + ], + "reactionCount": 51, + "topReactions": [ + { + "id": 91006, + "emoji": "😁", + "count": 7 + }, + { + "id": 33237, + "emoji": "😀", + "count": 9 + }, + { + "id": 53636, + "emoji": "🎉", + "count": 12 + }, + { + "id": 15454, + "emoji": "😀", + "count": 18 + }, + { + "id": 14384, + "emoji": "❤️", + "count": 14 + } + ] + }, + { + "id": 12700, + "name": "이병헌", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-08-18T22:43:12Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 81662, + "recipientId": 12700, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/362/200/200", + "relationship": "가족", + "content": "전지현님의 메세지 내용 94", + "font": "Pretendard", + "createdAt": "2023-01-25T05:02:39Z" + }, + { + "id": 29275, + "recipientId": 12700, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/163/200/200", + "relationship": "지인", + "content": "한지민님의 메세지 내용 32", + "font": "Noto Sans", + "createdAt": "2023-01-19T15:33:19Z" + }, + { + "id": 4746, + "recipientId": 12700, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/260/200/200", + "relationship": "친구", + "content": "이병헌님의 메세지 내용 44", + "font": "Noto Sans", + "createdAt": "2023-02-17T03:59:23Z" + } + ], + "reactionCount": 74, + "topReactions": [ + { + "id": 88984, + "emoji": "❤️", + "count": 18 + }, + { + "id": 57596, + "emoji": "❤️", + "count": 1 + }, + { + "id": 12377, + "emoji": "🥹", + "count": 17 + }, + { + "id": 45146, + "emoji": "❤️", + "count": 9 + }, + { + "id": 53052, + "emoji": "🥹", + "count": 7 + }, + { + "id": 60303, + "emoji": "❤️", + "count": 10 + } + ] + }, + { + "id": 91444, + "name": "송혜교", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/91444/600/400", + "createdAt": "2023-06-03T08:08:37Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 75089, + "recipientId": 91444, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/380/200/200", + "relationship": "지인", + "content": "박서준님의 메세지 내용 22", + "font": "Nanum Gothic", + "createdAt": "2023-12-14T21:41:57Z" + }, + { + "id": 98743, + "recipientId": 91444, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/27/200/200", + "relationship": "친구", + "content": "이영준님의 메세지 내용 74", + "font": "Noto Sans", + "createdAt": "2023-09-23T04:44:23Z" + } + ], + "reactionCount": 9, + "topReactions": [ + { + "id": 5270, + "emoji": "🎉", + "count": 4 + }, + { + "id": 42056, + "emoji": "🎉", + "count": 9 + }, + { + "id": 79595, + "emoji": "❤️", + "count": 20 + }, + { + "id": 49566, + "emoji": "😁", + "count": 10 + } + ] + }, + { + "id": 431, + "name": "송혜교", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/431/600/400", + "createdAt": "2023-09-19T05:38:16Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 85796, + "recipientId": 431, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/391/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 89", + "font": "Pretendard", + "createdAt": "2023-06-30T16:55:54Z" + }, + { + "id": 45946, + "recipientId": 431, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/231/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 22", + "font": "Noto Sans", + "createdAt": "2023-07-29T17:47:32Z" + }, + { + "id": 19138, + "recipientId": 431, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/112/200/200", + "relationship": "친구", + "content": "전지현님의 메세지 내용 98", + "font": "Pretendard", + "createdAt": "2023-03-09T07:33:56Z" + } + ], + "reactionCount": 53, + "topReactions": [ + { + "id": 89292, + "emoji": "❤️", + "count": 4 + }, + { + "id": 50557, + "emoji": "🥹", + "count": 14 + }, + { + "id": 50390, + "emoji": "🎉", + "count": 1 + } + ] + }, + { + "id": 59201, + "name": "한지민", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/59201/600/400", + "createdAt": "2023-08-02T10:38:08Z", + "messageCount": 10, + "recentMessages": [ + { + "id": 92555, + "recipientId": 59201, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/65/200/200", + "relationship": "친구", + "content": "전지현님의 메세지 내용 91", + "font": "Roboto", + "createdAt": "2023-04-10T02:51:26Z" + }, + { + "id": 64459, + "recipientId": 59201, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/452/200/200", + "relationship": "가족", + "content": "전지현님의 메세지 내용 13", + "font": "Noto Sans", + "createdAt": "2023-11-09T13:15:50Z" + }, + { + "id": 48918, + "recipientId": 59201, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/45/200/200", + "relationship": "지인", + "content": "박서준님의 메세지 내용 21", + "font": "Roboto", + "createdAt": "2023-01-05T13:09:05Z" + } + ], + "reactionCount": 65, + "topReactions": [ + { + "id": 79656, + "emoji": "🎉", + "count": 14 + } + ] + }, + { + "id": 6989, + "name": "김하은", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/6989/600/400", + "createdAt": "2023-04-14T01:33:48Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 81227, + "recipientId": 6989, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/484/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 56", + "font": "Roboto", + "createdAt": "2024-01-05T22:51:56Z" + }, + { + "id": 15361, + "recipientId": 6989, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/281/200/200", + "relationship": "지인", + "content": "현빈님의 메세지 내용 46", + "font": "Noto Sans", + "createdAt": "2023-06-19T05:28:03Z" + }, + { + "id": 98203, + "recipientId": 6989, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/28/200/200", + "relationship": "친구", + "content": "정우성님의 메세지 내용 88", + "font": "Pretendard", + "createdAt": "2023-12-18T08:50:50Z" + } + ], + "reactionCount": 41, + "topReactions": [ + { + "id": 90464, + "emoji": "😀", + "count": 14 + }, + { + "id": 30005, + "emoji": "😀", + "count": 10 + } + ] + }, + { + "id": 56031, + "name": "전지현", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/56031/600/400", + "createdAt": "2023-01-03T23:21:51Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 47661, + "recipientId": 56031, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/395/200/200", + "relationship": "동료", + "content": "이병헌님의 메세지 내용 62", + "font": "Nanum Gothic", + "createdAt": "2023-08-20T17:27:35Z" + }, + { + "id": 20252, + "recipientId": 56031, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/49/200/200", + "relationship": "동료", + "content": "현빈님의 메세지 내용 63", + "font": "Nanum Gothic", + "createdAt": "2023-07-10T22:36:06Z" + }, + { + "id": 23385, + "recipientId": 56031, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/498/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 11", + "font": "Nanum Gothic", + "createdAt": "2023-06-21T11:14:02Z" + } + ], + "reactionCount": 83, + "topReactions": [ + { + "id": 33533, + "emoji": "❤️", + "count": 11 + }, + { + "id": 51483, + "emoji": "🥹", + "count": 16 + } + ] + }, + { + "id": 2331, + "name": "송혜교", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/2331/600/400", + "createdAt": "2023-12-17T01:45:14Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 66942, + "recipientId": 2331, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/245/200/200", + "relationship": "가족", + "content": "전지현님의 메세지 내용 89", + "font": "Pretendard", + "createdAt": "2023-08-18T18:11:01Z" + }, + { + "id": 42191, + "recipientId": 2331, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/336/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 55", + "font": "Nanum Gothic", + "createdAt": "2023-02-06T06:21:56Z" + }, + { + "id": 8612, + "recipientId": 2331, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/120/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 40", + "font": "Noto Sans", + "createdAt": "2023-05-16T19:20:19Z" + } + ], + "reactionCount": 61, + "topReactions": [ + { + "id": 76710, + "emoji": "👍", + "count": 5 + } + ] + }, + { + "id": 80397, + "name": "최민수", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-11-20T05:03:59Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 51404, + "recipientId": 80397, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/222/200/200", + "relationship": "지인", + "content": "송혜교님의 메세지 내용 47", + "font": "Nanum Gothic", + "createdAt": "2023-11-10T08:33:06Z" + }, + { + "id": 3634, + "recipientId": 80397, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/430/200/200", + "relationship": "동료", + "content": "김하은님의 메세지 내용 63", + "font": "Noto Sans", + "createdAt": "2023-04-27T11:10:26Z" + } + ], + "reactionCount": 97, + "topReactions": [ + { + "id": 82751, + "emoji": "🥹", + "count": 7 + }, + { + "id": 27780, + "emoji": "🥹", + "count": 11 + }, + { + "id": 11937, + "emoji": "❤️", + "count": 15 + }, + { + "id": 35875, + "emoji": "❤️", + "count": 9 + }, + { + "id": 93134, + "emoji": "😀", + "count": 6 + } + ] + }, + { + "id": 92514, + "name": "정우성", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-10-03T05:42:45Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 17969, + "recipientId": 92514, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/229/200/200", + "relationship": "동료", + "content": "최민수님의 메세지 내용 59", + "font": "Pretendard", + "createdAt": "2023-07-25T08:20:39Z" + }, + { + "id": 27640, + "recipientId": 92514, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/12/200/200", + "relationship": "지인", + "content": "한지민님의 메세지 내용 90", + "font": "Noto Sans", + "createdAt": "2023-08-09T19:30:02Z" + }, + { + "id": 51718, + "recipientId": 92514, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/196/200/200", + "relationship": "가족", + "content": "전지현님의 메세지 내용 50", + "font": "Noto Sans", + "createdAt": "2023-09-21T04:00:24Z" + } + ], + "reactionCount": 48, + "topReactions": [ + { + "id": 33044, + "emoji": "🥹", + "count": 18 + }, + { + "id": 77894, + "emoji": "😁", + "count": 4 + }, + { + "id": 97021, + "emoji": "🎉", + "count": 17 + }, + { + "id": 94868, + "emoji": "🥹", + "count": 3 + } + ] + }, + { + "id": 91659, + "name": "박서준", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/91659/600/400", + "createdAt": "2023-02-05T05:14:29Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 86637, + "recipientId": 91659, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/95/200/200", + "relationship": "동료", + "content": "최민수님의 메세지 내용 53", + "font": "Nanum Gothic", + "createdAt": "2023-12-23T14:34:42Z" + }, + { + "id": 43583, + "recipientId": 91659, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/400/200/200", + "relationship": "지인", + "content": "김하은님의 메세지 내용 31", + "font": "Pretendard", + "createdAt": "2023-06-03T00:26:24Z" + }, + { + "id": 32047, + "recipientId": 91659, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/127/200/200", + "relationship": "가족", + "content": "한지민님의 메세지 내용 65", + "font": "Pretendard", + "createdAt": "2023-12-30T16:06:15Z" + } + ], + "reactionCount": 13, + "topReactions": [ + { + "id": 81498, + "emoji": "❤️", + "count": 10 + }, + { + "id": 39236, + "emoji": "❤️", + "count": 17 + } + ] + }, + { + "id": 52526, + "name": "전지현", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-12-06T09:42:54Z", + "messageCount": 3, + "recentMessages": [ + { + "id": 95226, + "recipientId": 52526, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/364/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 12", + "font": "Roboto", + "createdAt": "2023-03-22T23:13:59Z" + }, + { + "id": 5308, + "recipientId": 52526, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/293/200/200", + "relationship": "친구", + "content": "박서준님의 메세지 내용 53", + "font": "Roboto", + "createdAt": "2023-07-05T04:02:56Z" + }, + { + "id": 22581, + "recipientId": 52526, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/471/200/200", + "relationship": "지인", + "content": "한지민님의 메세지 내용 100", + "font": "Pretendard", + "createdAt": "2023-07-11T08:25:24Z" + } + ], + "reactionCount": 57, + "topReactions": [ + { + "id": 5184, + "emoji": "👍", + "count": 18 + }, + { + "id": 31068, + "emoji": "😁", + "count": 8 + }, + { + "id": 87339, + "emoji": "👍", + "count": 2 + }, + { + "id": 79179, + "emoji": "❤️", + "count": 15 + }, + { + "id": 2076, + "emoji": "😁", + "count": 9 + }, + { + "id": 9962, + "emoji": "👍", + "count": 15 + } + ] + }, + { + "id": 66246, + "name": "박서준", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/66246/600/400", + "createdAt": "2023-06-05T11:15:08Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 67335, + "recipientId": 66246, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/155/200/200", + "relationship": "지인", + "content": "최민수님의 메세지 내용 92", + "font": "Pretendard", + "createdAt": "2023-11-13T18:00:50Z" + }, + { + "id": 97868, + "recipientId": 66246, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/163/200/200", + "relationship": "가족", + "content": "송혜교님의 메세지 내용 8", + "font": "Nanum Gothic", + "createdAt": "2024-01-30T05:20:18Z" + }, + { + "id": 36892, + "recipientId": 66246, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/204/200/200", + "relationship": "친구", + "content": "송혜교님의 메세지 내용 51", + "font": "Noto Sans", + "createdAt": "2023-04-03T14:58:25Z" + } + ], + "reactionCount": 87, + "topReactions": [ + { + "id": 87641, + "emoji": "😁", + "count": 12 + }, + { + "id": 89470, + "emoji": "😀", + "count": 4 + }, + { + "id": 40031, + "emoji": "❤️", + "count": 1 + }, + { + "id": 42953, + "emoji": "😁", + "count": 18 + } + ] + }, + { + "id": 78492, + "name": "현빈", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-06-27T06:54:39Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 51872, + "recipientId": 78492, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/149/200/200", + "relationship": "지인", + "content": "전지현님의 메세지 내용 14", + "font": "Nanum Gothic", + "createdAt": "2023-08-29T19:08:59Z" + }, + { + "id": 55542, + "recipientId": 78492, + "sender": "전지현", + "profileImageURL": "https://picsum.photos/id/283/200/200", + "relationship": "지인", + "content": "전지현님의 메세지 내용 79", + "font": "Nanum Gothic", + "createdAt": "2023-01-14T20:52:51Z" + }, + { + "id": 93850, + "recipientId": 78492, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/441/200/200", + "relationship": "지인", + "content": "송혜교님의 메세지 내용 80", + "font": "Pretendard", + "createdAt": "2023-11-01T00:19:15Z" + } + ], + "reactionCount": 55, + "topReactions": [ + { + "id": 71312, + "emoji": "❤️", + "count": 1 + } + ] + }, + { + "id": 82777, + "name": "현빈", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-09-15T12:08:04Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 87777, + "recipientId": 82777, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/233/200/200", + "relationship": "지인", + "content": "현빈님의 메세지 내용 6", + "font": "Nanum Gothic", + "createdAt": "2023-06-02T07:12:19Z" + }, + { + "id": 80014, + "recipientId": 82777, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/243/200/200", + "relationship": "지인", + "content": "이영준님의 메세지 내용 12", + "font": "Nanum Gothic", + "createdAt": "2023-03-29T10:02:35Z" + }, + { + "id": 70414, + "recipientId": 82777, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/179/200/200", + "relationship": "친구", + "content": "송혜교님의 메세지 내용 38", + "font": "Noto Sans", + "createdAt": "2023-10-05T10:33:01Z" + } + ], + "reactionCount": 34, + "topReactions": [ + { + "id": 4256, + "emoji": "👍", + "count": 4 + }, + { + "id": 89759, + "emoji": "❤️", + "count": 3 + } + ] + }, + { + "id": 16044, + "name": "전지현", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-05-20T07:28:44Z", + "messageCount": 1, + "recentMessages": [ + { + "id": 88553, + "recipientId": 16044, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/109/200/200", + "relationship": "가족", + "content": "최민수님의 메세지 내용 76", + "font": "Pretendard", + "createdAt": "2023-08-03T22:59:16Z" + } + ], + "reactionCount": 40, + "topReactions": [ + { + "id": 93310, + "emoji": "😁", + "count": 4 + }, + { + "id": 37249, + "emoji": "😁", + "count": 5 + }, + { + "id": 73269, + "emoji": "🥹", + "count": 7 + } + ] + }, + { + "id": 42617, + "name": "정우성", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-09-04T03:21:42Z", + "messageCount": 6, + "recentMessages": [ + { + "id": 36095, + "recipientId": 42617, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/119/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 8", + "font": "Nanum Gothic", + "createdAt": "2023-03-20T16:47:37Z" + }, + { + "id": 79006, + "recipientId": 42617, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/58/200/200", + "relationship": "친구", + "content": "김하은님의 메세지 내용 81", + "font": "Roboto", + "createdAt": "2023-05-27T14:29:42Z" + }, + { + "id": 54211, + "recipientId": 42617, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/57/200/200", + "relationship": "지인", + "content": "현빈님의 메세지 내용 70", + "font": "Nanum Gothic", + "createdAt": "2023-05-14T01:15:48Z" + } + ], + "reactionCount": 12, + "topReactions": [ + { + "id": 66681, + "emoji": "🥹", + "count": 8 + }, + { + "id": 67854, + "emoji": "😁", + "count": 15 + }, + { + "id": 94387, + "emoji": "❤️", + "count": 16 + }, + { + "id": 94338, + "emoji": "🎉", + "count": 20 + }, + { + "id": 59665, + "emoji": "🎉", + "count": 8 + } + ] + }, + { + "id": 63381, + "name": "최민수", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/seed/63381/600/400", + "createdAt": "2023-05-05T23:49:25Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 56206, + "recipientId": 63381, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/73/200/200", + "relationship": "친구", + "content": "최민수님의 메세지 내용 80", + "font": "Nanum Gothic", + "createdAt": "2023-09-19T13:55:51Z" + }, + { + "id": 15343, + "recipientId": 63381, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/1/200/200", + "relationship": "가족", + "content": "정우성님의 메세지 내용 30", + "font": "Nanum Gothic", + "createdAt": "2023-12-09T14:00:31Z" + }, + { + "id": 64540, + "recipientId": 63381, + "sender": "송혜교", + "profileImageURL": "https://picsum.photos/id/486/200/200", + "relationship": "동료", + "content": "송혜교님의 메세지 내용 92", + "font": "Noto Sans", + "createdAt": "2023-04-10T11:58:05Z" + } + ], + "reactionCount": 26, + "topReactions": [ + { + "id": 63913, + "emoji": "😀", + "count": 8 + }, + { + "id": 82488, + "emoji": "🎉", + "count": 6 + }, + { + "id": 38729, + "emoji": "👍", + "count": 3 + }, + { + "id": 79770, + "emoji": "❤️", + "count": 16 + }, + { + "id": 75631, + "emoji": "🎉", + "count": 5 + } + ] + }, + { + "id": 25814, + "name": "송혜교", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/seed/25814/600/400", + "createdAt": "2023-09-02T07:06:25Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 18455, + "recipientId": 25814, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/361/200/200", + "relationship": "동료", + "content": "박서준님의 메세지 내용 49", + "font": "Noto Sans", + "createdAt": "2023-02-12T08:14:35Z" + }, + { + "id": 45626, + "recipientId": 25814, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/476/200/200", + "relationship": "동료", + "content": "최민수님의 메세지 내용 18", + "font": "Pretendard", + "createdAt": "2023-09-04T23:48:15Z" + }, + { + "id": 71644, + "recipientId": 25814, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/485/200/200", + "relationship": "친구", + "content": "현빈님의 메세지 내용 59", + "font": "Roboto", + "createdAt": "2023-08-12T05:15:13Z" + } + ], + "reactionCount": 45, + "topReactions": [ + { + "id": 86657, + "emoji": "🥹", + "count": 10 + }, + { + "id": 6702, + "emoji": "🎉", + "count": 11 + }, + { + "id": 64387, + "emoji": "🥹", + "count": 7 + }, + { + "id": 16189, + "emoji": "😀", + "count": 11 + }, + { + "id": 58652, + "emoji": "🎉", + "count": 2 + }, + { + "id": 67118, + "emoji": "🥹", + "count": 5 + } + ] + }, + { + "id": 85652, + "name": "현빈", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-09-30T18:53:27Z", + "messageCount": 7, + "recentMessages": [ + { + "id": 13934, + "recipientId": 85652, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/456/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 43", + "font": "Pretendard", + "createdAt": "2023-11-22T11:38:51Z" + }, + { + "id": 5599, + "recipientId": 85652, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/26/200/200", + "relationship": "지인", + "content": "정우성님의 메세지 내용 90", + "font": "Nanum Gothic", + "createdAt": "2023-11-21T01:23:07Z" + }, + { + "id": 78185, + "recipientId": 85652, + "sender": "이영준", + "profileImageURL": "https://picsum.photos/id/193/200/200", + "relationship": "가족", + "content": "이영준님의 메세지 내용 14", + "font": "Nanum Gothic", + "createdAt": "2024-01-16T07:51:56Z" + } + ], + "reactionCount": 15, + "topReactions": [ + { + "id": 40353, + "emoji": "🥹", + "count": 19 + }, + { + "id": 25637, + "emoji": "👍", + "count": 17 + }, + { + "id": 34226, + "emoji": "🥹", + "count": 4 + }, + { + "id": 14495, + "emoji": "👍", + "count": 14 + }, + { + "id": 96566, + "emoji": "❤️", + "count": 3 + }, + { + "id": 2409, + "emoji": "🎉", + "count": 10 + } + ] + }, + { + "id": 70835, + "name": "이영준", + "backgroundColor": "beige", + "backgroundImageURL": null, + "createdAt": "2023-04-17T15:50:50Z", + "messageCount": 9, + "recentMessages": [ + { + "id": 32521, + "recipientId": 70835, + "sender": "김하은", + "profileImageURL": "https://picsum.photos/id/475/200/200", + "relationship": "지인", + "content": "김하은님의 메세지 내용 24", + "font": "Pretendard", + "createdAt": "2023-09-29T00:00:45Z" + }, + { + "id": 77740, + "recipientId": 70835, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/288/200/200", + "relationship": "지인", + "content": "박서준님의 메세지 내용 84", + "font": "Roboto", + "createdAt": "2023-02-22T09:49:22Z" + }, + { + "id": 95524, + "recipientId": 70835, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/375/200/200", + "relationship": "동료", + "content": "한지민님의 메세지 내용 91", + "font": "Nanum Gothic", + "createdAt": "2023-04-04T03:33:36Z" + } + ], + "reactionCount": 73, + "topReactions": [ + { + "id": 83819, + "emoji": "😁", + "count": 15 + }, + { + "id": 91850, + "emoji": "🥹", + "count": 2 + } + ] + }, + { + "id": 77967, + "name": "김하은", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/seed/77967/600/400", + "createdAt": "2023-01-25T15:36:52Z", + "messageCount": 5, + "recentMessages": [ + { + "id": 58327, + "recipientId": 77967, + "sender": "최민수", + "profileImageURL": "https://picsum.photos/id/333/200/200", + "relationship": "친구", + "content": "최민수님의 메세지 내용 39", + "font": "Pretendard", + "createdAt": "2023-06-14T02:06:26Z" + }, + { + "id": 8140, + "recipientId": 77967, + "sender": "현빈", + "profileImageURL": "https://picsum.photos/id/320/200/200", + "relationship": "동료", + "content": "현빈님의 메세지 내용 17", + "font": "Pretendard", + "createdAt": "2023-03-29T03:09:31Z" + }, + { + "id": 99412, + "recipientId": 77967, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/301/200/200", + "relationship": "동료", + "content": "한지민님의 메세지 내용 49", + "font": "Pretendard", + "createdAt": "2023-09-30T06:21:13Z" + } + ], + "reactionCount": 12, + "topReactions": [ + { + "id": 14335, + "emoji": "❤️", + "count": 10 + }, + { + "id": 37620, + "emoji": "😁", + "count": 18 + }, + { + "id": 35030, + "emoji": "😁", + "count": 18 + } + ] + }, + { + "id": 31249, + "name": "이병헌", + "backgroundColor": "blue", + "backgroundImageURL": null, + "createdAt": "2023-05-16T17:41:45Z", + "messageCount": 2, + "recentMessages": [ + { + "id": 77297, + "recipientId": 31249, + "sender": "정우성", + "profileImageURL": "https://picsum.photos/id/356/200/200", + "relationship": "동료", + "content": "정우성님의 메세지 내용 30", + "font": "Roboto", + "createdAt": "2023-10-09T19:45:25Z" + }, + { + "id": 54855, + "recipientId": 31249, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/188/200/200", + "relationship": "지인", + "content": "이병헌님의 메세지 내용 84", + "font": "Pretendard", + "createdAt": "2023-07-01T14:34:04Z" + } + ], + "reactionCount": 87, + "topReactions": [ + { + "id": 64819, + "emoji": "😀", + "count": 16 + }, + { + "id": 14849, + "emoji": "😀", + "count": 4 + }, + { + "id": 30100, + "emoji": "🎉", + "count": 15 + } + ] + }, + { + "id": 87008, + "name": "이병헌", + "backgroundColor": "purple", + "backgroundImageURL": null, + "createdAt": "2023-05-31T18:24:49Z", + "messageCount": 8, + "recentMessages": [ + { + "id": 2572, + "recipientId": 87008, + "sender": "한지민", + "profileImageURL": "https://picsum.photos/id/379/200/200", + "relationship": "친구", + "content": "한지민님의 메세지 내용 9", + "font": "Roboto", + "createdAt": "2023-05-01T19:29:33Z" + }, + { + "id": 29069, + "recipientId": 87008, + "sender": "이병헌", + "profileImageURL": "https://picsum.photos/id/25/200/200", + "relationship": "지인", + "content": "이병헌님의 메세지 내용 19", + "font": "Roboto", + "createdAt": "2024-01-14T03:59:30Z" + }, + { + "id": 33287, + "recipientId": 87008, + "sender": "박서준", + "profileImageURL": "https://picsum.photos/id/71/200/200", + "relationship": "친구", + "content": "박서준님의 메세지 내용 61", + "font": "Nanum Gothic", + "createdAt": "2023-08-09T16:33:57Z" + } + ], + "reactionCount": 42, + "topReactions": [ + { + "id": 86769, + "emoji": "❤️", + "count": 10 + }, + { + "id": 17942, + "emoji": "👍", + "count": 8 + }, + { + "id": 88772, + "emoji": "😀", + "count": 5 + }, + { + "id": 69231, + "emoji": "👍", + "count": 15 + } + ] + } +] From 9aae688abbb429a42d62447d688518e82ba1037c Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 14 Aug 2025 15:01:41 +0900 Subject: [PATCH 076/253] =?UTF-8?q?feat=20[#36]=20=EB=B8=8C=EB=9D=BC?= =?UTF-8?q?=EC=9A=B0=EC=A0=80=20=EC=B0=BD=20=ED=81=AC=EA=B8=B0=EB=A5=BC=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=ED=95=A0=20=EB=95=8C=20popover=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=20=EA=B0=B1=EC=8B=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/use-popover.jsx | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/hooks/use-popover.jsx b/src/hooks/use-popover.jsx index 6efc314..70cea0d 100644 --- a/src/hooks/use-popover.jsx +++ b/src/hooks/use-popover.jsx @@ -1,4 +1,4 @@ -import { useContext, useState } from "react"; +import { useContext, useState, useEffect } from "react"; import POPOVER_ALIGNMENT from "../components/popover/popover-alignment"; import PopoverContext from "../components/popover/popover-context"; @@ -27,17 +27,36 @@ function calculatePopoverPosition(target, alignment) { function usePopover() { const { showsPopover, setShowsPopover } = useContext(PopoverContext); const [popoverPosition, setPopoverPosition] = useState(); + const [target, setTarget] = useState(); + const [alignment, setAlignment] = useState(POPOVER_ALIGNMENT.left); const openPopopver = ({ target, alignment }) => { - const position = calculatePopoverPosition(target, alignment); + updatePopoverPosition(target, alignment); + setTarget(target); + setAlignment(alignment); setShowsPopover(true); - setPopoverPosition(position); }; const closePopover = () => { setShowsPopover(false); }; + const updatePopoverPosition = (target, alignment) => { + const position = calculatePopoverPosition(target, alignment); + setPopoverPosition(position); + }; + + useEffect(() => { + if (!showsPopover) return; + + function handleWindowResize() { + updatePopoverPosition(target, alignment); + } + + window.addEventListener("resize", handleWindowResize); + return () => window.removeEventListener("resize", handleWindowResize); + }, [showsPopover, target, alignment]); + return { popoverPosition, showsPopover, From bccf3f293edd72d3686a5db165103685d2c96273 Mon Sep 17 00:00:00 2001 From: luli Date: Thu, 14 Aug 2025 15:12:41 +0900 Subject: [PATCH 077/253] =?UTF-8?q?[#37]=20=20=ED=95=A8=EC=88=98=EB=AA=85?= =?UTF-8?q?=20handle~=EA=B5=AC=EC=A1=B0=EB=A1=9C=20=EB=B3=80=EA=B2=BD,=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=20=EA=B0=84=EB=9E=B5=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (pr수정사항 누락된부분 추가 수정) --- src/pages/rolling-paper-list-page.jsx | 62 +++++++++++++-------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/src/pages/rolling-paper-list-page.jsx b/src/pages/rolling-paper-list-page.jsx index 8812315..be7816d 100644 --- a/src/pages/rolling-paper-list-page.jsx +++ b/src/pages/rolling-paper-list-page.jsx @@ -96,7 +96,7 @@ const CardItem = styled.div` } `; -const NextBtnWpr = styled.div` +const NextButtonWrapper = styled.div` position: absolute; right: -20px; top: 50%; @@ -104,7 +104,7 @@ const NextBtnWpr = styled.div` z-index: 10; `; -const PrevBtnWpr = styled.div` +const PreviewButtonWrapper = styled.div` position: absolute; left: -20px; top: 50%; @@ -112,7 +112,7 @@ const PrevBtnWpr = styled.div` z-index: 10; `; -const MakingBtn = styled(PrimaryButton)` +const MakingButton = styled(PrimaryButton)` margin-top: 64px; font-weight: 400; padding: 14px 60px; @@ -157,27 +157,17 @@ function ShowMessageList() { ); }, [popularCurrentPage, recentCurrentPage, testData]); - const nextPage = (mode) => { - if (mode) { - if (popularCurrentPage < totalPages - 1) { - setPopularCurrentPage((pprCurrentNum) => pprCurrentNum + 1); - } - } else { - if (recentCurrentPage < totalPages - 1) { - setRecentCurrentPage((currentNum) => currentNum + 1); - } - } - }; + const handleTurnCards = (direction, mode) => { + const current = mode === "popular" ? popularCurrentPage : recentCurrentPage; + const setter = + mode === "popular" ? setPopularCurrentPage : setRecentCurrentPage; + const total = totalPages; + + const additionalPageIndex = direction === "next" ? 1 : -1; + const newPageIndex = current + additionalPageIndex; - const prevPage = (mode) => { - if (mode) { - if (popularCurrentPage > 0) { - setPopularCurrentPage((pprCurrentNum) => pprCurrentNum - 1); - } - } else { - if (recentCurrentPage > 0) { - setRecentCurrentPage((currentNum) => currentNum - 1); - } + if (newPageIndex >= 0 && newPageIndex < total) { + setter(newPageIndex); } }; @@ -212,14 +202,18 @@ function ShowMessageList() { ))} {popularCurrentPage > 0 ? ( - prevPage("ppr")}> + handleTurnCards("preview", "popular")} + > - + ) : null} {popularCurrentPage < totalPages - 1 ? ( - nextPage("ppr")}> + handleTurnCards("next", "popular")} + > - + ) : null} @@ -251,19 +245,23 @@ function ShowMessageList() { ))} {recentCurrentPage > 0 ? ( - prevPage()}> + handleTurnCards("preview", "recent")} + > - + ) : null} {recentCurrentPage < totalPages - 1 ? ( - nextPage()}> + handleTurnCards("next", "recent")} + > - + ) : null} - +
); } From 7c3ef1ba4c2a969eaf25ef4b55ee6d14e4e5ca96 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Thu, 14 Aug 2025 16:37:15 +0900 Subject: [PATCH 078/253] =?UTF-8?q?feat=20#22=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=ED=95=98=EA=B8=B0=20=EB=B2=84=ED=8A=BC=20PrimaryButton=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/image-option-arches.svg | 9 +++ src/assets/image-option-car.svg | 9 +++ src/components/option/background-select.jsx | 66 +++++++++++++++++++++ src/pages/post-page.jsx | 18 +++++- 4 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 src/assets/image-option-arches.svg create mode 100644 src/assets/image-option-car.svg create mode 100644 src/components/option/background-select.jsx diff --git a/src/assets/image-option-arches.svg b/src/assets/image-option-arches.svg new file mode 100644 index 0000000..1420d13 --- /dev/null +++ b/src/assets/image-option-arches.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/image-option-car.svg b/src/assets/image-option-car.svg new file mode 100644 index 0000000..dbc67a5 --- /dev/null +++ b/src/assets/image-option-car.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/components/option/background-select.jsx b/src/components/option/background-select.jsx new file mode 100644 index 0000000..0e0c937 --- /dev/null +++ b/src/components/option/background-select.jsx @@ -0,0 +1,66 @@ +import Colors from "../color/colors"; +import { ReactComponent as ArchesImage } from "../../assets/image-option-arches.svg"; +import { ReactComponent as CarImage } from "../../assets/image-option-car.svg"; +import styled from "styled-components"; +import { ReactComponent as CheckImage } from "../../assets/ic-check.svg"; + +const BackgroundWrapper = styled.div` + display: flex; + gap: 16px; +`; + +const OptionBox = styled.div` + display: flex; + justify-content: center; + align-items: center; + width: 168px; + height: 168px; + border-radius: 8px; + cursor: pointer; + position: relative; +`; + +const CheckWrapper = styled.div` + position: absolute; + top: 8px; + right: 8px; +`; + +function BackgroundSelect({ type = "color", selected, onSelect }) { + const colorOptions = [ + { label: "orange", color: Colors.beige(200) }, + { label: "purple", color: Colors.purple(200) }, + { label: "blue", color: Colors.blue(200) }, + { label: "green", color: Colors.green(200) }, + ]; + + const imageOptions = [ + { label: "arches", image: }, + { label: "car", image: }, + ]; + + const options = type === "color" ? colorOptions : imageOptions; + + return ( + + {options.map((option) => ( + + onSelect(type === "color" ? option.color : option.label) + } + > + {type === "image" && option.image} + {selected === (type === "color" ? option.color : option.label) && ( + + + + )} + + ))} + + ); +} + +export default BackgroundSelect; diff --git a/src/pages/post-page.jsx b/src/pages/post-page.jsx index f88a174..bee19bd 100644 --- a/src/pages/post-page.jsx +++ b/src/pages/post-page.jsx @@ -4,6 +4,7 @@ import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; import Colors from "../components/color/colors"; import ToggleButton from "../components/button/toggle-button"; import styled from "styled-components"; +import { PrimaryButton } from "../components/button/button"; const PostContainerStyle = styled.div` display: flex; @@ -33,6 +34,18 @@ const PostToggleButtonStyle = styled.div` display: flex; `; +const ButtonWrapperStyle = styled.div` + padding-top: 50px; + width: 720px; + display: flex; + justify-content: center; + align-items: center; + + & > * { + flex: 1; + } +`; + function PostPage() { const [name, setName] = useState(""); const [nameError, setNameError] = useState(""); @@ -74,7 +87,10 @@ function PostPage() { - + + + + ); } From 57a61b5f150efb1987d5b19f5cca75283bc0124c Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 14 Aug 2025 17:12:08 +0900 Subject: [PATCH 079/253] =?UTF-8?q?feat=20[#39]=20Avatar=20component=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/avatar/avatar-size.js | 8 ++++ src/components/avatar/avatar.jsx | 59 ++++++++++++++++++++++++++++ src/pages/test-page.jsx | 24 ++++++++++- 3 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 src/components/avatar/avatar-size.js create mode 100644 src/components/avatar/avatar.jsx diff --git a/src/components/avatar/avatar-size.js b/src/components/avatar/avatar-size.js new file mode 100644 index 0000000..9bb1492 --- /dev/null +++ b/src/components/avatar/avatar-size.js @@ -0,0 +1,8 @@ +const AVATAR_SIZE = Object.freeze({ + large: 80, + medium: 56, + small: 40, + extraSmall: 28, +}); + +export default AVATAR_SIZE; diff --git a/src/components/avatar/avatar.jsx b/src/components/avatar/avatar.jsx new file mode 100644 index 0000000..d5146e8 --- /dev/null +++ b/src/components/avatar/avatar.jsx @@ -0,0 +1,59 @@ +import styled, { css } from "styled-components"; +import defaultAvatarImage from "../../assets/ic-person.svg"; +import Colors from "../color/colors"; +import AVATAR_SIZE from "./avatar-size"; + +const borderWidth = { + [AVATAR_SIZE.large]: 0, + [AVATAR_SIZE.medium]: 1, + [AVATAR_SIZE.small]: 1, + [AVATAR_SIZE.extraSmall]: 1.5, +}; + +const avatarStyle = css` + width: ${({ $size }) => $size}px; + height: ${({ $size }) => $size}px; + border-radius: ${({ $size }) => $size / 2}px; + overflow: hidden; +`; + +const StyledAvatar = styled.div` + ${avatarStyle} + border: ${({ $size }) => borderWidth[`${$size}`]}px solid ${({ $color }) => + $color}; + + img { + width: 100%; + height: 100%; + } +`; + +const StyledDefaultAvatar = styled.div` + ${avatarStyle} + background-color: ${Colors.gray(300)}; + display: flex; + justify-content: center; + align-items: center; + + img { + width: ${({ $size }) => $size * 0.4}px; + height: ${({ $size }) => $size * 0.4}px; + } +`; + +function Avatar({ + source, + size = AVATAR_SIZE.medium, + color = Colors.gray(200), +}) { + const img = 사용자 사진; + return source ? ( + + {img} + + ) : ( + {img} + ); +} + +export default Avatar; diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index c254524..0089ee5 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -1,6 +1,8 @@ import { useState } from "react"; import styled from "styled-components"; import smileAddImg from "../assets/ic-face-smile-add.svg"; +import Avatar from "../components/avatar/avatar"; +import AVATAR_SIZE from "../components/avatar/avatar-size"; import Badge from "../components/badge/badge"; import BADGE_TYPE from "../components/badge/badge-type"; import EmojiBadge from "../components/badge/emoji-badge"; @@ -44,11 +46,11 @@ function TestPage() { const handleToastClick = () => setShowsToast(true); const handleToastDismiss = () => setShowsToast(false); - + /* Modal */ const { showsModal, setShowsModal } = useModal(); const handleModalClick = () => setShowsModal(true); - + return (
)}
+
+
+ + + + + + + + +
+
+
); } From 296d1c505bbbe9dad4eca7d768ab7713116b5df0 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 14 Aug 2025 17:14:14 +0900 Subject: [PATCH 080/253] =?UTF-8?q?refactor=20[#39]=20`Modal`=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=82=AC=EC=9A=A9=EC=9E=90=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EC=9D=B4=EB=AF=B8=EC=A7=80=EB=A5=BC=20`Avatar`?= =?UTF-8?q?=EB=A1=9C=20=EA=B5=90=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/modal/modal.jsx | 45 +++------------------------------- 1 file changed, 3 insertions(+), 42 deletions(-) diff --git a/src/components/modal/modal.jsx b/src/components/modal/modal.jsx index d8b4aa2..eb06aa9 100644 --- a/src/components/modal/modal.jsx +++ b/src/components/modal/modal.jsx @@ -1,53 +1,14 @@ import { createPortal } from "react-dom"; -import styled, { css } from "styled-components"; -import defaultProfileImg from "../../assets/ic-person.svg"; +import styled from "styled-components"; import { useModal } from "../../hooks/use-modal"; import { formatDate } from "../../utils/formatter"; +import Avatar from "../avatar/avatar"; import Badge from "../badge/badge"; import BADGE_TYPE from "../badge/badge-type"; import { PrimaryButton } from "../button/button"; import BUTTON_SIZE from "../button/button-size"; import Colors from "../color/colors"; -/* ProfileImage */ - -const profileImageStyle = css` - width: 56px; - height: 56px; - border-radius: 28px; -`; - -const UserProfileImage = styled.div` - ${profileImageStyle} - - img { - width: 100%; - height: 100%; - } -`; - -const DefaultProfileImage = styled.div` - ${profileImageStyle} - background-color: ${Colors.gray(300)}; - display: flex; - justify-content: center; - align-items: center; - - img { - width: 32px; - height: 32px; - } -`; - -function ProfileImage({ profileImg }) { - const img = 프로필 사진; - return profileImg ? ( - {img} - ) : ( - {img} - ); -} - /* UserInfo */ const Name = styled.span` @@ -89,7 +50,7 @@ const StyledUserProfile = styled.div` function UserProfile({ profileImg, name }) { return ( - + ); From b7a872e791d18dbcecdcb6bf506f0db98ff4efae Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Fri, 15 Aug 2025 02:26:06 +0900 Subject: [PATCH 081/253] =?UTF-8?q?feat=20#16=20Option=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8(background-select)=20=EA=B0=9C?= =?UTF-8?q?=EB=B0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/option/background-select.jsx | 119 ++++++++++++++------ src/pages/post-page.jsx | 29 ++++- 2 files changed, 109 insertions(+), 39 deletions(-) diff --git a/src/components/option/background-select.jsx b/src/components/option/background-select.jsx index 0e0c937..0ca9967 100644 --- a/src/components/option/background-select.jsx +++ b/src/components/option/background-select.jsx @@ -1,63 +1,110 @@ -import Colors from "../color/colors"; -import { ReactComponent as ArchesImage } from "../../assets/image-option-arches.svg"; -import { ReactComponent as CarImage } from "../../assets/image-option-car.svg"; import styled from "styled-components"; -import { ReactComponent as CheckImage } from "../../assets/ic-check.svg"; +import Colors from "../color/colors"; +import CheckImage from "../../assets/ic-check.svg"; +import { useEffect, useState } from "react"; +import { OutlinedButton } from "../button/button"; +import BUTTON_SIZE from "../button/button-size"; const BackgroundWrapper = styled.div` + padding-top: 50px; + width: 720px; display: flex; + justify-content: center; + align-items: center; gap: 16px; `; -const OptionBox = styled.div` - display: flex; - justify-content: center; - align-items: center; +const OptionItem = styled.div` width: 168px; height: 168px; border-radius: 8px; cursor: pointer; - position: relative; + background-color: ${({ type, color }) => (type === "color" ? color : "none")}; + background-image: ${({ type, url }) => + type === "image" ? `url(${url})` : "none"}; + background-position: center; + background-size: cover; + background-repeat: no-repeat; `; -const CheckWrapper = styled.div` - position: absolute; - top: 8px; - right: 8px; +const CircleButtonWrapper = styled.div` + height: 100%; + overflow: hidden; + display: flex; + justify-content: center; + align-items: center; + + & > button { + border-radius: 50%; + } `; -function BackgroundSelect({ type = "color", selected, onSelect }) { +function BackgroundSelect({ type, selected, onSelect }) { + const [imageUrls, setImageUrls] = useState([]); + const colorOptions = [ - { label: "orange", color: Colors.beige(200) }, - { label: "purple", color: Colors.purple(200) }, - { label: "blue", color: Colors.blue(200) }, - { label: "green", color: Colors.green(200) }, + { color: Colors.beige(200) }, + { color: Colors.purple(200) }, + { color: Colors.blue(200) }, + { color: Colors.green(200) }, ]; - const imageOptions = [ - { label: "arches", image: }, - { label: "car", image: }, - ]; + /* useEffect(() => { + if (type !== "image") return; + + const BackgroundImageUrls = async () => { + try { + const response = await fetch( + "https://rolling-api.vercel.app/background-images" + ); + const data = await response.json(); + setImageUrls(data.imageUrls || []); + } catch (error) { + console.error(error); + setImageUrls([]); + } + }; + BackgroundImageUrls(); + }, [type]); */ + + // 이미지 옵션 테스트 코드 + useEffect(() => { + if (type !== "image") return; + + const testImages = [ + "data:image/png;base64,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", + "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxMTEhUTEhMVFhUXGBsbGBgYGRcfGhoaHx4YGCAfGB8dHyggIBolHhgZITEhJSkrLi4uHx8zODMtNygtLi0BCgoKDg0OGxAQGy0mICYrLS0tKy0tLi4tNS8tLS8tLy0tLS0tNS0tNS0tLS0tLS0tLy0tLS0tLS0vLS0tLS4tLf/AABEIAOAA4QMBIgACEQEDEQH/xAAcAAACAgMBAQAAAAAAAAAAAAAEBQMGAAECBwj/xABFEAACAQIEAwYDBQYDBwMFAAABAhEAAwQSITEFQVEGEyJhcYEykaFSYrHB8AcUI0LR4TNy8RUWU5KissIkgpNDRGPD0v/EABkBAAMBAQEAAAAAAAAAAAAAAAABAgMEBf/EAC8RAAICAQMBBgcAAgMBAAAAAAABAhEDEiExBBNBUWFxoSKBkbHB0fAU4TJS8QX/2gAMAwEAAhEDEQA/APQVFMcJhs4I5jb9fregLQpph8WqfCJPMmmerlcq2B7mCIEnQedAuKZ8TugkGdCPlSxmoHibatnNbZSN66tXADMA+RoriOMVyIAGg150zRyepKiC1kytmnNpHSo1WuQRU2HEnSgHtbCDhvCGG3P9frlUDWT0pzg3tqMpYGflQPEL0kjSByFI54ZJOVC6NdaPxVy0bahQZ9dvWg1SSBpr1Nav28rFSQY6Gg2aTa3OAK6C1tIo84aVDD3/AF+t6BynXIJigk+CYgb9agou7hyBJ0HnQwE7a0wg1RpVJ2rVG8OxioTIB0OvOhL1wEzAHpQNSepqiaEyDfPOvSKIwVkN4Tz2/X62oFCOtMsLikTUCT1NIyyWlscXMC2siAOZoG4oFNOIYkOoIPqP1+tqVswoDE5NWznKYnlW0WaNfHL3QTKsz+j60PZFBak2t1RoWtdZit4sLmOSY86cnB5lBPhPOleKKDRdfM0GcMupkmEe13b5gZj9RQB8qya21siCRvtQaxjpbfic1lZWUy7OxXZJG/rWkj+afaKJxIt+GM3wjkPPfXekZuW9AF674WJjQqqhvhzNOreQg/MnWIri5aceFhbzEqLZQFSSTBDKY8IEnNHTUzWzdVFYuJVzkM5oWVYgnLrqRE9M3WhcPcCm4to5kFl2iSwtvBXwMQOR3gb84mmaKL3r++f9f0JmuqQpCjuicpun48xMB43ySI6ctxJy9cVbi2HUDRA766XGAYAn7O4PlttQd6237uQbrwLauFgd3DMAFmZLSSdtwelMLyd4+JtsNX7iJ5MbZyn/AJso9zQU4xVvu38fFK/f0N4i4qrcbu1zLeNpRyOkgkbTIOvQ+9bsIe+W1cCagtNsOpGUmQQf5TlImOYINKxcZsKzE6nEKS3nkOtMsHb7vENbLMxuAkXD8RKF1ZW8iVPyWgU4aYtd+/tX258zSYlTbW6V0LMFVRBckwoIn7rk+wrGvMXKuqhgpZShkMoJDKY0LLDGQBsfI0Ph7wXD4Rz8CXmzeRzZh9JNawjrnsoGD5O9ZiuaApXbUA8m+dA3jq6X/b2v9e4T3g0JGbM2RF+00Tr5CR8/KurA+N7gtMiqzBrekkGMpBjN1mOQ1g0Iz5BZuEEi3cbPG8OqAH/pb3Arad33d7K2dhaOqhgAuZBBkDxHXTlFAnHb1/fttX1C3u5bdpzaQZjbzmIBV5Pg10IECepqe5iHX+FbAN3eG+ECconlmbQAb+JY6hJiMJbW0SF8QFoh5MsXGYiNoAB5TpvR95nOIxBFx0m6iQgBYk5gupIgDL9RQKWOPPrz6qvHxJbmIzItwAMbrKtsNrlOoKn0aNekdazC3bguMii2HyBlZAyiCQsOG20M7dORpeEPdoofbFsqv7LDfnU9s92b6SSWttcVz8TeFlIfrEsfVSaBvGkml/b/AK/JI15TlYAd0TlN0/HmJIDx9iQR05biT1cQrKkIHABdn1VJOggAyfbrqANQL9pv3eDdeBbVgsDJDMAF3kmSTtuDROLfLdurcOXvO7uKxBiQpEGATHiYTG4oHo8PPx7mvw/Qnu2nW2W7u0rgMWJMoQub4BJGYgTEfKRW8FJUvdW1AQOMmjDNEZlG/hYNt013FD3VTIzW5M2X16wyKSukhTLDXpUWJMWnYbmxY/8A1KfqpFBKjqVeLr39RpYssJN0WMoUkoobMDlLAGOWm/lQF2+wQXSlooSIXKwcqSwEEaZvCTAmNJqTD27YzLaa2BldtGZncC26jNyU+MnLp6aUFYHdpZvFi4XdTsisXUFJ/mBQn1y0DhFW36d1eO3lfiM7+GZXa1b7slACTcUszEz0mAI1MCNCTrpLhL2U6AAwMwBkK3MKZOg9TrOtB482Scjtka1ID5nzkQCrjQhiemhiIMVvBsX7kvu48XLN4ioJ8zET70EaXoTf9+/wNX4iQDLbiKScU4h3dwoERgM2/UEgaiGnSTJgzsBFDYni0EgWrZgxJU7cxAj66jaaNxeDRmIdWlYAKsAYgeF5Bkr8ObfTWaC4YljknNbM4wOIzpnKhSHCnKIBBBO3IiOXUU0Lu+VdTGwoS3bgAABVGyjz3JPNj1qYGNRQTOm7S9A7/ZD1lR/7RufaNZSOes3igWurk8+Q+ldWXCkEgHyNTcQxQdoRZPluaDW3qqgIrvEa6EEAgjzB0NaVCNFyqOiqoB0I8QjxaEiDNSmVYB1I8jImgO0/GBagogzOYUE6abk/TQUxSmoq3wFZTEeDLp4ciZdCxECInxN8zU6W2Y+JhJIlgqhtDIkgTAIGnlVd4Fx57lzurqqCQSpWYMakEEnlzq2YW2OZgUiO0jKOpEN7BsJWEykzl7tMpPUiIzcpqNrbqc0jNJIYohIJ1MEjTfanxvqVOXUgc6U3AWMlh7mKCMeRy5QBlMR4cuvhCJlMxusQToNfKt2bS7EKqn4siqJ9TvHlR2NsQx1X5ieXIULFBupKS2CeJJbBHdnUqARAKkdCDoaBVSBAyqOahFymdPEI196PfCdGE8wdKju4crGoM9KyhmhKkmRCUUquwXK33SBEAomURMQIgbmt5nmcwzGCWypmMQRmMa7DeikvEKVEQfIVARWxa80CfvAHhzWgA6jJkSBcYErplgMQPwmuLfEU1JdJXOCXt+ID4mBzJOX+JPnm0ovA8JZrudQkZg3+Gs5oIPjGupLHbdjQeG4CLJABaQHHiFoznyAk+ABjCfzAzPlTVBJw1Uvn/V+wg4+z3RLEBVYIQbXhU6sJXJp8ZMxzqN8fZaPGtzM8DMhIznKdPDp8S+Vbw/CEVUQlmVHDqpyRmEnkgMSZ35AbaGHD8At20CAkw+cMMgacqKRJVtDkDctT5UbBUFk5dGjxG3ObOulsMZRsotkSARkygEbL12qUXh3jW5XMqwyd34QoIOxQLGYzNC4ns3bMZiWJtqsxb0gQCoykqQI2YUywfBc90uNNWb4bW7Ag693nMzHxUOirgrbe3d/f+AP+0baXMma0rjKP8Jd30CghDqQduk8ga6OOSGBe2AoaUNsAALDnwlB9oEGNa3iOFOL4c3XCqyMbceElMu/jA1yzJBrMNwNB8MzDwT3Z+JSpzeDxbz4p1FP4Qi4tNy+RG3E7bjMzW2+GM9skjNngDwaD+G2m2nnRVlhcXNOYNsYI0ErtAgaERQuG4FltujNOYgyii2RlmAAC0iWY67E6RR2Fw+RQskxOpidydY8iBPOKTruGnHTtzfsaFqWzZUz/AG48Xrvlzfeia7RIo3h91VYFh79K1eykzlInUKu8dTOw/vU2ZubuqIbaSa7eyRWWr9uQPHJIEQOZiZnXXlvTu5YXLLakDWKLMsmXS9xDkrKY94n2PrWUD7R+AqIkqJiSBPSTFT37yW+8S2jrd0UNqSROpHSfLyqEJOhprge8YFe8aI0OmnvFBWSVbvj++ovvqy2kS4SXzZoJkqsRBPrr/pSnjfChfUDNlZTKtE77gjoasN7CBJLNLH5+5oF6BLTONHmuR1uN4yrW2ZQVkagwSOetNcL2ixNvdluj7wg/MfnNCcVXLibw+8D8xP511wbBHE3e6RlXwlixBOggaDSTqOfWonNQi5S4R51yjJqJY8F2ytz/ABFe2eu6/Ma/Sm1rFJcE22Vh5EGKpNzhJW9ctXGBFsgHLpmkBh5gQRpUr8NUa25Rxsykg/jWkFripLhnVjyT5aLu75mnaaOfDC2FaQ2n6Iqodk8fcu237w5irQDpMRzp498aAsNOpFTKKkqZv/zimtkMLlkE5i0A9d/pRC2g+gOsUst3JjxSB70xw+KVPhGvU1hDC4tNvj6UZzjJLYiuYMgSdB50E9ddoOPWLZGe4AY+ESW+Q296q+J7XA/4Vlm82IUfnXQEcyS+Jlns3ypkVzmJqkX+P4ltmS2PurJ/6poC+7v/AIlx38ixj5bUWTLqoLhDjiXae6Hbu8iojEeISWI0JPl6U6wVzH30DW8Kqgga3Hif8o3j1oL9nvZ1brnEXFm2jRbU7M43Y+Q0jz9K9NpWc3bzvk8/xHEL9ggYywbakwLisGT3j4abWL5Uyp5VYeJYNb1p7TiVdSD/AF9QdaovZe8WwtsncAr7KSB9AKaZ09Plc7jIcW1Z2Cjc8zy5yaJsWW8LWyLqmdVEbbgzQ6ObbJcidDI01GoMfKulw/hizfUJuFZirD16+tBvL2/rGdy0hkmR1HOaXXyOQgVO2IGiZs5CQX5E/nHWhXcAFmkgEAAbsxmB9CfagjGmuTLKTqdhvG530HmYqXK5AZT65eR2g8wBsPIeZqI598wBWYA0UGNug6S0k+lcXLwukIVyud2GnhGrFgdtJ9enKsXPU6RW7ZJbaXN3ePCh6n+ZvbYevWiluMkEgwwoJ3GwEKNFHQf15+tY10kAEmBtWqVKhuNhWdfP6VlBzWUx6Dq2RRyY0gQNB5UtonAqpYBjFMmaVWwjGXg0N86hW0uUliQf5dN6JbKC6rDRrqPmKhB71Y2IOnSK5pZnGXGy5ZnF0tuDz7tDYBxoB2dVJ84BH/jRRtDSJUr8JUlSOWhWCK57bWyl600wYYT5qZ/8qGwOJusy57YCczMH2n+ldmNpquTG0ptBioWGZmOa0yq7NJLWHJCux3JRswJ+zWcSw15VBQAZiRJ8uYH50+Tha3bYa03dSro2cB86NlnSRsRodt9Na57Q5FW2JY5UGVvCVI2JJ3nSZ9K83B1b7bsY8W9u9fjnzdIaXKKa/CGCnK5J3K6gH670Haw6MBC7+tWBsQoXMWGXrP4Uv4OLwIe0pkGdpA1mDOlejkilwY5IK1pIcbwo2WAZSpIBG43E1JhuIYi38F5/RvEPrt7U57TcTv3iveIVQADbSYE6+vKmdnC4NMOl822bkdf5xyboDXPPJorYhKUX4FNx192uG7dWC8agHLoANPlWhVzv3f3/AA+RcguI0hNBKxEL+uXpVKxeEewxVlIjcHcUQyatns/AmXidV3hcI9+4tm0Jdvko5lugFawlh7zrasjM77dAOZPQCvVuzPZ23hEgeK43x3DuT0HRfKtBB/CcAtiyllNkWJ6nmT5kyfei6V8Y7Q4fDaXbgDHZBq59hr7nSlF3tLirg/8AS4C6Z2a9CD1gkSPcUhjTtTxhcNYZp8bDLbXmznQQPLc1XOBYY2LNtOYXXY6k5j9aXrwriTXe/vYbvrn8s3bQCDogBgev+tEXcfft638HeQc2SHA9cuwpo6cDhHdsfXcWxC6jbXRd5J6elRWrVsqxYweWlJ8Fxs3swwuGe/AEtmVAJ/za/hWrnE7lv/Hwl+35hc6/8w0pm6y41snQ1FY6qylG2OoPRhIBjnuRHnST/ebD8mYnpkafwphZv4nEWwuHwxt6mbt+VEaaqu5+o0oKlnhHe/oFLauc7yx9oSWjy0Bn3HrW1yqCEBE7sfib16DyH1rlOxbkTdxt8v8AchVHtrS499hry4fEMHV57q7EZo/lYcm2/vNJJLgmPURk6H2BweedRoKFuJBjQ+lbt5htPSt4iyVOx2B+gPSqNVerdkdZWqygoypETws3SPrP9K3iMSWIOggDYRtXdvGuFYZzOkanzmKCG5Uc2MRlnSZqV8SuQhRlJjakfFeJgAhXl9B1j8tqTLxC6Nc7fj+NcuRY9Vv+o6cfRyyLVwH9rMEXtBxr3ZzEdV5x8p9qDRgQCNQdqM41j4wbPsWUL7scp/OknAOD3L7FLTFQASfFA2/M9K64TSPPzy7OdBlvirC6bQJ+ArM7DQ5QPSpG1EHUdOWu9IrmHKNHwsp3mdfzqezcxF05LYLnn3aEkevIVUZRV7GMcy7zjAYBGv8AdxpnifICSPxFXOzetz3aESo+EchVTOGvYV0a5ae3rpmGjdRmEiSJ03p5wo2c1y6rGTqwb+UEyfrWZr0s0tl4+w2ZQRBEg7iuMdi8Jatrh2DwfEQsb+ZO/wDpUOLZCMzXCoEiQ0ajQ+pBG2vpVX4tjO9uFhsBA9Bz+ZNZ5ManV9xp1clXmWzD8Os4e3cxKRdXwm3J2kwZ8xIqrcZ4q+IfM8aCAANIqKxjLmU2lY5XIlep5e8xTq72PuhTle291QC1pT4lB28vw96jHipty3f4OGrWw2/Zdw1VtXMRHidiq+SLG3q2/oKvFUrhiYvBYMWlshrhuEIZBVQ2svB2Bn6VcbBOVc0FoGaJiecTymtWJqgDhvAMPZdriW5uMxJdvE2uuhOoHpTOsrKQjKysrKAALfBrC3/3hbYW7BBZZEgxOYDQnTciaPrKrHGMddwmJF53LYS6VRwf/otEBh908/fypgP8feKIzAEmOQ28z5CouF4w3ASYBB2H40RZvJcXMjK6kbgggj2oTi+MaygNu2X1AgToPYe3vTinJ0hyyRjjdr5k2KxWXQDXryquftAdWwXeD4rdy2yf5swGnsTVivqpXPcOQBdZIAXnrNU3HYwY69bt2jOGsNmZzoLlwbBeqj8/QnkxxzrM3J/D3FrTJJLkf27Ry5lJBG8H9dfqa1is51logbkxtBozCYhF0EmdzQfErhLGTpyrsOmLblwBZPOsrU1lM6LNWLRYgCp8dgzbPIihAale4WMkyadEO7K5j2Uph5BCgNnOU6tnOaD/ADHb0qDG4rvCqW1hR8K8yetWW32et3m1ZxuQAREneAQYnepxwNLIJ0XzJlj6f2rl7OXB3rrMUa5b329SscevmxZtFQC1u4hKsJBiZBB5GleOvWlui7hWKq6yU1BtsZDJPMdI5GrVxnEpctMt+136AToctzTXwsOfkd6pWL7kHNh2uNbKz/EADKdfCY0MdRWqPJ6q9VvvHnZfs/8AvGa7dzCxbnNE5nIElVjWBzI1Ow8rv2Y4rh3XubXdo6b20Igj7SR8SkQZ3E661LwK0LGBtwPhshj5sVzn5kmvFFvsGzhiGnNmGhB3kRtTOQ+gMRYV1KOoZToVYAg+oNU3i3YXdsHcyTvbYtl9mEkehn2q2cKD9za70k3Mi5yd80CfrRVAFEwnYW64H7ziNASctsTqdT4mH/jTmz2JwSiDbLH7TO8+0EAH0AqxVFiMSiCXdVHViAPrQD3PNO0PZ18E63bZL2gwIY/EjToH6gnZvY8paz+8O1/B31tXbixdtuYOwBKmPIaj5jarndFu8hU5XR1IIkEEbHavHMfhDZu3LJM925Weo3UnzKkGmioyovfZjhT2DdL3UcuAMiMW1+03n/erNcv92gOR25eASR5x0qgfs3xqriLtltDcVWTzKzIHnBn2NXTiDlpWWAn+UkH5jWKaq9ypasiqPIbhMalycp1G4IIYeoOooil/DuH21i4qwxESWYmPcnpXHFnxKvbNhFdIbOpYKSdMpkg+EeKY12pS038JjFSSqdX5DOuXJgxvGlV/G3eIFMgtWw5IK3bdzwrqCQ6uskf5QZHSiuNdorWHZbZD3LrfDatLmc+cch/fpSKE3ZjiFw3yHdmDAkyToRrPl096svFcIt+zctNBDqR6HkfUGD7VWLXHbRvBXw9zDPc27xAoc+TdZ61J2g4z3CtZtnNiLgyoi6lZ/mbpA1E/hJrbNNTlaVEdPgePHUpWyr9nuGhrCXbdy7Zcg5jbciSCRJHtTc4fGD/767Hmqz86l4ThhZtpb0OUa9Cdz9SaYca4tbVVJUDlpv6DyqKPRjhTaWm2J04B3rDvrt6+Z0Fxzl9hTTuBb8AAAXQARA9IpC3HWJIS3Ouhk7eYHtXdrj4JOdSPMGdadHYuiyR3Uf2PRcrdy9O9D27gYBgZB2oi+EhcpJMayKDB7PcjmsrmsooDmpLZrrD21Ms5IVd435/0oy8vdgEWgvm/iO0mANNNd4olJIls7w+OCjwgep3rXEMRmyuACRoQRI+X65VHiNc4Y+JCJMAeE7aT5j61BisoMI2YUqTM9KTshvXywgrbGsyqgGqVxrhRssWUTZY8v5CeR8un6mxcbx/c25US7HKg6sfKi8J2Az2w2IxF7vWEtlYZQTy1BmNqTSWxGeUa0jrsVxNb+EQSC1tRbceYEA+jAA/PpQmG7BYRLwujOQGzC2SMgO45SQOhPzpHc7GYzCMbuCv5jGogKxHSDKt7x5VxwOzZxBKXcVjLOMHxB7hXxb+ARt93Qx5a1JynpNLr+OuZ07tA9toOYagz0I0pJwHtKENzD429bFy00C4SAtxSJB6TG/t50ZhuHpBXC4xktknwWzaYLOp7slSVHlMDlFBUWk91ZYKRWuzVprj3cSFv3GY5c4lUSfCqKZAgRJ5maCfil0OcJw+0H7kAPcus2RD0J+Jm66/nC7iHaHFWLiLiu5AmM9lzAP31YzHmRFARVum6LBw/s3bsYg3rJyIyw1pfhz8mGumhIy7azyrzntLfD4zEMNu8y/8AKFQ/VTVo4t2xt27Re3na+65VJR1T/OMwAMeW58jVDwAS40XLotrzJPib32E9T9aItPgWl3RJw/DXL1+0lpshLwtzUAMBm0I1kRy8qvz4/HWrwsOMLfbIXL+NMqLzun4Rm2EDeeQpVi8CvcgWNDbh7RQicw1EHnNDC7+8FbAdi93+LjGgqfD4VtQdQq6CPMGqaot43FpIf2e3JuCLOEuOwMNDL3YPk+oPyFSL2zdNcTg7ltObowcD/NAECpLNpVUKoCqNABsK7oo6P8VVyAcV7VfvJWxgHMtJuXcrDIo+yGAOY9f9Qu4eqcOxIvMGazcQo9wyzK8hszRrBgbf688Jwq2cbetqID2w6joJggeUz8qsJFFBDAnFp8irtNxq3j0GGwoLgsGe6VIW2BrpMHN+U9dF3ZrDhHuWWQC+slm1Jdd8wJ1irMqgaARSftArWymLtjx2TqPtWzowPlqfrQth9j2a1LdhOIu5EZugJ9fL3qoYm+XYs25qw8fxHeWQ6iQxUyNgDqD+XvS7ht58oC2s4Vt9BycwxPqTOm0HetD2OiWnG8lb+pFhTaUAm46tzCz16xvptzldRrHPEEtAKbbZic0z8UTpm+9v+tSar3Mq/wDp1IE6sAVMxGmw1jnrWhi7hDqbMkKBA/lXUyAQT/N6QaR0KT1WvugThGMNt40ysQDPLzq0VVuKuSwUoFKiDBkQddNNhJjfpsBVlw58KyIMDTpptTOPrkvhn4klZXXdnpWUHBZLgTOZOTKRz3Go2o7DcUYDIQzMAB4SpB89PEJkTO0DbWhuE2rZY52gwYH5z1FQ3bhZsodipMfXpMVLjbMm4vZomNyC7NALLESCYiAOZ3kySPSgJrLogkdCRRGGw9oWu/v5ipbKqrz/AA6HnyppaSkxKii5xDDqdVtg3I89SPqq1f1xfUEeoqrXeKYLDBr1sE3nGUK2rKNfkCecmdOlOOD4u5dQtdUhSskGJU9NAPX5VD3MZRTbb/2OlM0r412ew+KjvrckbMCQ0dJG48qNwROUTRFSc8lTorA7A4H/AIbf/I/9ahu/s8wR2FxfR/6g1baygR5l2h4D+490uGxOIU3mIK54GUDxHwgSRIpY/CreQqFAJHxbmes1av2k3rQFk5x36MWRIJLI2jbbbDU9DVb4Ziu+JCqQRyMfSlKSitTdI9PoOyaany/sdcTxZvoi3UAyXVDwZBzK2UjSQCdCPrXfcrEZRHSBFc4mxlF8NoQMOx/+RvyFS8WsXUHgCyToCdQP1HOvO6LJgg3hxtVfw787KW3jz9DqwSjFz7/v3r8EXZ3s9Yv4q5ZuBo7rvFymIIYKR/1TTDg3DVsYzFW0LMtsWwCxBPiXMdgOdBdneLtg7jXb9oMLmVWdWEovQLGonU68qY53Z8XjrGRrLGcrSGZbS5SVOyzDESDy2r0J5I41cnXceZJac91S5oeVlVZMKbwFzEMzFtQgYhEB1AAB1Pma7szhriFCe6dgjoSSAW0DLO2sT1rQ7GpJamtvcK4x4MVhbvIlrbf+4eH6kmnlJu1tonDMy/FbZXHsf6E00w2IW4oZSCCAdD1E/PWgiO0mvmS1zdthgVIkEEEeR0rqspllT4daLYe7YaS9l2UecSV9jqKg4SrFzbzFNGPQyBJ1gkCBr6UU2KS3jrwY5BcVdW0BYADQ9NTr1mpuIcK7w5k+MnWdj/eqW6NOj6iME8Unt4+ALZwufQXyToYHqBO8aQp5RpMRFc2sEDmIvichnkT5fFzgab7SBtUC4N0JzWswGmxj1EVlvhlxifDl567elOj03OKV61XyNMrXbsMS2uUt90aT021q1YdwpGgIHI0FgcCtsabkCT/ToKKp0eX1XULI0o8Iff7YT7FZSGspaEcHZxJTaI161JhrxVl2gHmF2kTqRTXA4TPbgiOh/Xv86Cx1tE0HiPPpRd7E6r2A8XiCxaYgnkF6mNQPOt4LFoEazeBNtjII3U/rX/WoM2uokdKC7VY1VtXHRcsiB6nT8JNNrYvUkhpw7g2Ee4L63jeC6KsaAjXXQa6zyqxKjPAjKo2UfnUHZrhYsYa1bI8QUFv8x8R+pimoFY2YvJ395pFiuqysqTIysrKygDyq65fE4l3+PvnT0VTlUfICprUT4pjy3qwdo+ytx7pv4VlDNHeW3kKxGmYEbNHsfxrHHuz+LXDvdvZERI8KEsxkhZPIATNElqVHrYetx48Kj3ru/wBjl+4drbOil48JMHLzEmgcbfDNOx5ienSh1iNNqGfAd9icPbDFWYkSNwACZ9o/GuDpf/nY8E9cW3tSt8bt/r6HZPTgi8iRLgLIuXbjOAe7hVB2EjMTHXzo69YZczWWZWPiyhjkdhyddjIEGtcW4LcwI73v1vNcIXu8hVngaFMpbUDeQBHtUnB8Qzyb1pk10AIk13zScXas5IZMeZNV3vu/Poc4FQDlSe7dRcsg7hSYZPVGIHoRQvEcFiHu5SVtohDA6MSwgiRtoeR09asmH4OUvK3eAW1d3RMviDXAcy5s0ZZJaAN/SgeI3kVzLZZJHjIHi10HWuLo+qeWWjlJc/3lz5k4W5x0T4QrxIYlLeJc3bLuBPwMrbLOSAVJ08tKsOCwNu0uW2gUEyQOZ21n0qv8TOfJZXV3ddBuFVgxY9AAKtFegDhFTdGVlZUd0nludKZSI8Xh7dxctxQw6H8uYPmKR5buBYXEJuYcHUHVrfp1X9eZtf7tYFxbDZzcYTmGwME/l0NRNwy8AZUMNRuNR6eY5UrMZKE/J91is4nvPGCCG1BG1T4fCllZhEKJ1IpBh1/d7/c691ck25/lbmv68vOnCt9frWqdox3W3eTLakVLbcKjKUBJiDrpReDwwCjMAGYE/wAQsogGIA015kmsXCKYIzgN8IYaE/ZzT6wSKz7WN0Q8kbqxXFbrv94X/hn9e1ZWtmtS8AyzxByRr6DlWcUttmmN+nWoeEIpOYnxDZdp+ddI97MQM0TrGsTXJPM1kajW3N7fQyoR8VwN8kFLptiPhKiD5yaRcSt4mbVu4Uu5ri5ANCzbAHQAAzFXbjebMJ+GNPT+tVXiuMti7hnzqe7vKzQQSACCSY9K1xz141N95MlsXHh/ai6bi2sRgr1pmOUMBmSepMCB6TVnpNhu1ODuXFtpfVnYwoAbU+sRTmpMQe9jrSuqNcRXb4VLKGPoCZNEV4T2hvPcxV8tJY3WHnoSoA9AAK9xwwIRQ2rBRPrGtAEtZWVlIDK4u2wylWAKkEEHYg6EHyrusoApuI7BgH+BiXtJ9hlDgeSkkED1mm3AOzFrDE3MzXLpEG4+4HRQNAKcXbyr8TAepA/GuwZ2plOcmqbdFN7YqRi7DN8Jtuq9A8qT7lfwoMPGsxGs9KO/aMXZcPahe7uXlDGfEDyjoInX0oD/AHeU6PevOn2Cwg+TEAEj3p8o7ukytQcaBuGcV79CYIAc7mSZAMn2rjjWHV7T5+QLA9CBvR2M4Mc2ew4tkgAqVlGAEDQQQQNJFD3OFmM+LvJ3a6lFGVCeWckkkeVCilwb9p8GmS39g7gmEtpaRltqjOiloGskA+sTypjQ2HGIvf4FnKn/ABL0qD/lT4z75R50fa7NMf8AGxN1vu2wttfpL/8AVTs53nhFUiGKjvIY03pkvZbCc7Wf/O9x/wDuY1v/AHXwfLDoP8sqfmCDSsj/AC9+AW/aN4i9ZOW8ohl/pP8AoRUGFwmJ71WhwZGYk6Rz56+lRjhdhnK4TGZbqz4O87weYIJzjoYbSolxd8ObF9mS5EgZiVuL1RtyOoOopmmPMn8Kr5/bzBO21kOt103tlXB81jN9J9xU/B7xZWe3/iG2DbHODBbL97L711xFALF3p3b/APaaT8FP8C1vIUQelVFXsKdRkvT7Fgw2IfK3fC53ZIAVplm10BbULA1NTLiwLZdF1FwgKWOVDEiBsecUtXFyCt3NcUkHVjmUjSVJ8jtWruIGUJbUqgOYyZZmiJPLbkKnsVqtinHHL4q39jjL94/OsrnPWVvROuRNbwzBO90jNESJqfGcULkZZUevP2pagZvCgJ1Gg2k6CelMRwy2WNpbxN4Tpl8BI1Kz+f8ApWc8cJSUpLdC0+JLxPBW7uGHeXc0nqfIx15VU8fwW13TC2gDRIOpOmsa9dqbKxIilD4u/cJFpMi/bff2H9jTUVFUQ0lyXfsljMO+Ft3stq2yjLcMIsMBB15Tv6GneCx1q6C1q4lwAwSjBgDvEjnqK8gucLFl1uXUN+1M3FBKnXciD+udeodmcRhXtf8ApMgTcqogg/fG86bnesmqMGmid+B4c3e/NlDdmc0az16T570wrKypECcXxhs2Lt0LmKIzAdYBNUf/AHlxlu0MU12zcQwWtBY0MCFaZzCefnvXoZpMOymC7zvP3e3mBnYxP+X4fpWeSM21plVPfa7Xh5epSa70NrNzMoYTqAdd9ddah4itw2nFkqt0qchb4Q3Kd/wNE1laknleK7GY1WN28lvFH+Yd7czH0Jyn8fSvS+GYdbdq2irkCqAFmcum08461x/tK3mKkxHM7ULwmzeVrjXbgdW1QAz1MgchEaCnRTg1yJ/2gvH7oYMDELJjQep6/wBDU9Lu0fH8Li8FeVbmS4kMEcFXDKRAA5k7abTrFS8JxwvWkuDmNfJhoR86EdPSy5RLjMSLa5iCdQFUbsx0Cr5k6UTguGW7WW/jXt94T4FZgLds9EnQv1ffpAqHAWs+Ntg7WrbXAPvkhAfYZ/nVM/aTiWbGsrTltqoUcoIDEj1Jj28qGR1GRuWk9erKq37OMa1zBAMSe7YoCegAYfINHtVjxmIFu29xphFLGNTABJjz0pHOTVHiVJRgujFTHrGlJeG8buPdto6WwLqF17u5nZQIPj8IEGYzAxOnnT6pUk1aA+fcNfe06upKuhBB5gjr+BFewdoYu4IYkCHtoL6eULmI9CuZT60p7S9l8L34usLozkllQqFZue4kE84P1qPthxoWlfDm5Iuqq90qjNatwMwMfzMPCB5zpFWaLG0tXHgRdqcXFjIvxXoRR6xP0/EVLw1sts2ltZzlABAYkAacqUWLb3bnf3hBiLackX/+v15B9hrjjC3DaJVluAuV+LJHLymfrWqVKzpfxys54dgWutAERvPKoMRZZCVYQRTRMTbvXmaybiXiJGaMrwIjTYwKUYcG4w11M66nkTVJtktNGprK4zVlUIacNxJ7oJaupauK5Y54AcHzj2jyqbBW1tuzd4ty+5MZPhUtMmdidaRqJpxw7u0guZPJR+dQ4jcqRE3DmBywSRQWLUJJYxAk+VWXiGPz2pQxr4hz6f0+dUzjtwCzcP3SPnp+dNN1uQpN7sjGIxBtG+uFc2ACc5ZQco3bLvFVTEcbC3M9kGy45oxB+kD2r2zgOGjB2Lbif4KKw/8AaARXh3aXg5sYp7PJW3+7oVPqVIqIy1OpGEpNls4T+0m+oHfKt0Hn8D/QEH5CrZhe3+FJi73llujof/GdPMxXily5J02G1X8dqxfwtnCop7xQod2VGGVRHhzTqYXcdaWSGlWEIuclFcs9GwvHcNc+DEWmPTOs/Ima57QcXXDYdrxGaICqP5mOgH65A15S62lvW+/sq6Hwt3coSPtZUgZx5aEcgdaixV2wt0PhkuizbdWIck5oYGYiFHLUk68qzVFzxThJxktz0DDdm8TfAuYvF3kdtRbstkVPLnJH6J3rjFdmMTbRricQxBdASgZvBA1hwSQT94/KrV++W+770uot5c2YnTKRMz0ivKu2nbV8STh8MG7s6aTmueo3C/d3PPpTSbdIzLnwWycXZt4iQveCWEH4gSrR5Egn3rONcVwWGZGe4Wu2gQqIZYz9oDQe8VR14DibIt277XVtuswrHLmiSCNpjejsJw21b1VRPU6n+3tVqDZusmSS5BeJW7mNutfuqtkEQigDN5FzoT7+0UNwviVzB3StwSj6sB/3L59RVms4VmIAG9FPwy0LgF0yAMykCdYO3Sh6E9N7go6d0awvE0W7bxSNntZTbuldSqkqwYjfwkajkGJ5Ud2l7KWsdkvJdCNljOoDqy7jYidzBBqp3uFpmLWy9tvtIcp9xtQN21fwwNy1iXWSPCPCGJMagGJ84ocGLInJ6j0PhNzCYIJg++XvDrDHxMzdeQJ0gem9WCq/h+ytruHtXWd3uMHuXZhy4ggg8gI0HLWqnxWxdS/csXMVibgBtC0vfZMwfMIuGDqMu4GtZmSV7F3a5h8MzE/u9hCAZlUYtJmRoCIiOe9L8R22w05bIu4hulpGP1MCPSap+BwXcuyNg7V13DG27vmykR8YIykAsNlBP1E3DcEww2dWfvbclVmFV0YlhlBg5iCCTMg8hAp0aRwybqgzi/HsfeS7ktCwtoKXE5rsHWVMQCF8RAgjrSnBcAK3C3fhj3BvLcCzm1/mzHWROog61cuA2myNdcqTfIueGYClECjXXYfWqvxK2cJeupqbdzD3VsAAmGYq2TTkDmPkDQg00rDsDwbG3bS3QLC5lDBGZpYETuBCz0186l4NecgvblLiEpcQ6wRurddvw60zwHbDCJZVWZ1dFC92yNnMCNAJBmOtcdnLbZ7uIvAW++ctkO4EAKD96FBNWpPvFGciJscRJSzbRyILqNdd8o5Go+GX8jqCiRBEkCdjzJprxdlt6Ig11zb/ACqu3ATJ1MbmtIpNGt6kSf7Q/wDxWf8AkrKGrKukOkcKaZYWyFdQ75TI0ytO4jUdZ35Uuw2JZGDAKY6iaN4pxU3XDQoiI0/E0O7E7JsZcVWcC5m8RkQ3UiJPTr50mx9rvEZOo3/D60dntG2xObvS06REa/T+1B5qEgSHnZrtfaFpbOKburtsBTm+FgNAwO2v+lUn9ovE7eIxJaxDAIqlx/MdTI9Jj2PlXfG7+Yi0oBY6kkA5R5eZ/W9L7NoE/dXbzPMmudpRlsc8lTorbIRuDT3s9h2ALqVPLWfy9Kmt2VaWIEcuWnWtYQFP4iDT7PVf686rJlc40adNOMMqlLgmxuKa06s2UkiIE7E+fnU1i6FDd4pAckzErBAG4296W38Kbv8AEY67x0FG2eIgWhAJYCI5CNNTWDjsj0MPVRlkk3Kkt1e/l7gON4nee3+7JcJtoxKKSI1Mj18p2k0Lx3s/dwq2muFf4iZtGUkanoZ2jXao8ZYctmyxPSRWjeuNlD6hRAJ5DU6e5rqh8KtHlS3Y87PX72Iuo11yRbQKCxMAAED31J9qv+P4aiJbYXFJI+fmPwqtcPtqttcoiQCfMkDemCXNsx0G1VT5N4xpFp4eAyKBC6EEjeevvXF4C3bi5lY7DQH5Uus8VIUKoAArfE8WHVWHoR+v1qK89dNLXTSq2/PyGKbxE6CKScUVWvW0uaK8LJiFl1DNrpIXnymrBg+7LjvCQs8q12mwdh3ZRJE69Afumu+SvYJb7FwxKtYwrZLktbQw96TsJl8sTpVKu4UHBtjbxzYi53dwMQBlIZSir9lTABPnrVexuNuT3XePdtKVGS47FJ3ggEZgBGhNSYji2Iu5le82UADKgCCCNvDrEdTXPVGKajyOeLWrmQXrtwJlICC2YC5mVSWc6kQeQA050LgWwc3EYq4SWDkt4031B3cbHrv1pCHfuQuc5JVip1G/LpvsNK7xKDRiPhP0/tvQavP8VpfUaYDtLft22S0igZmKhyzZByVRIgAece2lA4/id+9le5eLBTIgKMh2mAPYzUVzRg3I6H8j+XvUYuAOQvizcl1M/wBxQYOTY94TxIk5HgONiNmHUefUU8fDXRbV+9Qg5tcuxEQPimTO0aQaqeB4c8qznKFMqBq3oTtFO+9MRy3roim1ubxtrcJbF3GAV2BAnYR6c+Y/7R1rdvHuqMgPhbehM1azVdF0dTWVzmrKYH//2Q==", + "data:image/jpeg;base64,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", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRs13WYFHZ6atXysoIMKKTUF7eHv9A3-iWaVw&s", + ]; + setImageUrls(testImages || []); + }, [type]); - const options = type === "color" ? colorOptions : imageOptions; + const options = + type === "color" + ? colorOptions + : imageUrls.map((url, index) => ({ label: `${index}`, url })); return ( - {options.map((option) => ( - - onSelect(type === "color" ? option.color : option.label) - } + {options.map((option, index) => ( + onSelect(index)} > - {type === "image" && option.image} - {selected === (type === "color" ? option.color : option.label) && ( - - - + {selected === index && ( + + + )} - + ))} ); diff --git a/src/pages/post-page.jsx b/src/pages/post-page.jsx index bee19bd..38396a4 100644 --- a/src/pages/post-page.jsx +++ b/src/pages/post-page.jsx @@ -5,6 +5,7 @@ import Colors from "../components/color/colors"; import ToggleButton from "../components/button/toggle-button"; import styled from "styled-components"; import { PrimaryButton } from "../components/button/button"; +import BackgroundSelect from "../components/option/background-select"; const PostContainerStyle = styled.div` display: flex; @@ -49,6 +50,8 @@ const ButtonWrapperStyle = styled.div` function PostPage() { const [name, setName] = useState(""); const [nameError, setNameError] = useState(""); + const [backgroundType, setBackgroundType] = useState("컬러"); + const [selected, setSelected] = useState(0); const handleChange = (e) => { const value = e.target.value; @@ -65,6 +68,15 @@ function PostPage() { } }; + const handleBackgroundSelect = (e) => { + let typeSelect = e.target.textContent; + + if (typeSelect === "컬러" || typeSelect === "이미지") { + setBackgroundType(typeSelect); + setSelected(0); + } + }; + return ( @@ -83,11 +95,22 @@ function PostPage() { 컬러를 선택하거나, 이미지를 선택할 수 있습니다. - - + + { + handleBackgroundSelect(type); + setSelected(0); + }} + /> - + From fdf876035a303ce21bf63ecd074ea0fa0b532956 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Fri, 15 Aug 2025 02:31:42 +0900 Subject: [PATCH 082/253] =?UTF-8?q?refactor=20#16=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/image-option-arches.svg | 9 --- src/assets/image-option-car.svg | 9 --- src/pages/post-page.jsx | 121 ----------------------------- 3 files changed, 139 deletions(-) delete mode 100644 src/assets/image-option-arches.svg delete mode 100644 src/assets/image-option-car.svg delete mode 100644 src/pages/post-page.jsx diff --git a/src/assets/image-option-arches.svg b/src/assets/image-option-arches.svg deleted file mode 100644 index 1420d13..0000000 --- a/src/assets/image-option-arches.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/src/assets/image-option-car.svg b/src/assets/image-option-car.svg deleted file mode 100644 index dbc67a5..0000000 --- a/src/assets/image-option-car.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/src/pages/post-page.jsx b/src/pages/post-page.jsx deleted file mode 100644 index 38396a4..0000000 --- a/src/pages/post-page.jsx +++ /dev/null @@ -1,121 +0,0 @@ -import { useState } from "react"; -import InputTextField from "../components/text-field/text-field"; -import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; -import Colors from "../components/color/colors"; -import ToggleButton from "../components/button/toggle-button"; -import styled from "styled-components"; -import { PrimaryButton } from "../components/button/button"; -import BackgroundSelect from "../components/option/background-select"; - -const PostContainerStyle = styled.div` - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - width: 100%; - margin: 0 auto; -`; - -const WrapperStyle = styled.div` - padding-top: 50px; - width: 720px; -`; - -const PostTitleStyle = styled.h2` - font-weight: 700; -`; - -const PostSummaryStyle = styled.p` - font-weight: 400; - color: Colors.gray(500); -`; - -const PostToggleButtonStyle = styled.div` - width: 100%; - display: flex; -`; - -const ButtonWrapperStyle = styled.div` - padding-top: 50px; - width: 720px; - display: flex; - justify-content: center; - align-items: center; - - & > * { - flex: 1; - } -`; - -function PostPage() { - const [name, setName] = useState(""); - const [nameError, setNameError] = useState(""); - const [backgroundType, setBackgroundType] = useState("컬러"); - const [selected, setSelected] = useState(0); - - const handleChange = (e) => { - const value = e.target.value; - setName(value); - setNameError(""); // 값 입력 중 에러 없애기 - }; - - const handleBlur = () => { - const trimmed = name.trim(); - if (trimmed === "") { - setNameError("값을 입력해 주세요"); - } else if (name !== trimmed) { - setNameError("앞 뒤 공백 없이 입력해 주세요"); // 텍스트 앞 뒤 공백 에러 처리(임시) - } - }; - - const handleBackgroundSelect = (e) => { - let typeSelect = e.target.textContent; - - if (typeSelect === "컬러" || typeSelect === "이미지") { - setBackgroundType(typeSelect); - setSelected(0); - } - }; - - return ( - - - To. - - - - 배경화면을 선택해 주세요. - - 컬러를 선택하거나, 이미지를 선택할 수 있습니다. - - - { - handleBackgroundSelect(type); - setSelected(0); - }} - /> - - - - - - - - ); -} - -export default PostPage; From 7ac0cfaa04f58d32965118bd9f53189994931c43 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Fri, 15 Aug 2025 02:41:59 +0900 Subject: [PATCH 083/253] =?UTF-8?q?refactor=20#16=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=A3=BC=EC=86=8C=20?= =?UTF-8?q?=EB=8B=A8=EC=B6=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/image-option-arches.svg | 9 ++ src/assets/image-option-car.svg | 9 ++ src/components/option/background-select.jsx | 8 +- src/pages/post-page.jsx | 121 ++++++++++++++++++++ 4 files changed, 143 insertions(+), 4 deletions(-) create mode 100644 src/assets/image-option-arches.svg create mode 100644 src/assets/image-option-car.svg create mode 100644 src/pages/post-page.jsx diff --git a/src/assets/image-option-arches.svg b/src/assets/image-option-arches.svg new file mode 100644 index 0000000..1420d13 --- /dev/null +++ b/src/assets/image-option-arches.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/image-option-car.svg b/src/assets/image-option-car.svg new file mode 100644 index 0000000..dbc67a5 --- /dev/null +++ b/src/assets/image-option-car.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/components/option/background-select.jsx b/src/components/option/background-select.jsx index 0ca9967..f982fc3 100644 --- a/src/components/option/background-select.jsx +++ b/src/components/option/background-select.jsx @@ -72,10 +72,10 @@ function BackgroundSelect({ type, selected, onSelect }) { if (type !== "image") return; const testImages = [ - "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOgAAADZCAMAAAAdUYxCAAACTFBMVEX/r9P/////vuOUzfb/ksH/9H3/sdSKXLP+6nXXs+Xo957h86Wh8Pb+x1pjY2L/m76CVrHOi8T2qNCber/VkMaSbbrpoMz/6dL+uEv/xOL/w+b/tNXTs+K53fr/z+zXlMf/8XGQdab/+nq4gLucXC15XauLd6v/+Hvt/p13Uq7s9P/l+aWBTa5xxvGsiMrQrOD774DW46bEe7aim6qki5/c56CQZ66h6/SJlsqBebx4VKf//8fxjL7/3TH34nn//9db1fvErZbqpVDw6/Xazub/1+9+R6zNvN3/zVLyst3g7v5wY4HWoM7m3u6lksSo1/iRebiodsTE41j+2QCPhsO+qdSciaxX2//pnz//j46/l9T/n87MwNzd8YvgzY//4fJ3PrlzW5L/iMLcgLyDRbD+mDPExKrBaKeTv+3+dZ3v4IfTvZVoYm2ybbfFsdgAwvX/rsSEc7//WI7+5FzO1KmRreLSvJa+op/t1M3StMX4nEeqjMesfMfP6XD/irSQZ6C6iZX+qoa9uavEko7yvGapdZ7Zm3X/zYT/m4yWXGOsiqfix8rOsMTApZ6oZbReZFdstObzt2z11bTjrnb+ho650Mfp0YPPoZ7gsZHxxZWncp7Pk3/6tU/foHDjmkb/6b2zepL/9OL/wzP+02S8fHrFppj217iYU68bjbxbd7j950yoseDZwYKzwOiSXIOeXACMVpSaXD//6wDslFnio62TWnX//FOjodfVqlDHeZ+UeITFj6hwWoWalJSus4G3w3h1K7b4wL270Wa+p7raZG5pAAAgAElEQVR4nO2djWMTR5bg1cJWJTAJJcttY8kgW1qfrLiQjTGKbcyHI7mEiCSjYJHEGFtEDXFM5IkDxjASMYGQZA0RZJhjZpLJ5WsyviWTTHZmd7I7yd7tLP/YvVfV3WrJH8Qiydxx8xKj/qj++PWreu/VR1fbFJRoJuR6WCUVFYg2+EsSnnc+tJJnNCpBJ7jf5nE8tOJxOHkGQZO80eOwPcziaeIxACV+z9/6Tn5o8TRyxRZltodbnygeMmtL5X9khepF58e9ptNlczl/1Gs6tr706muvvfrS1h/3qk3Upjb+uA/31Zdee/XV11569fiPetUfHdRR96rNs3Wrx/Pqaz/q8/1bgMLlHLaHHhSyLhI6tr669Ue96o8P6njt1ToPcL704z7ev4FGgRSt7o/su/8GoDZP3as/cgG1/W1AIWL48WOxvwno30L+Dmpbt4r3f7NsFNT7/6o0bRB08L+tL0c6OoKDg4PhcEdHx5EjRzoq0ocrpGPuyOLiEZTBDrlBSHgt6WhfV461hxet64tCjLUO/6o4a4I6gnu61pbOzZ2nXUokGUuRUi5XIhNKJNNZ3r15d+9Wi/Co8txz72ID1QQrbc3lKWUglORzW7eC/XU4tlZK8JG2deT2628/f9u6YdsplLP6Wt+GQXdtWVWA49yV3fBUSSozkVSUSGo5l2NqRGnHXXqaCtAhnvz4uaee+7kkDbLw5V/dfvfd2+9fDjOWPy4uLhPm8oSxXgS1yr59Fav7f/H267f3W7cg5s8e01e+L1CgPMY0Ojcw1j82Nkc4d8UUJbM8lGdJcuXc7mNd1aBQVRniEQB96ingLHBy9Y1Dhx4TcujQG1cpy2/FoNfRkCsxTlKxDKsC3VcF2vb8620VGx45te0xy+7vB7TrdFibm5/eZMr8GOMZJaLmckEXW14mK0Bb3LYcVxD0ueYo41cf0yl11seuMjpkszUCpSsWQZ3znBX07L4q0LduP/92FWjlc/g+QLv2HNHGNlXLPOExpZAfomRr/pwB+uJrhkYdWw3Qj7TFNyowBeobi6xERcYA+fjjSAWo4Nx3tszx+i9+8fzr63B+P6C7mDq9ghOkn4eU1Iu5YJ33tAn60mtmGe3ligJl9Jp2eQWmQL3MVEXKr59rjvCh9UD3v7W/DRUqDc/3CmoYGFj47yvVKWWaqkohly/ltYUuA7RMiqCoz6urcgLpVS0j1PnUc899HNXL6F0D9e6+fXdX0OwfvhYm7Qt3VqLWCtrVdYXs0osnXwMThbgUMkSPHLtSBjVJexmA/nZNTtSpNqEozcJgzUrQfUfLJfPs2WqapSy5/MtfXv4quzhTjVojaNe5MGs/0iWWtP51QDexTGRZO91VzroguncpAeiv+LU1OYH0mm6Yf62ESgL07NEVdCbKDCMfvCWy+rvvZc9XkdYE2rXnWHahvkfDkreHrZVvdZPEC+ycmcvLZTQfpDSlKCpZGxOFugATDLOy0o9Wy37t2jYhv3lr2yfvV5CerQ20a3e2fcZX7xtmcOvt6rqcmzaN8T0Gp9W95CgBrxHTbq8Pelt7H0mVJB+y2VcBRcMjrU9b+L1tFnk/+3uD9CyarY2DDl6hZNIXqK+v94V3d53WVrW3VuGnVwPdupWALaLrZVyReRfJUxg8ZajHvQK0re3OIkSNZGkYTO557TdW0G1Xs8IkGfZ546AdbDiAmAHfJAl3kfUzrlBpeFXQElWTMe0NHQjK1ltrqvQ5RSH5lpYq0LY7fXfiab/T6SdcW9q/eFkCvrm4KH4/+YhhQCg499WSdTv4jFDnzGL2Cij0vpybprVdq4HmCSjjPSPqQxOyujcNLz73awW9qM1TAdp2WaNxu91td7vdcSej7AMonQD41Psf6DpdDLcZpDWBti9C+ezpyx6Daszi/RUKLmaha7Wsu3WIMqOEHvoY3KUF9K0PTf2+z/+HIpxLpTFqa+d+u3sKno/djrhp9tRvyLVP3nyv8JGZez84b2Te2oyRNukb1sJoSnfdv4Ri3j2yFmjYZDv04YcWNaKTMDL1G9pFMM75KtC2JZ6wj0AdaWqHXQp/6v1r2z6KRb4ugz6VXdBJawLdc4WEmTAwXQvkO3CCh1kDlL0vId8M3776pjXjfqiUi+whAuERob0VoGB6vPYpJeK2G+Im73/ySVgNffSUxSB9kB02TG9N7oW0ywDgu+VcSyGtBO1lUmUfK5RRjtCHHtMrMR8rH5u6vuYC7BRUDSQo1jI/fYSm3TuUKXtZvJRe++CTj7Z98malk9n/IKCntT3yxrX57wK6STu3KijFYP4QaC/GCKEfHcJFRZlE1EOHypn6MrghF6UlAxQsziPnedwuS6ch8YQ3zT/6ZNt7WatKt5HP2moH3dIVPiYaDc59B5srQbsqQfFEUEu7redSUBeAfvqxrKp8eOixN8Lk/XffNK1RdAL1uXXr4GNCnfVgiYh7RNlhrxC328/fIwQ43zc5T10OPxDoOe3K7tNbuq7Q7wbKTltAAVGcCPzLIQn68W8BlP1SMeTDQ9co+J57ulLfBNdBgzkA7fjNqd+cOoW3zfxQQu3Vwi6/d3XbJx+EmanUU1e5HgrWFtR3hdkcI7t2z9UEapNtQQSjIvQrP3+KUBpWyvIYZGXClGZJepvR3JDICR0/e65eD2sT9kikmtNNF69evRzm7INPdM7nTl2j4QcA7TrN2PymOdJXYYvWLq/UAoqQNt0WvSEdybvPPXX5o2YkzBRm8adZgEYwE4O8y6heqAdPbZP58A74FmUFqD3uT6fTzniRX9ZjhlO/4TFt5gFAF+bmAWveZQWd52tV16ZZ3+k9en3U6bCVjdHiIVSo8tQHi4xxFaqeGU0T7UMI+pXhYt5gOQP000fKoJGVWReDJDeESgkq495T2xZVhUgP46sJ9Ir0n6oVrZ/h2vz8vFwpY6qcpJm2u2sVP/rR1TeB9CovxuNxPw8pSlLm3V8ySv5kBkvcADX96AxkXbd7JajB6yWyvhYmilJYanuArMtXgm4a2zQ/F14YXsA4f44ZIdM0S8fhMScYhkeVoCU0tjyV5E68Z3ecFoxC+vM/vfnUcwA6+djqoI/gIVMta5ImmOCk2OYUC9cOumWPdKBqOetODwDdtTs+X8Dn+4xu6idATSk8CVIUT95tZ6DTymqaKp4A4TIFkPKkEhHtYb/DxkEzOkJQG5ZtE7QtXASru0reNYRj2BB2iYG4/AFAu9oHBJ0l0p2en+sTtVSo2JyhqNOiN+GnlBrZKcGray8tQpF2p5nj0lSVzWG/hro2dlV8uBZoH60KjKryrp8+te0DWd6T/EHcS3WD2PQA5yGoj/tkTfWd+QESR7Ng93vNosTPdZkBA/w1xXUH4S7fnisq7k02a8Mvgh66yoYqsi42Gv0erNF64k6zbZdDcmg1ewCNbtnCKoun5sIhviGyMOnr6bkzTGZ5fId44GWT4SZXDFCH27Z1iLiVkWo9iLwmM+6vjZz7Ec9vrQA9ehT+ocW1bZEQ9u5HInMoqWsPAtq12xIUTVOCmBHwD9HYx0QtxJRIU5Wfg9Jognrsds/W3CqgxWszd9566zngfPd3qFiIeH9FmJnbXxsUCj0KpG2fQbC7PujVcEqA0vMPpNE95Xh+msk8Ql5cdgn3EIkoxGu3YrjjTqeX6VnXg1u25uiK2MZNKLl29Ve333js0Kd37hx66933LxNeGjI5XzJBj559hKXXVam7SFViAX3s01obsHebVVGme4XlurqhkppUl0vLGRVApyxXZWSOMqlRwWmHfJgYqVKpn733URhCB42ScDhMGGc0b2C+9trWlyTovqOC9Dz3rk8KRlwU+NR7bY/Uf3rq1LUauyRMlaouxQQFeWEI/lEL1qDb7aRonvuJBRRjeghuLBUQN3nvMr383qwrE2W9+Xy+t9fUJQi2e8usKzj3nW27xu6TeeMsKo3RqVOPPXfqUK2gXbtl8NPPDS9PgDBXyiOtK8rsblOlbiIt1/wu3RjZPG4HRIBF91RLmTTODx26zZkK5+Nbq+W1l1577bW6oATVO5cIWR+UMGGNYuQQ1O22BWrvTSOiqZPPGqCZfG65kEyV6upenFWI3+Lo9DCJLlQEDEO06LWoPcHfPXTVleEFJcmqKfVujKDhXWQcyNclJXQJ81qEQ9X70221tTBIlZ4WUbzJqSizGSwUmeUcQzftBEMrUeNS99NQ/64IAfPhsGlRIAAk9Fc0qoAnnaWVoFsrQMvtRne4uhalO07Ynd9TzGfXaq+m7ZGyBXPkWEaplmgGbe8EK9rtsokuzuZFcH9ky5YKUPbuY+GiXtDiZO5//hNlwmqr1aBGFhjcXyGP/J6RNcppgpI7j/weQqMYMxJvvF03yHUJCmGwxIxNTGweHAwyOgiCiygUZXCQMdxkilwelAmDIoU4N+yoSGdKRxBHrTD9urCAg3UG8c8qcgxPxyCmF7fCRNrBDWt0pmff0Z6eu0d9gbNH2wJtR+/29BzdB3+wUe5oW9BGn1xVftI/XN9jlfqe+ueff/31t2/X9wRm6sv7Tp2ypror+xX2B7ejPDGLtZ7PYeGJVIGwz8cYyTxx+AncdfiJJ56Iwl4UqsrUIIdxYWzDoI/cDfge+f3CkorqU48N37nbFqi/e7a+/uzd+kDb3Xrfgtb/kzWkf1gP/IUE3npr//7nn/cFAoH6wJKGsbKQQODUqU8/fexTPVmb5Nx3NihhJhD06+3bJwqp6OGvv8B6bCzL1a9xH3gTiclSku8BQPcdPdPOWSmfy+WGcrn8MifDPb6jR+vr8Q8UfT67pK4N+umpT03Q/b94HuRtURHo0b78Sltqb29fujd8xyfHQunJdE5To0kmQL/QGM9C2CmGc0SSs4R/ffhwCjkpdc2Cch9Qo4PDhOeH6iySo3yhLXD2bH1bGyh7Mnu+Jzu6Jijcv67TQOCt599+HXIuqDNw5l7fV3/416++/PLLr76iGsEGy2rQuz1sJ8im7dsxc47t3Jn64nCkwgqCHilRB/pv7dyJaJswOS6M4sLAxrsNe+uqJcfo5B9Bn/sOnTnTvuDzXRtbE3TbqceMbPvW68/f9gV6IOPCs/vqH0z5wz9/qQ376gE0YMm6nw4vDOqgqgRVU9UGv8C+2L59p8H3oKBDKzhB8tlhX9uMlmWLPl99YDLb/+RaZdQonyLbvgUovknKvvyHCvnDl2qPD8KZbdseEYnvnv2MZflihw76Nai0fydzVXMi6Q8NWpfjfX98PwyWRLYxhLNzq6H2Dxu2KPDW7ddff72nHm1XFSaAfsWz4d/+CbL5ITROPQtZ9s6Mz8y626EgjpHCSk5Fcak/NGjdEB/enz2jKyzgm1maWxcUyyj2nAfOa/9YzfnPYTYz2UezvPTe5YWFvnaND9eDKd4fxABr9PDhwwUIo9TVOCFO/nxUT3QYFzbhwnbROPB9gdbl/sV3JjtjWJqexdXKqRVUis/15R8qtfnPX2mLM4GALzBzfmFpMRxe7DvfI57f/qDhKw9TbN9eVWKs0tjWbnXXBK17gbQtLUmVBu6w+2TdNgO0/Ssr6D9+RT87IseCgMoNv6p7IxP0iS/YCkNkCHpYyffFDwVaV+rr65OgvqXV7a4BenbfPknqm+Scfvmv/wjyr19+Rbm2OOzzVWu9fgXodm0NhWK1TOeLaT8Y6BCl50XJC5yha7mXgOEvBGhgRlvqeaedMI1Ttb3vs8metSirNboWp6JoX0g+9vUPBlqX5zO+mTN3fL7zZB1QGboiqG+GLQYwhwZkPg2sTSlADau7fSy0NqhrTPogMvrDWF1hj+gS1Zi2tH94NZMrQY3ItS3gq38nu7geWTWo6V6271ybU5ntEHzsc3Avt/p/GNA6Ojf95Nz0nBZeIzQqgx71zSxw7bN1Vbg26FhsbdAkN/zorbll+gOBluZ/8hP65E9Gx9YIdvWs+8d9/3aVZOlnPb61oHrkE6jIyxZQ18r6vqWQGrGuNnfrB8q6dXmooLHVGXVQKImTfeFsNrxwx7cmpq89OyM4JyctaaxldE3vAsLmZSIzMtr+/YO+OPaTJ9ewQxK0b0mbXAovgHVdx7xCWEh6xG8fxFpm0NhTtrpfrxLnmhL5oQMGkN6On4yuYYckKGuH/LoCMqBnUbBPeoecrkggXZpBaww2uWeYlt0LX4NR/FvgXwg+PvZ9g5qbevmTm8p2aBRL6pNW8MoWBlOBfZoIHQNnwnyhcr9vkmjhheHzwwuLWa3jfgFDQZNd5hlNBIpfEPLF9wWaK2HJpOYqm/78cyT6HALAJ5nWPzpNOW4YfbJsjCwYAaNITgYkMD9T5UsDvna2yDS22Hdmppx1D6uzq4GqTN+sZg5PIN8YVR4cNNeLsZCLlZbVFMvlidhG1f5pJKLawJiWuVAIhy9e4APzqja6Cqjv3hkjjBUKheodhJDv7K8k7dHOyIi3x6y9HB7tX7XyEsOXDVBmC1GNfF+1lxJly+xG84WL15ubr6cydEiAUibyq3bh4sULzbrcWLqYmlsJGpjJnrGuglYD7b7AmSVfIGDRK1gmLLqBioDhlpF3kxV52FjJQGW1QL+HyCjfmyupzReuGygXLjbf4LkSydGrbHpubpoUDmRUcy9KmI6p/ZWgvgVawUl8vpns8MzC+Z7znw1PmqiBO1D5e+v51wPlijd4jjndwWhU8saSVmCCAQWff3DQkqtww4rBmNp8vXDjOmV3mFq44YKdGlWtKZqv30gNVIGqC1ZPup8sLIV7hvuGlyDCZxo9b+z0aed9bz//i54K0FuaROKidT+iMVbWaCTFcT4xtf+BQYd4c6VolIpfQojrYuEALrq0ikfRfPFis/ZkBWiPNEGm1fHdmfEFfDOU4CCiuF+D8or173pfeMGHGrVm3Z07R/VMKhxNhPFZJeLinLsiYHPTfj8lDw6aI+z6gUrQiyGRT6+zUHPI5bpQiSjLKefXlzrGrE0pd7I9FpMz3E7CS2d89Swth2+4E/yznjvnr00GfH0MmwrrjXbdJ0ST7ZFqBxPV/HF73M8LDIf1uP2EffGAAUOu0HyRrMZC6fKFjKs5HKaFFTsvAmhzhg5bjYxm5lzfGcaLTn9aC/cxo0PMS7VsVmu/A0dQ0XBhrXhv/2KFJy00TrnxMOAUx6eNGviDgHKirUDJsNxyoZlkmtv/3LNIUMMXKkhxS6oM6pvkxCyFZ7JFMZAvrsphZHjDfGFycka42sBkFnCtIeD27Z9X+5dZv+xsNcfBxOkDgubYxWaVlS2NS9oatZSjhXvXycULS4G7R89QF+GMuy4037DiHjNAA77PsiRstBnOaH7z9vQFNxFeRn8Qi4u++m0VGv2cVIG6nJHKEVZxjskfIGA4kkGuJcLVe9cLFy6kLuJqmLNlsAPkOrlx48zd+ru+dhwCaHfy69cvpJjGXULDKfqOHrhOqtnh89QnmQOTaXf1ODA3Gy6bZPQw2049FRwF2S5CgNFNWrQKtLEalH0+R0khivEFyMb7XprBEF2gRSj4aXLhxo3mA9cLmpqZnYgI65da0s4evXu+vejGVxjccbbE/KAlLyu4NH71L0GycH7yzALDWP181idbgLNZ1r1i0FF6UUaI8Fjw7bB/P3XqZ0Gr1e3XKirfEZd/qnJkk5fyTHQipH1dq9U9AjokYuyL2x9uvnBD5amyXYhqE2zhz8MZlzuiuOXl4nLIH1na7/vzQm8vYZyHF2ZExwW4mPOL2fD5mc+0ZPVgmjhl79yB+vfM+fae+sAwqwDFquY8Y6mJZCQSSUYzBcpI1Qgtt0r0sYBf1wjqdRJjNJObMFK4Tqz2bzaU0WbUZppQ5ChTi234t7uBhX9/G0S0hrXdPZOFeC+7NAmZ2RfOrByU6megap7VlkS0+Kdq0J3bPx8jogucll7M1dUR54gl74L11Z1sVJuuDRTKnlcfOuD2Fy5cJJXtNxlWAt9zIRWrum13sTDpA1DZs1S/b9/Rq2GMYeWLi2R2xVhNd1ybnDx/ZlK0t/job6uyrh4LzGH1KSdedOMknZgynyuHMpwhSqyguAZqBLU+NjUjhqIkzUgTgvscu95ccFWBJoqkeemPn/273vELoHeNZn10NVCRXAGaXixH9772awBqMUYguEBorpcECSWZaBKysKqldS9aVBUxENOlKVFekzGqAHXqjVQxaewjs/RFeL6L95pThdmK11LcBNxM+I8L79x+W9bC9u3zLfYZ7QiTvLhDUapKaUKbtEYX4W0/s7oX6SJnl+sIsFKzrSxS4AkcVc9YNJI1toom7Y2DyiH6UkqGjScTyeisa/lFksv1ssnF6zf8EcWaMAERf/OibwEbx3xtdyHjHv1z+B3ZtVK/oKnEPqJMuSuktOSzyDDx6QEDeEZlu3SRSpRB4aQvWoOHKERGfhqztrXw2kDD4bDL+Os4ootKKSUknRYjX451dLQPuo4Yk9ZgyvBgR/uRcOX0NINh/Tc42C6mvznicskDxC+pmMomPNje3jEwMDcnLge/AwNHxOQ6HeGODvWIRWB1UB3rsG7B1Bue/aajMO5SC4WQWhgPqaHxguoaH1fTx562CoGNcodamVpNRaOzCZCJKEjro48mErgQxYXWaJSWckIIiUqhkD6K6WFndGIwl0sk8K9R/HkT3lwjbGiUG3PmRm/1xgRsDG8YtLu7e7xV/LWOd8u/7vHwzcfL8jINiR2tj5ZTytSumBLZASIcUmsxNJ4QSyM74D/s2zQa26herS6ouBNElL/B4w0tLcePt7TY4M9eZ4cVKMpDjvLGRhIEZ9MEG2zwB6kbYKOjDlIfL24YNJ1ubR1Pd4u/7vR4a2s61BoiFs7Hn6awIwQ7iq2tRTM1sKbJhIWTu0Iq19QJBTdNKZGImjcbwhmOs4sRSjmJj0hOZcegJDoON24DTHtdg+r0siDJGfwlVgTtu3gvsNfpGxvqENXeEtow6DiwgZZaxwkJ6TptLXZYNXqStOLGVj2lngMwpavb5BwhohE6WdCIe+TRcUDmNCcgS+AVS4SHplg+N5QrsUd1zgrQFxCUEHAm8RDvbXEfH3K3pIPoW6YgTgCd1h23gL5QC2h3a0hoieZztDiOmmotkpMmJRCHVSiO46jTIug0pOsUte9KmJxuHjWiVE5xxqJklIlWGpKnZAjb2Up6IxzROXdUZF1PXcs4FfGBEuMERwcSLpxxi6KofmvWFRm9hqzbLTVFIJ/lgpTQECr3pNTozZe/DRO0v2KYIykWMWUI/0DB8IegeqlMlB2ADDqUJIIOBYdyQdHQmAv2yl8xZBxzQscLuj6Pv4BaaiEZ8YbCFBTuXjBh6E3RAbdM+dOYcYVOIWUD6NPxwsZBUUvj6VaRz3JDdXm1CDmYCdJvIUQ5+fTLAHzz5uMvP/1tByVqWZ/d42k1YXDuGKdKlUQ4ggV787oq4WnhhiEERc4RyLoNDbo+j7fEEyymk+1Ik6FcHk6oR/V+mh73OipS15B1Q6jCUCvJGd0QIVBbCEifJvTky9ayCtkY0NPdoFPCQMOMDBpWFkCra844CRWeLmjkWZLDXCM0Ks1V0N1Sp+uzKU+DQVChThanQTh7OQwrlWCD325ov6HGMjoudGpYyOB4K+qUdgDm4ysE8XHv00+//PLjN0/OGpw7ZlcOQ3AJwiG9h2OI5imOxutlhlkebAAt2UBLCTVI8jnITBhm4ptfcRbfESGimcIN58d4CU4TLNodDVKf9uOuGkG7i/rIx14K+gSzSoipzb9809T0zWWT9VuaNsrwyZjBqSRXdiokucwlNC97AqRqSWhEcAIoltG6urgaLOVkKU5gCYXY0UnsWFeJJ+K4XiB6XqPBXqFTO1jpfG1ZF1BVcRu9wXGRdWmHCdbUIMT2FzOAIIabRVAzAHCtGOSW4qhCqP5AhESks6nLgbIEpxIJwg07WpxBs9SUILeih0qraTtGuWk/eF0o6+awzHxQhXJqtzfUVEalMWrtBv+SpxQyLuiThk3Ob4BRSINJanofADU5M3xl11+GoweNRUKcEb2k0oLOqUwNulteqPMHzbACdvrtESXZGi+q7hYAxfeB7SORIin39tGSKKOe2sqocBhAR9UQZluMHcqlssEmSPEfM++aoUSsHNBVt25Jy5spZJK6DS4Jb6pGuc7pHrTZW/zBXJlT5N2REbu7CRtJvcYrnHFrmrpev6PF02KrPWBAlwHeUQSBtGyG/hK/fLMJYJtAs4ZKzb0nEwanUlxj1GK5xKqcMRxHzrsFp/SjQ1YGYrxzOLIDKqFOYjSVpkt11qdRsoNON15Gx6uCAIj2Uk9b7GzD4wL05Ztl0McrQAWGGRithxoTcx+m0BFhjDzo8R+3EEBwoTcCTClazB0n/h2yJQVcV10FadHT4tm4Rosrgvr0Sav3/Oabyw1YQG9+E6/mFKCCYWRlvLA2r5aMxiBYd3cUg5Xd7cH4DkEWUQgj4DgVEUBEwP7WVabL1+ZH9UC91QjpDVtz83GMih7/Jm5Dq/tN/JuVoON6gD5C1hspZJXIrIuqRf94KD3bQXMVACV8zW5EvgaVgyAwCPkcPKsSqR4Nnw/GHyCoH3cRglWvULdeQk9SrrJvbz5+85uGb76BzHt5BSdoVHLu2PEdcq4QF5mNuIQnjSiD+YrbzwUJtrTa40Umy+QQYRmwTrOsVFclhNRWRrtDUDuhpd6SH3UaQqN682lewMlmCfjTl/9y+XLDzZWYesCAnPFVfEu1Ks2llDqCnJHByruHeIIw1UXLfrWulwTzx1m+mhNKc6O/hop3NyUQtuDpesGNthKojN48SfQWzwJ7+qbIxo+vgipA0fAm1hgoVJaoRs0RCWQE6wJVoCXxHmc+31tRbo2Vyq11pfTGQbtFDW0oL58UlNX0SaxrA6J+h+zky1BzOdkxyBjmZIvcRFBREYmtM+BWf2CUisA4OptxkYR4ibwCNF92lrkXS8sMag1suZQ3NhJa9cqM0tkAABpWSURBVG5ODbHuOC2fgEJZVU/efJlFlImUEdIVGEQSmVgUghYyaEC+/O23Tz8NoIJTid3X6GaobK2NRZOudKzAJ5QRK6jJOZTnrtmoPnghGSuwkiQsVUQNQ7SGxrFQ2XiDRrtbAXRQjAKh6sqCVzCiom/xXarBWcmpRC3V7tWHpCY1015JCw2RkZVTN6wlWn14VAbhkCRvBd14c2daLYPKMnryZdQPvv62SslLmTq92aGqCckJGCYn48mVRwn1GAti4BvYozJoXlZw6obYyhFkUSUm2mTgGZStVK4GjYK9NY8nxW5sGfsWWyczOM/UKjesfmuCFrEpZUSoB4cgCP0XKF3PpWZSmRC++oEOxgQFhF7JmVRYlf0OcZeSZPLminp9DpbVWvxo0fBTeYKx0TjpmBB3TOhqbxcluQFKQgAqOCNxphK1gHlzlpVBk66+xSr/mkzO8oJKC24EFS0rvXl745BsGYWAoUCrlMoI0MfwDoPOlgTES/le7IcaqqVxrHvcKR5oLjguoiMqJgKY5XQV5whbXEYkTMddCcGZYcW0Ofw/VC7ZxOfrWfFagIqN2Ani3hEZhAiBBIP+loY6PxrEnAvnraWVoGAJoNQyrCljY2fOrwaDtNhUV0PjWBrr2aR3CDhlrEvkjAexTEVhmxVWIgsLeoT4NE2rqLwIB72u6kgLnw0vJpVkxvySJIgLMi7k25Ed4F68/nw+YcfmriY0RrkMTqSnF/FYSh/CKso8xbpquVW/psYxWXsJkSAL6bWXEJuNqpzrWTCiquKSSahwRlxkQonq5ugkGVcRfko0AQlFVOcANEAuXvL7S1zXM5GcWBeIBC0N2CXwk7kC9hNKqzvxWc+iPEcsimMpoBy7zaZR2wM1YEOeFfpEu0uYPx5PyBfGZnsbZFUzSTijqZgBevNkqBVnY5ecYBonXK5ygUwWCKO4jq3vOOKIoCWfiLhMTux7sem9Kcdb7IQM1bFyFoosXrYYiNSL+WDCaOx01N44hrXRYjf+jRcJCXUXxYgMt7sINzebTJGJ8iUnImbWLXQjqM6JzesWVaZ42pnwFnmhQMw2S9cEySYrOplE49gLsrmrgdDeITNKVDLJyEQMLD/HWdqSUGlLtLxgacCuqXGsWG5fUFna6SeU6hO0uCE/JleM65fG6GU23lpUZScTcLpcrfjxT306tRRP4DxPoMfy9D1xyjIRC6eyYxDwQKfYhAmlzl4MkhLTLXY05irEIpQk4nEnD1FK4jZswLYZ+qy5AVs0eHarMpt5i4YWcOqlGC2oVmVFpHshaiuAZgx9zk7tSGipiMy8kWzTiD4SIF7u4CdUjVk5d4jGsbKWPC+kcUbIVDRZ0CjUY5JqUR/pQ5wtLWXtP0DjmMRsHedxYxoqMSEfzmgBd1Ry+61hmQgYXiYEjxCdTLKpCwxpnGrSNUTsK0aOYdaNZvi4hXPHYIPH3uKwieZL8ddyvIioYqI6u5/rjWPuBGux2UXTaItHT93SUGsDtmhMaTIndXGm006g9aIq1bzVF6YGb2I7oGr2phmcO3ZESYazAgT/1DtVPVTDHkf/M8EtnLKTySyjLzha7CK0L1Gv4Isbg4LijC03tgjtG6lrbsAWjWPEGGcYp1xVOVgkv/AsVndaGHz85ZOEhlCfrSGIdcucEYgvIokiAcfUtHLKUeloweWanDsGPS0enA7J0eKx27AJs4h1sRJNqdR6ZJxnkrOsCZZEapGyxV5D45ihzzRx6sPvxJzzEZW6wc/QglFpQo0QCpSQbYXp6k6riTKnkplAgJGRkShzrqbRiAA1OUciwXIZFVrKoT5z6MtSlom53H4ReZdA+y+Y2q+xjOoNnqH0DmUHZFinDP0irAh1sqdPQoUblATCOVRo0vhgzP7R2TInCpqakVnuIiqU0crRN3JKOfnGjl63A40iCWgI/wO9OoOloRL6siSzHJnGLbN5fcydkbYGq1tQ1VDBReAv6IzFvN6ESiaEgFX/FqvXT3978qT4itTJk+BlVSJTh4iroKYgmRiWMosHdONSLHgkOhFMTSQqJXwEEqQoJhPrExOxjt7eRKI3l0g4X8S/xoQ3PzhIM5AiQxLm17QSaTxS9Sdy1tQ1jEo59gByREXBz6Kr5SVccamDHR3GJ9M7OowkMp1LX+sY7BioWTb+la0tnSAnLnVWyIr1ZyrXO+X67tCja0gaKib6Tgi21FXTDEbJ/b5csbZsfPabPZs3nzhx6ZkTJ05sNuS7rq8NOi5mIZLIOARitTTdg1iXkZPXjW43ALaPmkvrbqoN9BmQS5vLIN9xvRp0PB3qLiuU0HHUJyJTsXm8GKoGVTJymr7th3WY0cMGzHqbNh2uYT6jPfLOLRz3X98MoJtXgkJYQ0P6EkraUC0id6tUB7aCKjHxnatRU2nm0qhlaeWm7RserytAL1269IyV49IlLJTmauelZyr3n3jmxCqgAoqSbgMP8m63XABQuSm0AlRJ8oENFU5datQoljsTa/OVRZ7VyO49ErXzXN9iuP2dPZ0WUPm3GqigKurzhHWr+sJ4SO4rrgRVIoRUf8JidOXSaFWS2kCt0nmO0dlkJDLhyu4Gts5dREvFJjKqWKtKuiooYBFdVHNB35VeBRRb+kT23W5Yne3b58dUyiA+mRvTP1M3alokPdWDgp7oPG2OdE6yY50nzhmrSXpE1+VaoHo+XU9W0yhWP4mmjvV//vnYgIpzmaoag8AzmoxOZApUI2PTlRbp+9DoiUt7suU6WUS7csnyOgrpA/+5Duij9wddpYzqj3G2gKFEajaaJKxgrUZEZok2ADnXtEM1Z91K/9hubcuN0j5LA0Mku6fKn1aBqvfjFA5nVVCLpFY0skbVlZPmbxzUkhnBi/xXtuIyakX/Qug/qvzpf1SChu4LutK9fDeJaQNj8xWm6cGy7oln/pfZahLBr45msFMiajTuTZBKf7oiYLhv3n20RlBsH2PsC6OgjtYyAaIV9NIz7xitCVHOeEyJqUqEMn2yaCWZlf5zLdBHN1JEVwONrT05TDILUVTB0Oj2GgMGE7RzwQDF+1KVmEt8vUXvm0hmOy3+dhXQ4gaK6Cqgsez6IyHAThlltbZY13Lrp41xUVSAzhLsbDJAo7zSla4Ava+DWRc0KTmfHF0bdZZRdDbT8/1zNYIaetqV1U+Z4ZRHwZVDiEaN+b8z7SboiVVB71tI1/Cj+rMV71Ic/OlPD6+j1ZjKOdeYuuGKtwQ9YdiYTvMdvOhsUolwWE3OGi319IoJ+kxNZbTC7HYPFip7seTwgJ+uD4qax1kpUg9QH91zGgNA61vlrmOnLb1kGWqoc436aGhNhVI5KF+oFCpzErRjTqOpCfNyTDzPJwB0Bdrhnx7ER1/R6VELKFRO/vfwMaZppzs79/SVu3pcdEvXEXMwYwF3d+r+VtTTqkEBhElBNonIkE8NFVKZzKwopUU6xrqlRjdt6p+jOOGcquI09vIyB3+6Xfxa/bmena2jtmoB3dUX1jTSP/3kQF/nrv/ctTsbiiUjyYmC1o6fGWvXUtEkroV30YVzp2UlZtX6KJiiAmSrJAiU66gIH+CpubgxZCWFNdL02KaB4jhh3Qi6CQ3LfD8IhPHK1MjUlAESCyHphAmKFiqjPhBo5xXtczltz3y4s8/V1bVrd5hrPNwnvxrWdfoY5Tx87HRX1zGwAtoxodJLq9ZHzd7qZCop/JLoeTRzyCyAjo+zTdOcANejg+WmEVjqV6dGUAxNporFtEt/O1kHjViKVS2guzR9uspRbTPBr//u6erCz68bn5iSa1u6FrREpCVOXJ2bL8n6axVoiFSMnSkYoKbgbNehR5f7N4GHmGfdgxWNJPNMgho6jXZPTaX15ScOHhS/rJx3ayqj+uxEP3lSO6ed6/q57ZVX9myplr/aXmGN2Cxt56fPnd7VWW11u4sQ0lcMSHGJrGsNAXCgC3Hh93PmVRaCrFvRWsKjkSkQ48lEQlM7LHOuic2u8viGWkA7w/P61FrknrZnyysgf+2q4vz5K694meixcKc5Z9qRLZWgIVb0OlVq7UzFqa0r0YV1EmCsKI1RRX1EvK5e7tBSp9KCLlpwFVqnRKYulF+0rwm0bwy0Odo/x1k737UqaNfvXnnFSSLi/Zu4F78EQCpAx/WZWyzjWKIQhrdT61ClmJihfLqfDWzq714JummOTPCoy/QhqaJ4SCrzO/2EjACqEiLmJyBqKaOdV9gYWPnF3eeuEHK666+vvGL7sKuCFAzUK6806qByNhsGwUO5PqrKKVHcpKxSCBwnfe20rGR9JnbGYmzTJtJtgJqNJKPbC9xlDKBT0KDhOA01LTpx/BRVyubnmW7wNg76X5s37wn3nd61ubPz0n9pi8e6uj783Ydgai0fd95z7FzXrr/+C7OXZ4BwFyEcFPXRbhXcpj4a3u03osWISvkZX6CHEyoHtUTETOzgXsZTEd4/DfG9AVpurD08UMDxrvoJeDrNaEF/g8CdLkxFZvErFl8TzRVL1maMNuuBwOYT7D+0XWBfge4K361/lbRrN0dT3LWFJcqTerj9AIpZt5sV4/GE/mktt5fizALRWRfk2wWceeIdwGOkUFCZ0QJKFFeIWcqopZFkdAwfk6pigwoT8+d4WcJtdiRHRWP36Oj0GNG0jfe9VFTTju2m6hbJt2U3fqMHP3xoEPcRS68lWZCg+htkJih+JQChaNjnO3MnUC/1aMSGNAQKTT9qRkZWmZ6f7sd8PsFTkB2KI+K85Y9d0Yr2lPlaay86KKUsTHbpYHuOkXO7wu3iOyngSE8zZn70y+3X9ghj1M1GrB9r8pvRLp/xnQ+Ret87lfEvKrTbCOqt7bcD+IkO+dkrLKSt9qppZdx0YPp7a0rp3MPZri3t2WOnRbwAJqg9fK5ThA7nroSzC31ULzD2YvZ0p7S6CetsPO60GcUv+GZUJbrg62EVlZfxTNJo27UGDF8wFQeIZag+HDZKdlQODgD3PQ1hxYM3pYj65TmVQcDQda6dc7W9b/eVK6dBrizsboc6INkNmmVFyEvxeFEjImJAjZKK2XiKFoUuwK1zn2+prFI63k0yhkJRoyaoYcMM7zFRCeqONzmp2aSLdqvWphRRH+3s43uuQEzU1Xmk1JsvQcmCesiy6grlc70MA9+uc5xSnu07fbrTrI+ypvJIG0vOZcO+HsilkwELqDqOA4nMxnpLGR3Tnac5kDvJK7JuibpcrPJLzbV1G0JFDXW6hR3rxPJ4hR2vq/NgENc7lKdJBcdmZ/cIC0XouT2dJzpPmPXREI0rivHRKdatWlQ6qb3jC0xyS84VuKuAGoFiyIz5iHPK/GaX2yn0rT046CWjv3OX1o42l8UA1KYHcWxWeaGuriUKKu06RwhW02R9VK94F5nTPiUHYhVpubeFhgP4AY391iIqpFgNun3TNNZKUtRa4Yzy+JRiGHOvywo6Wjuo2f/ZuYvwhS1XNNQhglKSx5YjWHMo/3lu17HsMaMlxVIfHYfs6EzE43FnhYEFP1of2F+NaWkJ1EHBwkxz7FPDalg5XsywuPmVWYgWoOqjDwPQe4NrAzX7PyEc1M61pySakuwdqsuNK7h2XCmw7JFzeptRVX10PKQSvanEIhAZ3aneZu1PK4eAqFEETVrH8Ge40ygREDdAAKL3LW6XBmzjxmjX5i1bLm3ZcmKzjPegpGpRXaP4UzeiKPjyI2SmXZv1NJj4xAlIa62PrmzTZWG+Yptl2IaljJJZfHM6Gqt48z9KiB5wedn8dPW3mTcKautY5etXg+J7V7ikf94K1wZXSTnYseJrWPcT6wHlRXGRwcpLlL+3Vf3hLSEbBX3IZG1Qx/+rslHQh0z+Dvqwyd9BHza5L+hqVuw7PJjqw9YwhmucybJ5LSt6/0tWyvqgDo+nocHmcchlm1yCE3r0HwckEOIQaY1F2NHQ4PA4LOfRT+MRtyMOlZuNBXmoPAI26UsO/UDj3CDmdcytDoclZW2gjoY8fqmSNAKYw0thqQnuoZHhL/6UbA0l0UdW8no8Xn3GVKfD01TCz4vmG4zzOvziNE6HLc+50+Pwwhlgp8cJm0tigYqeNr84wpHHg+Wx+oG2vN4Zx0oNxmLJZjnKuFPnmqTrgTq8vJCEqDpG/R5HE49FIhne4Gjg0UiG2fDH5S+5oslkMppi6QYWw96yZJQ3NXJ8ITBZ4PLEjgaiRuE0E2rJr0aSQa+NT0QKJY/DSaORSIE4ABzPkpxwcS9Qp9VkJKnm4eE2UPxWfSRGqCupS4EZiy5CzaM8TfqdEjzsu4E6yv80ML1rKMIbPCXRfFzIe5zYRefyN6o4rMroKoqUv1hXKBmVxwneJM5jfrRPxRMW/PjSTIR7bLJWTRs9eaNpOgYPsonrl4QDjeo2KXfUaEYXXJKXj2oy3uiK8CaZkR3VZbYSFHJdY5NH/APZQSBF8Z0P1mSTfQpR6kFCuEqvC5vYETQi5qNlVLwcEklScVExP22qhHm+EXtBI1FxRzFsSddBvVT0EGXyAjQiTgMPsld2sqhOj5MYB866xO4I5qmk+IWswMpHUWLcqepFS9DU6BUoFtYKUIdNpSWqpvEfeCD5zIEDNzR+78AB2uQlBw5cbz5wgDc0hg+ALDEXbGAMNmUZ+/jAARdhGvxoUD+E3QXO4eBmjgWQ3Dhw4AJnGqTn1w8cSDmbCO7y5FMHDkCiC8yTh0vcE0fACrkoNt8reSgsXdcYExfihQMHLmqMsgsHDoQ5GgOaMY/iKUyJiwImHSxRIv5pWB3UI174F7PY5VWPI7+0d++HLs6u32NNuLx0fe9el7MxvBfkAHPt3XsBQPfu5YTdg52UsA/37mWEHtm7txnqmxzWxKk5pAlDJfTC3nsczpACm4EpPBRWCB7flIfj71GiweV4g/bh3gMaJmjAMxBxIJycpvbuvcjE2l4EhS2Wo1LyTi/eY6BK8Wp6r6Agq4M20eMR44V52uTJE0RqXuKMNlE4vwqnu1dqdOHWvdfDAhTuRaOIcqQk0OBW7ul3hFB+B5R0fCxEDFrAbR82N0PyZoYcBzTYUHAKUM5SuLkRLnpBgxTUyRCB6KMddNA0Ploxa34Jnz0cVcCj2AHjThsdDcE6xZxtwMJWBnU4Szh5m/6ivtPjp0fwlAcuqLQJv57BSHPzBdYYbm7GyehD+EkJdgG/kgH/XOB+j0jTkL/X3LxEbQ0MflPgJZoo7nV6RDf3RWPGfjiPCifghebmG3DLzfJzMs0pWoLlJXajublA5OUcSJn3+EVKj4fpH125TvyWo6j4WsCB5jRtcHiJZ8Sk8N8XtOQEa0GZ/NA4KaXtdq+Knw2neRUWi3Z7HCf/onHZDQJLThuDlWBD3m+3+9MeDzZ34Bv0TRSn82sAm0RFE0g8jm8Lximmc6bTxqJo2MM3JxJ2ezoN52+kBA+0efDABo8/jck9HpqQpyjl/UXLUfqdugncNnHcD7SJ1mELpp51YdWfpjQdx/Znp1sSuYsk7bYnmOBPCFC/FzYEaYMBWnTb4aE64I7caQQVm8GW27yekhdfm6bEDXR4x+JlVDehftjgFB0XJWrXN0MKbBCWBzoc/qLbrYO6scGNpP1wVEIcBcazqN+pEwx98AWTgnhXA7U5aG/dlDFniMOT97vdRNxFI2uw6+/IemkJQKiKj1JqlAXhAnkCsQmu5NPYtbacL0EyO0XQINyak/bmcZBRIz4pIkHt+inhMWImYPCAHDSdNl7GBZwm2EfEgaBR2C1AYWNJ5GYE1Y8ixRa807x4xB6SNyhywYbVQf3B3HE9BQRD+bGDB/vnBnbuPDhGDu7cWVLVEvww9eDBeUrnD+6EH/wEDSMqbCZ0AL8v0z9A6S1YHfunnbjfCcaIzsH6/MA/3To4xuYPHhwA0IM7b7EBOA1RydjBnfOsHy5E4LiD/XJRJZBwjA6IA/tvHRwA9wrp+7GMYioUQvH28GoH5xkszs8N3NqJSRxOg2KIps1AqcqP6tMu5ihBPzrw7EEhO5fhKrdwipSdB58lc8+KZdh+iyzvPHhwmQA13LRM/Oyc2CUEdIKBEbuln+fWMoKCH8VTChQiEi8jHSUqJKNwBWzUFxdEKHlgSYDO66DiOreMo/BCc88al4Ss6yBUTghCqanQ6sioSUxIlacUo3c/KkDwkLmDzw5gyeh/9iDc2rP9eCvPwg+df/YWTRO6E5aNSxGi7nxWHkYwEvNTvCXcoNKxZw92OJvYzmfnl8fwVHDKW3DLc88+O1fCkx2Eh7JTtHjDRah4guJMYHU74BYAFG9BgPbT8lF6wmdvEVr0YHBNS0NI4V0jMhIBuGhZb5J3SOncwIDoAlJV2AiPYQ4bm+dgGR7lHBYVFR4KEe+vWNrel1U4DDSNZ4a8C8nmBuZgA/xCmfdSPAOeqtgEtnVOnt7vFGfHFM4mv0iCPTx4IFzLI7agMbdcpnwUkXcKl/Q6TAoIBWxrgUo8v6ziNZj97piZoArjMbtzS3JRvlJn81r7F6g3b7zPI6sSDnO3fB2tsYHqyxTMqbns95hnaPA04aZ0+UAIfIUBcpRvoeIoM6F+SaTIV1TrV1bTPOJ/mZH1mZ8bPSr6MvSJ8BRQ0U3yoTWAjwtCBTSP00PLEak07YCbEoc5zfOo+gY8qGTD5LSRYFLw3UFwwXh6UW4oeAmwgzJJk8e4ATiTQ96CoSzcTcyj8paEhrmpqoWvX/F2NHidWAeAKqPXJvKErNxgVdeGm8QGrC54bZ6GJiGYzNYEh5UfKNQkvE4vnsfmbZK1iwaPXMRTNnjk6cXJ5Alt+kUcTY3iQLwXSCNvWYrNYRzlhbqWp8HbaL3kilaa+7QZmS3fFT/Gvw79H7nJYTl/dYv5aucxFx3W85rHWXdbN1ScteJu1m00+nsr4MMm/z+ButZuOnuIBEALq/ecPlziaFRtMbJWE+FDJJ5Sxqbwh7+QOpp4xKbMsoaHnBSqZQXFhrOqQmzxEIungagKgioZXmpseGjFm+fYV2ATTfkpM1Z+CEW+0/d/AAgE30XKDO8UAAAAAElFTkSuQmCC", - "data:image/jpeg;base64,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", - "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxMTEhUTEhMVFhUXFyAXGBcXGRofHRcZGh4XFxcbIR8YHSggGh4nHRgZITEhJSkrLi4uFyAzODMtNyguLisBCgoKDg0OGxAQGy0mICUtLTAtLy8vLTAtLS0vLS0vLS8tLS0tLS0vLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLf/AABEIAOEA4QMBIgACEQEDEQH/xAAbAAACAwEBAQAAAAAAAAAAAAAEBQADBgIBB//EAEQQAAICAAQDBAYIBQQABAcAAAECAxEABBIhBTFBEyJRYQYycYGhsRQjM0JSYpHwcoKSwdEVQ1PhBxbS8SRjg6Kys8L/xAAaAQADAQEBAQAAAAAAAAAAAAAAAgMEAQUG/8QAMBEAAgIBBAEDAQcEAwEAAAAAAAECEQMEEiExURNBYSIUMjOBocHwBUJx0ZGx8SP/2gAMAwEAAhEDEQA/APt7tXPHH0hceZrl78J5m7x7x5/vrjqVjJcDnt1xPpC4R6/zN+/fhXxnNyq0aRuU16u/p1d4AFUAugSNbWf+OuZGG2BSNh264nbjGZ4XmXeGN5LDsoLAcg1b9dvZ0wVr/M379+DYFIeduuJ264R6/wAzfv34mv8AM379+DYFIeiYYsxntf5m/fvw04a1oSSTudz7BjjjRxoNwBmuMwRkq8qhgQCLsi/EDkOpPTCXKcX1kgM/q6hZ5jUyfNfjjM56eVM20Uru6y28BJbfkJcv3BZ1UoBPIVhLNcNNU9sz6Rks0JUDqGAN0GFHYkXXnVjyIx5HnY2dow6l19Zb3GwPL34z3CpmESgO5589Qrc2KJJ25e7GI4xnqlklJa9Z01eom6UCtyx2GCyuPQqcpW6S/nJ9gxMZfheYm7FO1Lh9I1Avqo9RdC/3z54KGYb8TfrgszfZ35H2JhCMw34m/XEGYb8Tfrgs59nfkfYmEIzDfib9cGcVzJSJWF3YHPyOOrknlj6atjLExkoM65bvSMB/Ef8AOPGzUhalkf8AqOG2mP7SvBrsYv019MpMhmIlMatEyBjsdTHUQ9NdDSNBog3q5jHEfHJFmMTCbcWsm5RtroMCfiByOM/6SA5yN+31QqjfUTTtpR33BUa6oGiPOgemOUPHNb6PqGQziTRpLGdSOoZT4g/L2Yvx8k/8Os/L2T5cOwMb7LZFBrJGxr1g+48ca8Z6VCQzMf5jgSs5LOoumjWYmMll865Y6pG/qI/vjS5BrjU2TtzO94GqGx5VPoIxMTExwqU5rl78J5r1Hlz8sOM1y9+M7xgyhXMKgydL+JA5Fq5AkAmrI54eAy6Ac9l5pJYJIZ0ESsxcAKdXdI53vvYrpd9MTPPcw5VDGW/+pNqjTfxEYm/qGKvRkDSRELyw+yYk6iTvIPNdV7mjeoVQBNCzjsjMTSyyO5N3Wk9jGvkwSNbXmGcjnhkdQPBmTlnJXeMnU8YF0D60ieYNlkHMbgar1ahHsAgqQRYIqiDyOMbmJndg0cM23UhU+Dsrg+4V4jB3B+JdjHokgmUBmIICuqqWJVQImZqAIFV7KFDDPs5Ts0u/l8MTfy+GB8pnI5V1RsHXkSDyPUHwPkcCrxqFgDGJJQeRiilkB/mjQr8cctHRlv5fDHHF1zBybjLIJJNYpdQWwCpbc7HYVVjngGXiTDllpj7WiT/9kin4YDg4lmGnCxdpq7SM9mgBiSI6RL2raK1ECQim+6lA2bWXQJtcozI9IRG2nMRSZd6oagaJ7YS7MBuNJbesaLiUCZ7Kns2GsEvE4O2tGKqQfA0Qfb5YeSwo6lXUMpG6sAQfcdsLYcpHliI8tES8zd2INSWBbObB7NQALIHPSKJIxE3zySa+r/n3LOGZgjKrJIoRhFrZQKC7aiK6EdfO8JvRXg5YjNTqQ1XDGfuA/fYfjI/pB8TjQyrmVB7TKFgdj2UiPt12cISPIAnywJmOJxshAEoB2bVHIlAAu62yinKqwq7BOA5HJu+lPsNmmpQwMQRhs0koQN/DSsT+g59ce5bMBrHUDoQQRexBXZht/kA7YxGfzrSMXfmdgByA6KB0AxdwjKNK+0UjR+rLR0900SpZmVeYUkatwOowG6ej2Y9zfP8AODTnjMVsEEkum9RiRnVa52yiiRXqgk+WDoZFZQym1IBBB2INEEYvSeEwNDGjerpMaohIHT1ri07VZOnYjmMJeEJ2CtGw7gYlCpUiNWIOk6ZHKjVdE7CwL5YKPOg5NtNDXxwZxz7FDV0yn4HAe2+E3/iFwXNziMxSIYQoBgYuoZtzqJj3YVQo0BXnjsSGrVwpl8+YV/V6c+X9scZ2A2kUY1yS2oBNDTXfckbhQDv5sANyMfP8l6ET3bSJHXVSxb3AAAe843//AIecJWGXMHW8jBY11SGyAdbGvAE1t+XD2zzI4oOXdmn4LwLL5VNEESp4kDcnleGLKCKIsHmDj3EwpsMD6S8HXJyjNZdY1Dd2SMd0uOdqORcdBte43sUQjlgsnrKaIPQg7j3VjXcQhDxupANjkRYPu64wHBJT2bwKVZYnKgpdaDUiACzQUNprporphov2M+phcd4zzMoYisavhy1Eg8sZUMmiq737641HCfsU/hx2RPTfeYXiYmJhDYU5rl78JpvWO/XDnM8vfhNN6x5c/LDw7HXQG7RwRE+qiAmlHtJAA5kk8upOAIJJI9ZJKyyHU4B2j22QVsWAoM/MkVYAAwbnlt8uprS2YS+X3Q0i/wD3IuE2dzaJ2ck8vZJNLoSgCzC6aTvbKgPWjYINixbWr5BV7lzHmSwUAWSd+fIAWLJonnsFJ8jTJNRv7vW+Y89tiMXcZyLwGpAHQ7K96Q2xoNvSuLOx2YE1zIVbGe0NgiqpgDZA3v1b28zXK/LA5Nvg9DCsLx3IJzeRD2ys0bkadabEg2KPRhvyPLmKO+DpZydrIUbBbNKBsAB4VioNe43B3vHiutkEgUVG/UuQqj3kge8YrS7MTaXLPJpAis7eqoLGudDw8SeQHiRjS+iOSMeXJf7R2LyfxEDu+YUAKD4LjK8KInncDS8UdajzDSAq8Vb1anUT5hMbrhnqH2n5DEsjsm3YpX9/DAuQcDPgnpBS/wA7nX/+EeClr9+7C6XLiTO5ZQWUqGdyD6yAoVQ+2QKfYjDkxxA25Pus2mM36eo30bUOSuC/kpBBPsBIvwFnGkx4RfPDGTFk9Oan4PjDpddCNx8v74vn4iTFHHZ0pew5FizMW/Q7eQx9M/8ALeUu/o8fsru/0+r8MW8Q4LBNXaRg6RQItSB4WpBry5Y5R7Ev6rjbX0v/AEfHlzJJG+mwbI/CaIB8QdufVcdLnWUggb0QRW7AggivAjmPMjGr9JvQ91e8rHcZruqRakCjeo94Hndk2TthOnB/og7fNNFGVZWWF2XXIA3eIFk2qWwAskqOQ5lGp63E4br4/X/FG3iFLvzoX7drwx4xLphU1e4+Rwiy/F4nbSvaWeRMUoXx9ZkC9PHDrjn2KGrplPwOCPZ8/rX9FoQw0W73Xf34I9H5QmddRymiGnw1QsbHtIl/RDijMzBqofrjnMhInhlZlASTUWY0FGlwTdirB07/AIsUl0eTgveqNnNKqKWdgqgWWYgADxJPLHSm9xyxnMnx4TlhFIjCiLUqwHrAbA7ju/EYZ5DhEceW+jgEoVYNvRbXZc92tJJYnu0Be1UMTs9OcHHsp9IuJSwLE0UPahpVSSjukbXqfzrbCMlRMzoK1HS42306grcrsURd8vdh/FlctlMusQ0xwp3VBbxJNWx3JJOMhDxqCVptYMcQjbs1YV2lghmY/d2ulPiTz2HG6ZbFjU4S+lsPgCljqxq+Ggdklcqxi8tKWii1XqEa6ieZahfxvG04ctRIB4YrLo8rTfeYTiYmJhDYU5rl78Jpq1HY8/30w5zPL34TTHvHfrh4djroomQEAkVpIYG+RU2DfTlhAvDsnxCWFZGLdmv1ai1Eke11Y76bKbQ/eG554c8UgEkLxtJpEilLPi3dGx58+XXHmazPbQxzkpHNl5GGirDSqrxqgsqQG1Ajrpaut4Jrk7vpVQ9jzytL2IjYoAe+AClqaK3ysHavEHbFHFuNrBJHCELyy3oFqimvF3IF/lXU1b6axmmzMJzBaVsxEzkM6QOzJIUHrFUHaC1Sj3apefMl9xLiGWnjK9pC61bI5Xl+ZW3HTmMI00cq2l0LOP5AQlZFACyEh0B2WSi9i6oNTXyF0atjjN5Zu0ZRds80ew/I/attz2EL86qut7aKTMB9mfWBuAm5J3A5bDbffq3lgP0e4OYyZZSBIV0qq7iNb1MLHNi1k1sBQHUmkZNqjuSDVRse7eBw04Z9mfafkMZnhXGVneZVEi9k+i2RxewN7jY2Tsd6APXGn4Z6h3vc/IYJdCsUr/b/ABhJl+MQR59y0qACKIesDvrnLDbrRUkeYw2zGWSRCjrqU8weR3HPxHkdsLJItE6NHGUREKyMAAmlipFAbkqVvYUAx3xA2zNs8wClgC3d1ALzbawBfU4VcA9Joc0WRNccqevDKumROXMdRuNwTzGAXZ3sazRFalO+4PIjkRtv7Tg30f4XBlI+6FQu3ed2t5GP4mY2x57e3DJmXJi2LsdMwHMge3HoOF8mahlk7NZ4zIt2gZSw8bW7GKp+KwZciJmdnAsrHG8jAEmmYRKdIJBokAbbcsKnLdVceSdKjMcK9Ic5/quYgnB+jqG0jQAFAI0MGqzqHOyee1VhnnpUZZ1jhjDSoyu1UWtdO5AtiARz8hhmvEstmGEaTozldQUMNVcjtzB8RzGEucdO2MMJ1kG52B2jHPTf/Ixru9Bua7tsy+JY2uezvhrSaKlQKQAO6+oMNt91FezDbjgPYqB4j5HCrJ5YoWuWR1PIPpOnxohQSPbftw44xLphU1e4+RwR7E1n4fIgR00EEd72fpgeNVWXLyyAGNZdJvkrMrKjn+YhfLXfTF0NFjq67+/HMkQYsg3VtiDyIrcHxHPFWePCW1qQH6b5iLtlWChIl6pE2ZDtSqw38dQ5bAEc8Ar6UZvYGcmuYCxrfvCEj3YEfhFZo5dRIyBe0KqRrKqrMURmrdiFUW22omxtjV5z0eRU72WyvZmVaodlJDFp757RSxeUN4EXvvjNtm2+T6ZajTRhBbN3HN9mT4hnjKRa1XVnZ2PlqfcL+UbYu4Hw3t9avMkcctxoO72sxTvypEHOkigLJB5EbcwVwv0aeQO8kixxo7IWG7HSxXYchYrmTueRxosnxGGKNooY4hJFZgEz6BKG3dw5U0dRYMALsdAwOFhF3ci2s1OJYliwfmAJCyKh1MyOtlZ1RJ4mPq6hGAtHlVA+Z3rX8J+xT+HGJz3FEzU0aIkWoFWzMiWRqjL/AFYfSuqnUVfNWJoddxw2uySuVbY0ex4W2McnHj9wnExMTHChTmeXvwh4lmViWSRyAiAsxq6VRZNCydhyGH2a5e/GR9JzpUyMfqo21zJ+NFonf8tatP3qo7HDRHXRnPT/AIxPF2AjjpO0WQSbEOy95UoGx470TW3XDjPRKY0zEuXEbl4llUtv2bSRo4bQ1PSnYHwArpi3JcN1QxrKSdLrKi7HswtMkd/e08tWLjLCuaBzTlI0VWh1NpjaW31WdgXHc0qx62ATyZ+QuuTT/wClQiMxrGqKTdRgLTA2GGkesCAb8sZGDIuJf/i4isZbs1kVitMSxU9xqKkKLsAEsoAHqh96P5mSYnNSMFSVF7GLWTpQ22thQGtrXxoAC+d0+k/G9AEcSrLIxKCMjYtTMpJ6KClE9LJ5rRRMW+DJTZeXJSkbkvJ2cLuuoNG5WqKPv2an7M6PVcjYYd8DzbSdsGYPol0htIWwUjfkDQosw5nlzwvX0dkLDtM1IUX1VW7WxTU7ux33GqtQB59cPoIURVRF0qoAUDkANgMUSoa2+yxUq6UCzZ5bmgL/AEAHuw24Z6h9p+Qwp288NeF/Zn2n5DBLo4xUtfv3YF4hA0i6FcoCe+w9bR1CnoTsL6AkjesFLX792IKxnN7QvyuSkgN5WQKv/FICyfykEMn6keWLcg30zNMMzDEwiiMZW+0TU5RjWtF72mtQo7Mu/MYLGM76Pekohkm1xOUeR3QpRIBYgagSDvp1AjajXTd4xb6M+dQirZpfS7KRLk5SEVWVSYSqgMs3+yU29cyFQPEmuuJ6Mu/aZkSx6HeQS2LKspREADFRZUxkFeg0+O+c4nx+Sd0cUio2tEKgshAoMxIKFiGburYWudnYXPcRmlZGeV7RtSFNKlDyJXu1ZBIprBuiKxojpptWYHqIJ0a70xgHZLMQSsLFmAYr3GUxyMCN7VGY1e41DqKHy2XSNdCKEUCgqgAD3DGdznHZpNMc7gwM6q2mLTI4ZlVQ57Rl02Rq0gWL5csabxxCcHF0zdppKSbRB1/fhgzjn2KGuTKfgcBit8G8bUmFQoJ3HL2HCx7F1v4YhzMwaqGA/SHNfRsu0ybso2HmSFB26Wd8M4oCUrs3J/hPu3rHi8Gd1IZNjtTAUR530xU8eKbd1ZlPRXjBKLnHbtZg7RtHqKk0jGMqAtGg8looa1IYd5dJLzvFHnm7cNKEHc7OSSFIVarGoiQuOh9XUa5DDrI+i3Z/ZwRoT1FX0sXZobDYeAw0HA2KaWCX5779OmEr5NsczT4hwYxeKgokcTtJ6sjGKySzu0kv5EJN7Mw0h1F7YZJlXbS8yjQvqRWGUfmbbvOfZQs1d2dAno81buB7B/7YJ/0QkUZNvJf+8CSQs55ZppKkIZXU0FAUDwAHwGNbw5aiQDwwIvA46ok+3a/lhhl4QihRyAoXjrZzDjlFtyLMTExMKaCnM8vfhNP6x368sP8AAMnDwWJvmb5f94aLoZMWX+b54ln8Xzw0HDV6k49+gxjn8Th9yC0Zd+E0T2crKNyIz3owTvYBGpRe9KwHzx5w/hzLJ2shTUF0qE1EC9JdiW3LNoTptp62cacxQDqv9X/eIJYB+D9Lxy/gRyjdiu/zfPHovx+eGzZmNRdfoMcpxNDyv4f5x234B5Y+RcInP4v0P+MM+HoQhBu76+7AGRzcmYmdlcpBC2igFJmfSGaywNINQFLRLKd62PXExmYi00LdstW2XYKDQ5mNgAdXXS9gnkVwjlY12jlcg/4fiMdrw1/L9f8ArFcPGGeNZI9BVhYIv+/IjkR0rHUPEXN2QPdg9Ng9bzRyvArmV5GtEFhAWA7SwQxqg1AUAdtzhRkvQMJ/vdADSc6HMksf+hQ6YZ5jPPezn3Vjhs65Faj7bOHjCUXaM+TURnakeJ6IRdXkP9I/ti5fRjLDnqPtb/FYoeNqsm/eceZar392KOU3/cS3Qv7oSeCZKqKofa5PLfq2GH1I6L+l4S5ir2x79INV8cK4OXLYyz7eEqG652HpX9Nf2wTNMFF4z30c1fww34l9mvtHyOElFLorinKb+o8PFB+E/rinNcY0Cyu3jzxxl4Q259mB83lh6jEkcyOXs/z7sTWTG57F2aNpfluMmRbXSD1GPRxB+pH6YU5WSNXMSuC43Pj/AINbX7cW8RGpNPLW6Rneu67qjUeh0sa86xWlQOLXaCEzjyIXMjpGa7Nk06pB1IBUhUO1NzO5FbEiSQg9ZPb20xP6l9vdWCMzJqYnpyA8AOQxViTNmPDFLnsEmhlAPZSt/DIdW3XSzWQ1ci2pfLDr0d4iWHYyKwkQEgnTUiBioYaCd6K2CF3blgDFnoqVGYzShAG+rkLUO9qDoBfPbsro8ix8bPSWojGKVI02JiYmOGU4mNKT5Yz8mae9nar8Th7nPUb+E/LCPKha3q/PFcfRmzt2kjmTMM22OJICBe2PGNHbx2x3JMW2rFf8Gfvs7yoFG6v+2KZKvbHskJAvFmVA3ur88c+Q+Dl5yRWPJICBeOGRnlEcRAJtixFhFWrNdTZAAvrfSsH5jg0mk6Mw7N4SCPSfI9misPbvXgeWFc0uCkcUpKwP0Wzio82XfZi5mT86PVkeavqUjp3fEY02MZxHh0jizBMOza1kQprRhsWTvaiOYqu8LGlgd7MjxfMqo7i5hatWiZUZgeVpIQnLqHHsGJuNvgvGbSSkhjxHgL62lyriNn3kjcExyH8W28b+LCweoJ3CjOR52Jdb5aJgCBUMsjub22X6OAfeQB1Iwc/pOQrFoJ1oE0Vj3PRRpc2SaAq9yMO4s0ViVptKuQNSoSwDmhpBq23NXQ92BOS4R1qEuWZ/LJmjuMpXh2sqKf0TX8ccZgZhTbZR66mJ0evdasfcpxrIZQyhl3BFj2HHeDfKw9KDRk8rxNZVOgg1swohlPgytRU+RAxccuav4YY8Y9H4MwytIveUjvD7yg2Ubo6HwPLmKO+Ac5wJ4hryZ2+9A7Eow/IWJ7JvZ3T1AvUGWQnLB8nOWAvf3Y8zNXtgPJZtZLAOmRfXifuyJ7VPTwYWD0JwblgL3xT5M9NcMn0g1Xxw34gajX2j5HCfMgXthxnxca+75HCS9jTp+2L0kK2R1+GF3pC2uBixIKgEEdTdD54IkzGghaLM2wRRbN40PmTQF7kYFnZzasIgpFFSxckHYhgq6PIgM2E9OLldcm2GX05KT9mYpMyyENHu+oKtEbsx0AWdh62943P0d2iUSkdpSsTHyEikMCurwYAix05YT5nKi4guXiTQ4KvHsFoNpJQaLGrTtbdTV1gj/XT2bDRpkXSGBplBYhdQ0MTV8gdJO3Lnjqg4rkvqdWtRJUq/nkLy0EjzAHVo0EtIrqNDE7L2ek2COrXVbVvZ2Z4aiIXV5KQagBcm1G+6O9JfTcm+WFnDOHaexEmszO2oSJqClWBd+8hHMliRsbA20qDh1leBuhP1wVTsRHFGuo7CySps/wByfZiNMjLLzxYohzJoX1AKttTaidI2JpuQI8SKJxd6FWZ8y5q2SI1d7XPv+tj3VyAxZxPh80Ss9iWNbegdDAL3gCPUkqr5r7MLeCxyLLEyFSS4UaWFMh3lBvnSrqAG+pB01YZBmnuSa9jeYmJiYCJVmh3G/hPyxnZISOeNFmjSMfyn5Yz8kxbasVxmXUVZ3lVBG9XiljTbeO2PZISOeLcqoIN88U+SHfBxJOWFVinO3HGzkWFUmh5C6x2+zbeOKOMXLCyAcx09oO2Dro6qb5GmRy6ZeN53cyPpOtlO3dJtFW6ADWPHbcnAeW4rNmJUfLio1pZFeq7xYk7HoFHLe25VeO/RDNNJC0UqatHcLbFWFAKNJNg6avYgmze9YujgljlMcKKkR8FFcvWJ5kjw8h0wkJRSdrn56K5oyuNP6fju/wDQ8Rwbog0aNdD4Yx2YWWAM0kLaTIxBRoyPrJGKr3mB1d4AgA73V40XC8m0XaamBVmsePMiyT1O2EEpV8xLJqLhSBGTyQMiMwA/mO/gawkeJcFJu4XJFkz6UZtJYrvpAskDnQG5IG9DfbbAss2WkCpPONElOjqTRBOlGLAaUtrA1UCbA5VgjiDGJNVaiWVFUHcu7BEHlbMN+nPFfo/lmOazEU2XVQYFWVbDI1tKU07DWrB5bJAopy3w0+Jbk+TuGbeN45K0zRcQcwQAx6QsdA6gSNA7p3sVQ3J32U7HHPBs/JMGZkRVB0qyuWD16xFoKAO3WyD0ompstLAgEcqmJFAqayQoAH2moH3tqOJL9KZVC9jCvV1JkIUAVpUoq2d9zYAHI3tIsqSo5j4i6yESFSu9aBX62b/tjj0efQZkNBTMzx/wuEkb2fWNJjM5XjQJeIXmZRI6p3olJRNtT7rtqLi0Q7Ua3wwGWkdVIkCTp3gwBKEn1lIO7IeXjsDsRhqcuaOSeKEaTd/Jp+IcMhnAE0SSVy1KCV8weYPmMBZf0cijvQ0oB5K0jOAfLWSR7Aawhb0hkiJ7UiFuqSn6s+ccopT/AAtpPKwOeB896XOvKWG6NEMCCRQ6ElrZgKG4omzRwdCtqS5QxyLt2skMyhZI6OxtXVr0OL3o6WFHkVI32JecYkCw6iaC7k+AAJJxl+FpLKz5iRWXUoRFfZtCtK4Yj7v2lAHekBPPGg9JELZR1UWWQgDxJVqHv5Ydt8MTEkpNIWtK6xqrEh3GuQH7paqjHgFFDzO/U4FxbxLNo0mtWsOAy1vqBVeQG55jbzxUI5P+GT83d9X/ANX8t4vBxjFWxZKUmyYEysxExIokt2ZGwsUzR2fJhpv/AOYfAVdLIV2ZHU/mU1vspJGwBO2557c9sK8nGWljBHeLa9Q/Ch1NfipYKNuTafHC5ZJpUUwRabvwa30X4fH2azai53CrbaYPutGqMx0EEFT15gUO6L/SHicSo0TAMWFFTyo+OFEkGp2fsrexpF0jafvydDYOkWGKgWOuBs9kCxHYJ2VA2jHuaqIGjRZQD1thRod2yazU7Kyi64K5eIzFOy19ou1I0ZdpAQD2bNdFaNFmF6TZJ3bDr0Y4Mykzz7yMxZbawuoUzaQdKsbI2uh13OBOHZeRNbSaQXfUApJAACoosqt91V6eONTkz3F9mOyVB/auC7ExMTCnDiZbUjxFYRNkpAbCHY7Y0GKmlrA8yxq2JPEpiOYOdtDD3H/GBZIJGDdiI3dWCsGfSFJAbvEKxBog1X3hjQZ3PCKJ5WHdRGc+xQWPywr4FljHl4w/2jDtJT4yyd+Q79NRIHgABiWbWqGPdEWOmTlyLBNJCyjMxx6HYIssbllDtsqsHVStnYMLFkDaxZUmzbdDgL06hLQqoAJLqqksaVmdFUhBszWaBPq7nyOtOWjP3V/THdLqXOG6ZzJp1dRMbmophI8kMjIWG+kiyB0plIPWjzF+eDcr6WMqKJo2LggF1AKsOpqwVYgHaiASN6xofoEXgPcT/nHE3CYn5qL8dr+IxZyg+jsVOPZlLzGcId2MKj1VDENdRFj3dq1x2os8zvuKNiyqRARxilUUB8/ab3vDo8HXozfDEThIH3r93/eHi4olOOSXaEfFtUkYCUHV0kUm61RusgBobA6aJ3q8N+A8YaZpI5UWKWMi0D6iyMAVcd1e6TqXbqpHliScJa+6V+P+MD5/gzSaSVp19WRHKuvjTCjR6jkeoOCW19HcbnHtHnpZIivljPQy4kLSFvUDBT2eu9gtkkFttQXrWDOGtl4oAYJFMJJdCHBQBjZCkbBATsBsLodBgHNw8QsmOWOj914g1ewpInxvCZvRieYt9KmZ+XdWOlJAQDVqZiy3GhKggGt8JtK70L5+LJPBl0Z10jLqXZAo7GY6QhpRSNqI2FUUO1ahh9kdTwxyMKLIrEeBIBPzwt4hwCSWS8zKrrQtI42jV6DDvapH5hqNVsALrDw5naq8sUgmiGWUWeZdQTR8OWKpcrGrWiKp60APljvsTV46yygnfD/JH4PfpJqq9+GueH1a+75HCjMqAdsNuID6pfd8jhJexp0927M3xHIjs5EQvEZCAWhIVyWYeq3Qljv43g5+OBQFI0uoIYSFhRAVvWVSG2IPMbEedUZ/fsidelJAzaBbVpdQQKOrSzK9UfU5HF/BM2DmZFLOyOAVLpQZ02IWwDsuk+B3r1TiM48m3dwewZMyu0saMqyAFjIe69ClpbJqulAe+8UPDLlw8ssIIO7vGwalA2sFUNAdFB95JONNm9Ohtfq0b9mMFPnW0GJ5mKMwTQ1tYZgK1k6lBB0knVQaxVHHFwCbkPY5VYakZWF1akGj4bddxi3n7fngbJQsmouQzu2p6FC6AoDw264IZeo5YuvkUitWx5YeZP1F9mEnP2/PDrJfZr7MLPo4y/ExMTExSYGYbnBOEPGeFySzQumYeJY31Oi8pRsaNEHmAKuqJ2xl1VUrGiXcbyhmy08K85InQe1lKj5454XnRNDHKOToGo8wa7ynwINgjxBx7xDiQjhMqFXUMq2DtRkWN9xe62fetYCzHDnhd5svIioxLyxS2I75s6sN4mPNtmU86BJJ8+cW4bfeyifJzxvJlpMtKBawy63F1S6XXVRNHSxVvGlNbmjRmPSGSgfqolYBkD63cqdwSkdBLG9FicNeHZrtolk0FQ9lQ3MoSdLEdNS01HcXvvhNnPRRSD2cjA7BFfdVA2CihqqthZNfDHI5dv0TXXH/AKPCMbti7O8dcyxyLKx0ldSKCqEW3ad0sbJBFXy04b5H0uhZtMqtFZoMSCh8LYer7wB54QSejubH+2jeayD/APsDET0bzT7FEQHYl3B29iA37LGGc4PwXccbXZ9CBOPdZwkGXzMSxiCRJFSNUKTAjUVFBhIllSetq3ux7/rUifbZScDq0emVfcEPaH+jBCd/dkZWh2rnxx0ZCEJ6gE/pgHIZ6KddcThlujXNSOakHdW8iAcVcRzzahloApmdSxLXpij9XWwG5s7KoI1EHcAEjVppTc6YrotHEz1A+OOxxQdV+P8A1hRJkJwAYsxDM1X2bIF11zCsrHRv1IYfPHWXl1qGFb9NtiDTKaNWCCD5g428l4xxy9huOKL4HHpz8Z5j9RjMycYX/bjklFldSBQtjnTSMoauRKkgHbBWVzWuxodSN6dCNvEH1WHmpOCw9KA9+kQnw/p/6wozOejYsuWhWTQaeRnKRKRzXUASzDwVSByJB2wJmQ0sgy6HTa6pXXmkZsAAjk7kEA9ArHmBiZqVQFiiAWJBSquw2wjyy3bY/n8CrTRnKkdZLOqZAk0QVWIUSRuzLqOyhg6grZoA7iyAasXp5oAwAsisY8zMidz15GWJOW9kPKd+ixqx/TxxoeOH6tOne6ew4eeRxjb9hZaeEcm2BY3Cx0b4f94F4hw9wokXvPEwkUAbkL66jzZC6j+LC4ZlxdO/6n/OLF4hIPvt8D88Q+2r3RV6WXku4nx6NkdFhnc0LBjaLme79sFuyKAFkkUAcB/+W5NQkIW6AKiiF3tqO1sQWQsR6rECt7uOcYuHNFl5Egbcx08ifZqPicErxp+oU+4/5wLVQ9xfs+RdUWHLOeam8VBGHNT+mLl44eqfocWLxxeqH9Riy1ePyI8GTwButb4d5I9xfZgQcZjPMN7wP84YgYdZYzXBOcZR7R7iYmJgEJjPzcVkiJ+kQMFvaWG5Eq9tSgCRD/Kyj8WD+P5OaWBkgm7GQkVJV1RBPwwOmSmBQnMt3VUOuhKcj1mutSlvbtjNqeYpDRAkmy0GqdsxGsOYIdVZl0l6Opks76hpJA6qTzJx7xfMxziKFWV0mBkOk2HijKatxsVLOgPiCRjmM1xCTXzOWj7G/wAIeXt9PvMOr+TBuU4fHEztGuntN2AJ0k8ywW9KsepAF9bxheWGNp8viyqRQ8zuGWypIIDCrWwaI2qwN/bQrF+SQpGkZcyOqc2I1PW1n2nrgjsx4YozeQjkrWoNAjqNjVqaO6mhanY0MRzZoZOlXkpJp9FHAuJnMxCXsniB5B9PeGxDDSTam+e3LwomrKcWLzyRMgjCXWonW9EDWo06THvzDE7gEDBGW4cqNas4UWRHfcUtuxAq+p2JoXsBjjM5duhI9nh199beW+O4cePJJpuvARV9l8meQSpEb1SKxU9Do02t/iprA8FbwwThPn+HdrFTFlZSHR12ZHHJl9lkUbBBINgkYWZTiGekhRkiWTWFZXRkU6SRZZHPcNXsCwvrh3pE/uyXjknOe2VdjUJH9NDI4VzHpkX/AJBu0ZPiV0vR32LD2LuG5gJxbNwzXeZijMJ6FI0YOt9DZc+44L4BwJ1lOZzJXtO8saKSRGrsWNsa1NvXIACwOZwx49wHL5uEieMNpsq1kMproRv0G3I1jZhUY5Eou+Oya3NcgHCvRlMtK08kg0J6hJqgRVsTt1rz5+WFE8pGUzTIaYvmCK20EySV06WDfnY2x1H6KZfTpkMsw5ATSOwX2CwFPmBeDYuFQxwnLxqFjcFCBe4K6ST4kgAWeZxr74RqyTm28mR+xXmiqMsAZSUjCqAABpSlNAbAAmq6bXjuKTYo19m2zAEg+0Ebqw5gjfbHOa4KjaE1Hu7q16WTSAo0kbDahVAHfUDZseXhs4TUuYUjb14e/RIF2HCE2R9yvlghjcYqzmPV4pRUGFZScJFJHzl7Rklf/k0dxX8ASipYGwJbA086oLc0LobEknoABux8hviZeEItAk7kknmzMSzMfEkkk+3HmYh1DZmUjdWQ0VPiOh9hsHkQcLGKjdGyEHCFLv8AcLyMDFu1lXS2nRGlg9khNkEjYuxALEbbKBYWy9459mn8Q+Rwi4Vn2fVHKQJUq6unU3pdfAGiCOhBG4ol5x37NP4h8jhc34bMlVOP+RKevL4Yn6fDEPXHmPMNoPxJm06VOkvIkQYVa9pIkZYX1AYkX1GMvLkgZGeGNkI9V09cjcUXO72ALLE3d4fNOzuWVmWNGKrpNGRlNOSRuEVrUAVbK17AA9Y9v+nwWODc4p358Hzf9VzuWRRhJrb48i/hvEZIi6TLK4saG06j+Ybd5gDyNE74d5XNLINSMCLo+IPUEHdT5HfAL5B5u7HG7kdRpAX2lyAfYDeA89lp4iJNLieId+PSpM0Ivqrd+uQI1FSRsLN59TpYtuUOH49jZodZNxUZr8zQePL4Y2GMFkuKQy2I5AxrVXI1tuL5jfmNsbXKdcR0kWt1/H7mnVyT218/sEYmJiY2GQmBn54JwNJzxk1i+lDw7AuJcMSYLq1BkOpHQ0yNysHzGxBsEbEHA3Asy0sCSuQe0LOtCvq2djEP6NO+Ds5mUjQvK6RoObOwUD3nbCn0RdTkssqsjaIljJRlYEoNB3Ukb1fvxgyR/wDm3Xiii7G+JiYmMY5MTEx4TgA4zEIdSjXpYUaJG3tUgj3YyvpPwrLZfLs+XhjjnQXE0ahX7TlGLG51NpFE73Rw0XixbtCe4gWwx+7yFnr1vesVejvDVkCZmV3lcFtAagkZDMhKou17HvMWYXsRjdp4+mvUk+L68uvchNtvajSY7kH1bew/LHJx7J9m38J+WL6X8RjP2E1HwGBuJ5js4ZZCoIRGevHSCa+GCNvPAvFct2kEsa7F42Ue1lIHxxvNb6K8zP8A7Z06gO915bbWBe9j97URKztojUu3Mjot9WJ2X5negaOEozZdhKFNmPXRPNipbS1cnGpNXSzh7xbjv+nzZPLRRiRZ30yOb1MxKIWFbara/CgAKHIjJyVshDbhxrauRhF6OyndpUXyVCa/mLC/6RjpvR6QWRKrbbAoRZ6d4MaH8pw/nkKrYF+Q/wCsJOPs08fZRTJHJYaSPmzJRtSFdXUE1ZFGtuuC1e0VZsr5szkjFZom0lXWTsnVuYDjlsa9YRtY2IHnjW8d+zT+IfI4TtEHI7QhpEIJ0ihYBrYk1zurOG/Hfs0/iHyOJ5vw2XbbyRbEvjy+GJ+nwwLmMwVJorzqnDpVetvpYE3VXpFHFGazp7Euvc7wXVaMFBZUaQFCykKCTv8Ah3GPP9ORp9SJ7wbKNKmTiDadeVWV2AFgUrSEXtqLydfEneqJnHMhDBQSc9rWoQyEfWjckKaBD0rULo1y6ijgczJFDIqnVD2kOgkW8JYMosbBgFTyJUja7F3GONiR10ZV+2VSAXKHs1fYsAjsisRYtipq+fqn2W5J14PDWCMo7mr3HvCeIzCNY8unaMJS8u6BuyY60Kh2AIN6NXTQ214Z+kkitJCitUilmYrVpGUYeBAt9BAPPsz+E4x2c0ihK8aafVVaZx02ZqCeFkV549yOYdBUQNE2e7d31LAxp7dOv24JRt8FcMXjSeWlXyCZrLJDLF2cl1MDqYUq21SJqA0r3WZQt89umPqeU6/vx/f7ofO8uiLFO8+yF5LDEnWGLBVCnq3KlvVsdycfRMn1/fj+/wB0Cbt8+Ev+yWNdtLhyk1+gTiYmJhCpMDMNzgnAz88ZNX0v8jwEXE6+m5UyAFezlEd8hN9Uy8/vdms1HwDeOGoHx3xxxLIJMhjkBqwQQaZWBtWUjdWB3BwoX0flY1PmTJGOVJolseq3aI9Ag791V5eFg4nFTVSlVDW10h3iYUhM5DsNGaQdSRHLXnt2ch8/q8U5z0i7Nd8tmVc8laJioJ6s8WtQB1ok+AOM3oz9uR9yHmFHGM9/towHRj/Yf3wE/pfCC1WQvdA0uGkfb1VI7qDe2b3ct+uGdnmJGuF9lBeTRIiO55hdYBYDx88dWNx5kgbsCzmYEOXd3OoEElSNjElGb30bAJJ7vtw99HIuwyeXjehJ2aimarkK6mFncm9XnscLPS+CPRExFpC6s0Y21KCE07dKYnTXeoLteG/FGR5Uy88SvHKrFS1EdolNpo8jptgRv3G5UMbefSj82yK+8wbifEM2mXd0yoaZSKjEgYEdWulJrwoE8hzw8ViYiSNJ0mxd0a3FjnWF2QyMkT6RKXhrZZbaRD0Ae7df47b8x5YaSD6tvYflimmrfx8jsTX54lnxx5XliV5Y2mwWf6VpkZ4yul7LRty1Np1upA7pbSuoGwaB2Nk3SZ8I2rspJKb7vZ90gC93cC/8nBGazAjXUwPMKAASWYmgABuSTgDLws86wsJcupRnZGMTEO7L2ZFGQKGqY0CN05Y510JKUY8MMSSGft8zmC/ZJSINTjs9IGuhEd5O0JGpbOwA5YDymRvKCNIxHmYGEwD0shUszAs67h5I9Ss/4i98jgzNcBljjEUMmuIyiQo4Ao6u2dmdd9BcFigWyW02qnYbP5Rs5IY5TGjxKLKKT26Sa9AOpgBGSklo2oEqDY6lMye/ATw/R2SGPuoyhgKI9YarPnvveGXpFKFhVmIABsk8gKPjhXw2dnjtlAZWZGqwCUZkJAJsA6bAO4BGGnpFErwqr3pJo1zHdO4vqOY8wMLlrY7NLf1RaMdxH0k7OKWSFWcx6SVIZaVzpD7i9Ng9P054o9FuNHOwydsE1BirgcirDbZiTv3h7sXKdGZVJtNtE8bA7JKDpI06vXBGrZbrUQaOF/B+HfRM20UUE7RSi+2YjSANRVRS0SDamzZ2NAc8s4RUWl32PDJJyTfXQblYnjy8TQsSwLvTEmzbxdiTqGy6VBuzqW8Vtl+0sklVsghu8bBINX3K29YqWPiMMZ8kTrMMrR6m1EAI6MwIBJVlNXVHQVJ8bx3Gdb9lIkSsw1Q6NRDuuoyIWc+sVplWvutuaONuHUY5tJ9nnZ8OpxRl6b+kXQZSNKMcdmrDbbX5sbA9mK85nCWEcfecnSeYVaGs2wBo1XdG/eHLngxiNW5JN+r4bc//AHxbw0ghsuSBJ2jSxX/uq9GRR4urAmvAjzrbL6ao8fGnkctzt/z+UJeIPKpSRyrFHDiFaogAi9TkEtZJA8aFHnj6llOv78cfOM+CjGRqod0K25dufZhebEnah44+kZTrjPOtzPTwJ+nH8wjExMTCFyYGk54JxMSzYvUVHU6BKxCcF4mM/wBj9lIbeCmseV1wXWJg+x/P6BvBS2FfEeD637WKaSGQgBilFXAutSsCCRfrCj0utsPsSsdWlad7v0ByT9jM5b0cGtZJ5XmKkMqsAqKw5NoUd5gdwWLUeVYI9JIZ3gb6L2YnG6NIAQp5EiwabSTRrnz2vD7Ew0tPKTtyOJpKkgGHVpXXWuhq0ggX1oEkgX5nF0n2bfwn5YmeLhCYxbbV+ovmRvV4EMuZ7tIvLe657/n9l+FmrrfuPT7JbrO7hftibeeGCyZjS1omqhp5c77w9c9Otjfxxw8mao1HFe9WT5Ve/Og1geIo7G9FFvtHwKM/Ex0PHWuNxIobYNQZSpIurVmF0aNGjhdxMTy5lMwsXZ0qxsNasxAZjqqwtDW33tXKuRDa2Bsxqp0j03zHhR87G9dD15YkLz2uqNdPWgL5G/vnrp8drwriJLJGTtoX5X0nhUsmZmiiZdrkJjD1zI7ULqFdVsYU5XiEfaTyMJ3SQJGjpGza1jLve1kAvK4BIAIAINHGnzBmOrQi7GxqANjRY5Nsde3swTlgxXvqA1nw5Xt1PSuvPHWrQikkZfhkZCEuCHd3lZdu6ZHZwu2x0hgt+WHPHfs0/iHyOGmgeAx6VGOThui0U9ZJp10YefIxs4kI74rcMReklksddJJI9vsxMy1ggsyIpp25FgdICob2stp1bb0Ad9Q182Ws2AP31xx9EPl+63/fh+kFpn25DPVeyiZTIwlVNhVJ3Kr6qclVF8lUBel1fMnHWby4kXSxI3sEGirA2rKejA0Qcan6IfL9+79/pU+iHy/fu/fy49K7vcdWrVVtMfrdiyyhe0VdetSKmUFVLFOaOC62ACpuwRdYGzUkIRu37LQRX1taNRoLdggb9cbn6IfLHn0M+C/4+HPG6MmobW7PNliXrLJFV8GH9G1+oUlVBt6IUCxrZVbblqUKfO8b3KdcV/RD5fv+/wDn9b8vGRd4hjx7G3fZryZd+1VVF2JiYmKCExMTEwATExMTABMTExMAExMTEwATExMTABMTExMAExMTEwATExMTABMTExMAExMTEwATExMTABMTExMAExMTEwATExMTABMTExMAH//Z", - "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRs13WYFHZ6atXysoIMKKTUF7eHv9A3-iWaVw&s", + "https://i.pinimg.com/280x280_RS/44/d2/b0/44d2b0b9e08cf1f05b7215356925a146.jpg", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPe2BEhk6RfeibdWPG-1Iac78Tk1bdO1Rtqg&s", + "https://center.exm.co.kr/data/goodsimg/phob/l/0018/027/18027744/61709_1661145612.jpg", + "https://i.pinimg.com/736x/35/4e/03/354e03cd79702063da7353ffea0c8f8b.jpg", ]; setImageUrls(testImages || []); }, [type]); diff --git a/src/pages/post-page.jsx b/src/pages/post-page.jsx new file mode 100644 index 0000000..38396a4 --- /dev/null +++ b/src/pages/post-page.jsx @@ -0,0 +1,121 @@ +import { useState } from "react"; +import InputTextField from "../components/text-field/text-field"; +import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; +import Colors from "../components/color/colors"; +import ToggleButton from "../components/button/toggle-button"; +import styled from "styled-components"; +import { PrimaryButton } from "../components/button/button"; +import BackgroundSelect from "../components/option/background-select"; + +const PostContainerStyle = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + width: 100%; + margin: 0 auto; +`; + +const WrapperStyle = styled.div` + padding-top: 50px; + width: 720px; +`; + +const PostTitleStyle = styled.h2` + font-weight: 700; +`; + +const PostSummaryStyle = styled.p` + font-weight: 400; + color: Colors.gray(500); +`; + +const PostToggleButtonStyle = styled.div` + width: 100%; + display: flex; +`; + +const ButtonWrapperStyle = styled.div` + padding-top: 50px; + width: 720px; + display: flex; + justify-content: center; + align-items: center; + + & > * { + flex: 1; + } +`; + +function PostPage() { + const [name, setName] = useState(""); + const [nameError, setNameError] = useState(""); + const [backgroundType, setBackgroundType] = useState("컬러"); + const [selected, setSelected] = useState(0); + + const handleChange = (e) => { + const value = e.target.value; + setName(value); + setNameError(""); // 값 입력 중 에러 없애기 + }; + + const handleBlur = () => { + const trimmed = name.trim(); + if (trimmed === "") { + setNameError("값을 입력해 주세요"); + } else if (name !== trimmed) { + setNameError("앞 뒤 공백 없이 입력해 주세요"); // 텍스트 앞 뒤 공백 에러 처리(임시) + } + }; + + const handleBackgroundSelect = (e) => { + let typeSelect = e.target.textContent; + + if (typeSelect === "컬러" || typeSelect === "이미지") { + setBackgroundType(typeSelect); + setSelected(0); + } + }; + + return ( + + + To. + + + + 배경화면을 선택해 주세요. + + 컬러를 선택하거나, 이미지를 선택할 수 있습니다. + + + { + handleBackgroundSelect(type); + setSelected(0); + }} + /> + + + + + + + + ); +} + +export default PostPage; From 8215ff6fb926a3a15dea00a29367a6d10be30dc2 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Fri, 15 Aug 2025 02:43:23 +0900 Subject: [PATCH 084/253] =?UTF-8?q?refactor=20#16=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/image-option-arches.svg | 9 --------- src/assets/image-option-car.svg | 9 --------- 2 files changed, 18 deletions(-) delete mode 100644 src/assets/image-option-arches.svg delete mode 100644 src/assets/image-option-car.svg diff --git a/src/assets/image-option-arches.svg b/src/assets/image-option-arches.svg deleted file mode 100644 index 1420d13..0000000 --- a/src/assets/image-option-arches.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/src/assets/image-option-car.svg b/src/assets/image-option-car.svg deleted file mode 100644 index dbc67a5..0000000 --- a/src/assets/image-option-car.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - From 3402cddc5e4740670d2d00caf6b5df37cf9b4fc1 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Fri, 15 Aug 2025 02:54:23 +0900 Subject: [PATCH 085/253] =?UTF-8?q?feat=20#16=20=EC=9D=B4=EB=A6=84=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=20=EC=8B=9C=20=EC=83=9D=EC=84=B1=ED=95=98?= =?UTF-8?q?=EA=B8=B0=20=EB=B2=84=ED=8A=BC=20=ED=99=9C=EC=84=B1=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/post-page.jsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/pages/post-page.jsx b/src/pages/post-page.jsx index 38396a4..9cbc1cf 100644 --- a/src/pages/post-page.jsx +++ b/src/pages/post-page.jsx @@ -112,7 +112,11 @@ function PostPage() { onSelect={setSelected} /> - + ); From 8de39f14a77bed0d66958cd3bb5f5b99235c4495 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Fri, 15 Aug 2025 03:05:59 +0900 Subject: [PATCH 086/253] =?UTF-8?q?feat=20#16=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=ED=95=98=EA=B8=B0=20=EB=B2=84=ED=8A=BC=20=ED=81=B4=EB=A6=AD?= =?UTF-8?q?=EC=8B=9C=20/post/{id}=EB=A1=9C=20=EC=9D=B4=EB=8F=99(=EB=9E=9C?= =?UTF-8?q?=EB=8D=A4=EC=95=84=EC=9D=B4=EB=94=94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/post-page.jsx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/pages/post-page.jsx b/src/pages/post-page.jsx index 9cbc1cf..bf29c01 100644 --- a/src/pages/post-page.jsx +++ b/src/pages/post-page.jsx @@ -6,6 +6,7 @@ import ToggleButton from "../components/button/toggle-button"; import styled from "styled-components"; import { PrimaryButton } from "../components/button/button"; import BackgroundSelect from "../components/option/background-select"; +import { useNavigate } from "react-router"; const PostContainerStyle = styled.div` display: flex; @@ -52,6 +53,7 @@ function PostPage() { const [nameError, setNameError] = useState(""); const [backgroundType, setBackgroundType] = useState("컬러"); const [selected, setSelected] = useState(0); + const navigate = useNavigate(); const handleChange = (e) => { const value = e.target.value; @@ -77,6 +79,11 @@ function PostPage() { } }; + const handleCreate = () => { + const randomID = Math.floor(Math.random() * 10000); + navigate(`/post/${randomID}`); + }; + return ( @@ -116,6 +123,7 @@ function PostPage() { title="생성하기" size="large" disabled={name === "" || name !== name.trim()} + onClick={handleCreate} /> From adf8637fcacc30b304c12bff936006bddd4576a3 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Fri, 15 Aug 2025 03:41:56 +0900 Subject: [PATCH 087/253] =?UTF-8?q?refactor=20#22=20styled-components=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/post-page.jsx | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/pages/post-page.jsx b/src/pages/post-page.jsx index bf29c01..545add1 100644 --- a/src/pages/post-page.jsx +++ b/src/pages/post-page.jsx @@ -8,7 +8,7 @@ import { PrimaryButton } from "../components/button/button"; import BackgroundSelect from "../components/option/background-select"; import { useNavigate } from "react-router"; -const PostContainerStyle = styled.div` +const PostContainer = styled.div` display: flex; flex-direction: column; justify-content: center; @@ -17,26 +17,26 @@ const PostContainerStyle = styled.div` margin: 0 auto; `; -const WrapperStyle = styled.div` +const Wrapper = styled.div` padding-top: 50px; width: 720px; `; -const PostTitleStyle = styled.h2` +const PostTitle = styled.h2` font-weight: 700; `; -const PostSummaryStyle = styled.p` +const PostSummary = styled.p` font-weight: 400; color: Colors.gray(500); `; -const PostToggleButtonStyle = styled.div` +const PostToggleButton = styled.div` width: 100%; display: flex; `; -const ButtonWrapperStyle = styled.div` +const ButtonWrapper = styled.div` padding-top: 50px; width: 720px; display: flex; @@ -85,8 +85,8 @@ function PostPage() { }; return ( - - + + To. - - - 배경화면을 선택해 주세요. - + + + 배경화면을 선택해 주세요. + 컬러를 선택하거나, 이미지를 선택할 수 있습니다. - - + + - - + + - + - - + + ); } From 7b7257caa271269100429e47941c1cdfa4893c7d Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Fri, 15 Aug 2025 03:43:04 +0900 Subject: [PATCH 088/253] =?UTF-8?q?refactor=20#22=20trimmed=20=EC=99=BC?= =?UTF-8?q?=EC=AA=BD=EC=9C=BC=EB=A1=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/post-page.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pages/post-page.jsx b/src/pages/post-page.jsx index 545add1..69811df 100644 --- a/src/pages/post-page.jsx +++ b/src/pages/post-page.jsx @@ -31,7 +31,7 @@ const PostSummary = styled.p` color: Colors.gray(500); `; -const PostToggleButton = styled.div` +const ToggleButtonWrapper = styled.div` width: 100%; display: flex; `; @@ -65,7 +65,7 @@ function PostPage() { const trimmed = name.trim(); if (trimmed === "") { setNameError("값을 입력해 주세요"); - } else if (name !== trimmed) { + } else if (trimmed !== name) { setNameError("앞 뒤 공백 없이 입력해 주세요"); // 텍스트 앞 뒤 공백 에러 처리(임시) } }; @@ -102,7 +102,7 @@ function PostPage() { 컬러를 선택하거나, 이미지를 선택할 수 있습니다. - + - + Date: Fri, 15 Aug 2025 03:53:40 +0900 Subject: [PATCH 089/253] =?UTF-8?q?refactor=20#22=20styled-component=20?= =?UTF-8?q?=EB=AF=B8=EB=B3=80=EA=B2=BD=EC=9D=B4=EB=A6=84=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.jsx | 3 +- src/pages/create-post-page.jsx | 130 +++++++++++++++++++++++++++++++- src/pages/post-page.jsx | 133 --------------------------------- 3 files changed, 130 insertions(+), 136 deletions(-) delete mode 100644 src/pages/post-page.jsx diff --git a/src/app.jsx b/src/app.jsx index cd03eb8..413efb9 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -9,7 +9,7 @@ import MessagePage from "./pages/message-list"; import RecipientPostPage from "./pages/recipient-post-page"; import SendMessagePage from "./pages/send-message-page"; import TestPage from "./pages/test-page"; -import PostPage from "./pages/post-page"; +import PostPage from "./pages/create-post-page"; import SendPage from "./pages/send-page"; function Provider({ children }) { @@ -69,7 +69,6 @@ function App() {
} /> } /> - } /> } /> diff --git a/src/pages/create-post-page.jsx b/src/pages/create-post-page.jsx index 9645cf3..0635c47 100644 --- a/src/pages/create-post-page.jsx +++ b/src/pages/create-post-page.jsx @@ -1,5 +1,133 @@ +import { useState } from "react"; +import InputTextField from "../components/text-field/text-field"; +import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; +import Colors from "../components/color/colors"; +import ToggleButton from "../components/button/toggle-button"; +import styled from "styled-components"; +import { PrimaryButton } from "../components/button/button"; +import BackgroundSelect from "../components/option/background-select"; +import { useNavigate } from "react-router"; + +const PostContainer = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + width: 100%; + margin: 0 auto; +`; + +const Wrapper = styled.div` + padding-top: 50px; + width: 720px; +`; + +const PostTitle = styled.h2` + font-weight: 700; +`; + +const PostSummary = styled.p` + font-weight: 400; + color: Colors.gray(500); +`; + +const ToggleButtonWrapper = styled.div` + width: 100%; + display: flex; +`; + +const ButtonWrapper = styled.div` + padding-top: 50px; + width: 720px; + display: flex; + justify-content: center; + align-items: center; + + & > * { + flex: 1; + } +`; + function CreatePostPage() { - return

Create Post Page

; + const [name, setName] = useState(""); + const [nameError, setNameError] = useState(""); + const [backgroundType, setBackgroundType] = useState("컬러"); + const [selected, setSelected] = useState(0); + const navigate = useNavigate(); + + const handleChange = (e) => { + const value = e.target.value; + setName(value); + setNameError(""); // 값 입력 중 에러 없애기 + }; + + const handleBlur = () => { + const trimmed = name.trim(); + if (trimmed === "") { + setNameError("값을 입력해 주세요"); + } else if (trimmed !== name) { + setNameError("앞 뒤 공백 없이 입력해 주세요"); // 텍스트 앞 뒤 공백 에러 처리(임시) + } + }; + + const handleBackgroundSelect = (e) => { + let typeSelect = e.target.textContent; + + if (typeSelect === "컬러" || typeSelect === "이미지") { + setBackgroundType(typeSelect); + setSelected(0); + } + }; + + const handleCreate = () => { + const randomID = Math.floor(Math.random() * 10000); + navigate(`/post/${randomID}`); + }; + + return ( + + + To. + + + + 배경화면을 선택해 주세요. + + 컬러를 선택하거나, 이미지를 선택할 수 있습니다. + + + { + handleBackgroundSelect(type); + setSelected(0); + }} + /> + + + + + + + + ); } export default CreatePostPage; diff --git a/src/pages/post-page.jsx b/src/pages/post-page.jsx deleted file mode 100644 index 69811df..0000000 --- a/src/pages/post-page.jsx +++ /dev/null @@ -1,133 +0,0 @@ -import { useState } from "react"; -import InputTextField from "../components/text-field/text-field"; -import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; -import Colors from "../components/color/colors"; -import ToggleButton from "../components/button/toggle-button"; -import styled from "styled-components"; -import { PrimaryButton } from "../components/button/button"; -import BackgroundSelect from "../components/option/background-select"; -import { useNavigate } from "react-router"; - -const PostContainer = styled.div` - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - width: 100%; - margin: 0 auto; -`; - -const Wrapper = styled.div` - padding-top: 50px; - width: 720px; -`; - -const PostTitle = styled.h2` - font-weight: 700; -`; - -const PostSummary = styled.p` - font-weight: 400; - color: Colors.gray(500); -`; - -const ToggleButtonWrapper = styled.div` - width: 100%; - display: flex; -`; - -const ButtonWrapper = styled.div` - padding-top: 50px; - width: 720px; - display: flex; - justify-content: center; - align-items: center; - - & > * { - flex: 1; - } -`; - -function PostPage() { - const [name, setName] = useState(""); - const [nameError, setNameError] = useState(""); - const [backgroundType, setBackgroundType] = useState("컬러"); - const [selected, setSelected] = useState(0); - const navigate = useNavigate(); - - const handleChange = (e) => { - const value = e.target.value; - setName(value); - setNameError(""); // 값 입력 중 에러 없애기 - }; - - const handleBlur = () => { - const trimmed = name.trim(); - if (trimmed === "") { - setNameError("값을 입력해 주세요"); - } else if (trimmed !== name) { - setNameError("앞 뒤 공백 없이 입력해 주세요"); // 텍스트 앞 뒤 공백 에러 처리(임시) - } - }; - - const handleBackgroundSelect = (e) => { - let typeSelect = e.target.textContent; - - if (typeSelect === "컬러" || typeSelect === "이미지") { - setBackgroundType(typeSelect); - setSelected(0); - } - }; - - const handleCreate = () => { - const randomID = Math.floor(Math.random() * 10000); - navigate(`/post/${randomID}`); - }; - - return ( - - - To. - - - - 배경화면을 선택해 주세요. - - 컬러를 선택하거나, 이미지를 선택할 수 있습니다. - - - { - handleBackgroundSelect(type); - setSelected(0); - }} - /> - - - - - - - - ); -} - -export default PostPage; From d4b5841742b43fe8da4113820928a4a8c2b9b0e4 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Fri, 15 Aug 2025 03:57:08 +0900 Subject: [PATCH 090/253] =?UTF-8?q?fix=20#22=20post-page=20->=20create-pos?= =?UTF-8?q?t-page=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/app.jsx b/src/app.jsx index 413efb9..57aad09 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -9,7 +9,6 @@ import MessagePage from "./pages/message-list"; import RecipientPostPage from "./pages/recipient-post-page"; import SendMessagePage from "./pages/send-message-page"; import TestPage from "./pages/test-page"; -import PostPage from "./pages/create-post-page"; import SendPage from "./pages/send-page"; function Provider({ children }) { From ccc7c180f55ba9d825029df45f58094fc731de56 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Fri, 15 Aug 2025 04:08:23 +0900 Subject: [PATCH 091/253] =?UTF-8?q?refactor=20#29=20styled-components=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EC=88=98=EC=A0=95=20/=20handleOnBlur=20->?= =?UTF-8?q?=20handleBlur=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.jsx | 2 - src/pages/create-post-page.jsx | 1 - src/pages/send-message-page.jsx | 88 ++++++++++++++++++++++++++++++- src/pages/send-page.jsx | 91 --------------------------------- 4 files changed, 87 insertions(+), 95 deletions(-) delete mode 100644 src/pages/send-page.jsx diff --git a/src/app.jsx b/src/app.jsx index 57aad09..a061293 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -9,7 +9,6 @@ import MessagePage from "./pages/message-list"; import RecipientPostPage from "./pages/recipient-post-page"; import SendMessagePage from "./pages/send-message-page"; import TestPage from "./pages/test-page"; -import SendPage from "./pages/send-page"; function Provider({ children }) { return ( @@ -68,7 +67,6 @@ function App() {
} /> } /> - } /> diff --git a/src/pages/create-post-page.jsx b/src/pages/create-post-page.jsx index 0635c47..1d07a97 100644 --- a/src/pages/create-post-page.jsx +++ b/src/pages/create-post-page.jsx @@ -42,7 +42,6 @@ const ButtonWrapper = styled.div` display: flex; justify-content: center; align-items: center; - & > * { flex: 1; } diff --git a/src/pages/send-message-page.jsx b/src/pages/send-message-page.jsx index 9bab5b6..86a3d68 100644 --- a/src/pages/send-message-page.jsx +++ b/src/pages/send-message-page.jsx @@ -1,5 +1,91 @@ +import { useState } from "react"; +import InputTextField from "../components/text-field/text-field"; +import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; +import Colors from "../components/color/colors"; +import ToggleButton from "../components/button/toggle-button"; +import styled from "styled-components"; + +const SendContainer = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + width: 100%; + margin: 0 auto; +`; + +const Wrapper = styled.div` + padding-top: 50px; + width: 720px; +`; + +const SendTitle = styled.h2` + font-weight: 700; +`; + +const SendSummary = styled.p` + font-weight: 400; + color: Colors.gray(500); +`; + +const ToggleButtonWrapper = styled.div` + width: 100%; + display: flex; +`; + function SendMessagePage() { - return

Send Message Page

; + const [name, setName] = useState(""); + const [nameError, setNameError] = useState(""); + + const handleChange = (e) => { + const value = e.target.value; + setName(value); + + // 값 입력 중 에러 없애기 + if (nameError) { + setNameError(""); + } + }; + + const handleBlur = () => { + if (name.trim() === "") { + setNameError("값을 입력해 주세요"); + } else if (name !== name.trim()) { + setNameError("공백 없이 입력해 주세요"); // 텍스트 앞 뒤 공백 에러 처리(임시) + } + }; + + return ( + + + From. + + + + 프로필 이미지 + 프로필 이미지를 선택해 주세요! + + + 상대와의 관계 + + + 내용을 입력해 주세요 + + + 폰트 선택 + + + + + + ); } export default SendMessagePage; diff --git a/src/pages/send-page.jsx b/src/pages/send-page.jsx deleted file mode 100644 index c0d2391..0000000 --- a/src/pages/send-page.jsx +++ /dev/null @@ -1,91 +0,0 @@ -import { useState } from "react"; -import InputTextField from "../components/text-field/text-field"; -import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; -import Colors from "../components/color/colors"; -import ToggleButton from "../components/button/toggle-button"; -import styled from "styled-components"; - -const SendContainerStyle = styled.div` - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; - width: 100%; - margin: 0 auto; -`; - -const WrapperStyle = styled.div` - padding-top: 50px; - width: 720px; -`; - -const SendTitleStyle = styled.h2` - font-weight: 700; -`; - -const SendSummaryStyle = styled.p` - font-weight: 400; - color: Colors.gray(500); -`; - -const SendToggleButtonStyle = styled.div` - width: 100%; - display: flex; -`; - -function SendPage() { - const [name, setName] = useState(""); - const [nameError, setNameError] = useState(""); - - const handleChange = (e) => { - const value = e.target.value; - setName(value); - - // 값 입력 중 에러 없애기 - if (nameError) { - setNameError(""); - } - }; - - const handleOnBlur = () => { - if (name.trim() === "") { - setNameError("값을 입력해 주세요"); - } else if (name !== name.trim()) { - setNameError("공백 없이 입력해 주세요"); // 텍스트 앞 뒤 공백 에러 처리(임시) - } - }; - - return ( - - - From. - - - - 프로필 이미지 - 프로필 이미지를 선택해 주세요! - - - 상대와의 관계 - - - 내용을 입력해 주세요 - - - 폰트 선택 - - - - - - ); -} - -export default SendPage; From fbdabdd1b516b1a12c953f8b9148280694befbfb Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Fri, 15 Aug 2025 04:28:51 +0900 Subject: [PATCH 092/253] =?UTF-8?q?feat=20#29=20=EC=83=81=EB=8C=80?= =?UTF-8?q?=EC=99=80=EC=9D=98=20=EA=B4=80=EA=B3=84=20=EB=93=9C=EB=9E=8D?= =?UTF-8?q?=EB=8B=A4=EC=9A=B4=20=ED=85=8D=EC=8A=A4=ED=8A=B8=20=ED=95=84?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/send-message-page.jsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/pages/send-message-page.jsx b/src/pages/send-message-page.jsx index 86a3d68..37bfe2c 100644 --- a/src/pages/send-message-page.jsx +++ b/src/pages/send-message-page.jsx @@ -36,6 +36,7 @@ const ToggleButtonWrapper = styled.div` function SendMessagePage() { const [name, setName] = useState(""); const [nameError, setNameError] = useState(""); + const [option, setOption] = useState("지인"); const handleChange = (e) => { const value = e.target.value; @@ -74,6 +75,14 @@ function SendMessagePage() { 상대와의 관계 + 내용을 입력해 주세요 From 0903c48be31fe683ba5ed57f1f11e2a93800c3c7 Mon Sep 17 00:00:00 2001 From: luli Date: Fri, 15 Aug 2025 06:18:09 +0900 Subject: [PATCH 093/253] =?UTF-8?q?[#43]=20rolling=20paper=20list=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80,=20=EB=82=B4=EB=B6=80=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EB=B6=84=EB=A6=AC=20=EB=B0=8F=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=A0=95=EB=A0=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rolling paper list 페이지, 내부 컴포넌트 분리 및 데이터 정렬 --- .../components/rolling-paper-list.jsx | 144 +++++++ src/pages/rolling-paper-list-page.jsx | 222 +++------- src/pages/test_recipients_data.json | 400 +++++++++--------- 3 files changed, 395 insertions(+), 371 deletions(-) diff --git a/src/features/rolling-paper/components/rolling-paper-list.jsx b/src/features/rolling-paper/components/rolling-paper-list.jsx index e69de29..37b58c1 100644 --- a/src/features/rolling-paper/components/rolling-paper-list.jsx +++ b/src/features/rolling-paper/components/rolling-paper-list.jsx @@ -0,0 +1,144 @@ +import ArrowButton from "../../../components/button/arrow-button"; +import ARROW_BUTTON_DIRECTION from "../../../components/button/arrow-button-direction"; +import { + OutlinedButton, + PrimaryButton, + SecondaryButton, +} from "../../../components/button/button"; +import BUTTON_SIZE from "../../../components/button/button-size"; +import ToggleButton from "../../../components/button/toggle-button"; + +import React, { useEffect, useState } from "react"; + +import styled from "styled-components"; + +const backgroundColors = { + beige: "#FFD382", + purple: "#DCB9FF", + green: "#9BE282", + blue: "#9DDDFF", +}; + +const CardContainer = styled.div` + display: grid; + grid-template-columns: 275px 275px 275px 275px; + gap: 20px; + width: fit-content; + + position: relative; + overflow: visible; +`; + +const CardItem = styled.div.withConfig({ + shouldForwardProp: (prop) => prop !== "backgroundColor", +})` + width: 275px; + height: 260px; + border-radius: 16px; + text-align: left; + padding: 30px 24px 20px 24px; + box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1); + + display: grid; + grid-template-rows: 1fr 1fr auto; + + background-color: ${(props) => + backgroundColors[props.backgroundColor] || "white"}; + + img { + height: 28px; + width: 28px; + border-radius: 50%; + border: 1px solid #ffffff; + + margin-left: -12px; + &:first-child { + margin-left: 0; + } + } + + div.message-images { + display: flex; + } + + div.over-profile { + height: 28px; + width: 28px; + background-color: #ffffff; + border-radius: 50%; + + margin-left: -12px; + + display: flex; + justify-content: center; + align-items: center; + font-size: 12px; + } + + h2 { + margin: 0; + } + + div.emoji-div { + border-top: 1px solid red; + } +`; + +const NextButtonWrapper = styled.div` + position: absolute; + right: -20px; + top: 50%; + transform: translateY(-50%); + z-index: 10; +`; + +const PreviewButtonWrapper = styled.div` + position: absolute; + left: -20px; + top: 50%; + transform: translateY(-50%); + z-index: 10; +`; + +function RollingPaperList({ cardData, totalPages, currentPage, onTurnCards }) { + return ( + + {cardData.map((item) => ( + +

To. {item.name}

+
+ {item.recentMessages.slice(0, 3).map((messageItem, index) => ( + {`profile-${index}`} + ))} + {item.messageCount > 3 ? ( +
+ +{item.messageCount - 3} +
+ ) : null} +
+ + {item.messageCount}명이 작성했어요! + +
test
+
+ ))} + {currentPage > 0 ? ( + onTurnCards("preview")}> + + + ) : null} + {currentPage < totalPages - 1 ? ( + onTurnCards("next")}> + + + ) : null} +
+ ); +} + +export default RollingPaperList; diff --git a/src/pages/rolling-paper-list-page.jsx b/src/pages/rolling-paper-list-page.jsx index be7816d..3b6e839 100644 --- a/src/pages/rolling-paper-list-page.jsx +++ b/src/pages/rolling-paper-list-page.jsx @@ -13,13 +13,7 @@ import axiosInstance from "../api/axios-instance"; import testDataFile from "./test_recipients_data.json"; import styled from "styled-components"; - -const backgroundColors = { - beige: "#FFD382", - purple: "#DCB9FF", - green: "#9BE282", - blue: "#9DDDFF", -}; +import RollingPaperList from "../features/rolling-paper/components/rolling-paper-list"; const TopContainer = styled.div` text-align: center; @@ -33,93 +27,25 @@ const CardTitle = styled.h2` text-align: left; `; -const CardContainer = styled.div` - border: 1px solid red; - display: grid; - grid-template-columns: 275px 275px 275px 275px; - gap: 20px; - width: fit-content; - - position: relative; - overflow: visible; -`; - -const CardItem = styled.div` - width: 275px; - height: 260px; - border: 1px solid red; - text-align: left; - padding: 30px 24px 20px 24px; - - display: grid; - grid-template-rows: 1fr 1fr auto; - - background-color: ${(props) => - backgroundColors[props.backgroundColor] || "white"}; - - img { - height: 28px; - width: 28px; - border-radius: 50%; - border: 1px solid #ffffff; - - margin-left: -12px; - &:first-child { - margin-left: 0; - } - } - - div.message-images { - display: flex; - } - - div.over-profile { - height: 28px; - width: 28px; - background-color: #ffffff; - border-radius: 50%; - - margin-left: -12px; - - display: flex; - justify-content: center; - align-items: center; - font-size: 12px; - } - - h2 { - margin: 0; - } - - div.emoji-div { - border-top: 1px solid red; - } -`; - -const NextButtonWrapper = styled.div` - position: absolute; - right: -20px; - top: 50%; - transform: translateY(-50%); - z-index: 10; -`; - -const PreviewButtonWrapper = styled.div` - position: absolute; - left: -20px; - top: 50%; - transform: translateY(-50%); - z-index: 10; -`; - const MakingButton = styled(PrimaryButton)` margin-top: 64px; font-weight: 400; padding: 14px 60px; `; +const cache = {}; +function getCachedImage(url) { + if (!cache[url]) { + cache[url] = new Image(); + cache[url].src = url; + } + return cache[url].src; +} + function ShowMessageList() { const [testData, setTestData] = useState([]); + const [popularDataList, setPopularDataList] = useState([]); + const [recentDataList, setRecentDataList] = useState([]); const [popularCurrentPage, setPopularCurrentPage] = useState(0); const [recentCurrentPage, setRecentCurrentPage] = useState(0); const [popularrecentShowCards, setPopularrecentShowCards] = useState([]); @@ -139,6 +65,24 @@ function ShowMessageList() { // }); }, []); + useEffect(() => { + testData.forEach((item) => { + getCachedImage(item.imageURL); + }); + }, [testData]); + + useEffect(() => { + const sortedPopular = testData + .slice() + .sort((a, b) => b.messageCount - a.messageCount); + setPopularDataList(sortedPopular); + + const sortedRecent = testData + .slice() + .sort((a, b) => b.createdAt - a.createdAt); + setRecentDataList(sortedRecent); + }, [testData]); + const totalPages = Math.ceil(testData.length / cardCount); useEffect(() => { @@ -148,14 +92,17 @@ function ShowMessageList() { const popularStartPageNum = popularCurrentPage * cardCount; const popularEndPageNum = popularStartPageNum + cardCount; - /* createdAt(생성된 시점)에 따라서 정렬 */ - setRecentShowCards(testData.slice(startPageNum, endPageNum)); - - /* 여기서 messageCount(메시지수)에 따라서 정렬 */ setPopularrecentShowCards( - testData.slice(popularStartPageNum, popularEndPageNum) + popularDataList.slice(popularStartPageNum, popularEndPageNum) ); - }, [popularCurrentPage, recentCurrentPage, testData]); + setRecentShowCards(recentDataList.slice(startPageNum, endPageNum)); + }, [ + popularCurrentPage, + recentCurrentPage, + testData, + popularDataList, + recentDataList, + ]); const handleTurnCards = (direction, mode) => { const current = mode === "popular" ? popularCurrentPage : recentCurrentPage; @@ -176,89 +123,22 @@ function ShowMessageList() {
인기 롤링 페이퍼 🔥 - - {popularrecentShowCards.map((item) => ( - -

To. {item.name}

-
- {item.recentMessages.slice(0, 3).map((messageItem, index) => ( - {`profile-${index}`} - ))} - {item.messageCount > 3 ? ( -
- +{item.messageCount - 3} -
- ) : null} -
- - {item.messageCount}명이 작성했어요! - -
test
-
- ))} - {popularCurrentPage > 0 ? ( - handleTurnCards("preview", "popular")} - > - - - ) : null} - {popularCurrentPage < totalPages - 1 ? ( - handleTurnCards("next", "popular")} - > - - - ) : null} -
+ handleTurnCards(direction, "popular")} + />
최근에 만든 롤링 페이퍼 ⭐ - - {recentShowCards.map((item) => ( - -

To. {item.name}

-
- {item.recentMessages.slice(0, 3).map((messageItem, index) => ( - {`profile-${index}`} - ))} - {item.messageCount > 3 ? ( -
- +{item.messageCount - 3} -
- ) : null} -
- - {item.messageCount}명이 작성했어요! - -
- ))} - {recentCurrentPage > 0 ? ( - handleTurnCards("preview", "recent")} - > - - - ) : null} - {recentCurrentPage < totalPages - 1 ? ( - handleTurnCards("next", "recent")} - > - - - ) : null} -
+ handleTurnCards(direction, "recent")} + />
diff --git a/src/pages/test_recipients_data.json b/src/pages/test_recipients_data.json index 3111f67..3d307a2 100644 --- a/src/pages/test_recipients_data.json +++ b/src/pages/test_recipients_data.json @@ -1,7 +1,7 @@ [ { "id": 7024, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "beige", "backgroundImageURL": null, "createdAt": "2023-10-22T19:15:11Z", @@ -151,10 +151,10 @@ { "id": 30238, "recipientId": 43558, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/340/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 32", + "content": "Suwon Kim님의 메세지 내용 32", "font": "Nanum Gothic", "createdAt": "2023-06-17T00:31:29Z" }, @@ -263,7 +263,7 @@ }, { "id": 18499, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "beige", "backgroundImageURL": "https://picsum.photos/seed/18499/600/400", "createdAt": "2023-06-03T04:15:47Z", @@ -272,10 +272,10 @@ { "id": 48979, "recipientId": 18499, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/11/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 77", + "content": "Suwon Kim님의 메세지 내용 77", "font": "Nanum Gothic", "createdAt": "2023-08-25T00:15:25Z" }, @@ -292,10 +292,10 @@ { "id": 35753, "recipientId": 18499, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/173/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 67", + "content": "Suwon Kim님의 메세지 내용 67", "font": "Nanum Gothic", "createdAt": "2023-07-23T23:14:30Z" } @@ -467,7 +467,7 @@ }, { "id": 13425, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "beige", "backgroundImageURL": "https://picsum.photos/seed/13425/600/400", "createdAt": "2023-07-06T20:30:52Z", @@ -567,10 +567,10 @@ { "id": 34424, "recipientId": 97436, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/141/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 6", + "content": "Suwon Kim님의 메세지 내용 6", "font": "Nanum Gothic", "createdAt": "2023-06-01T12:35:35Z" }, @@ -616,7 +616,7 @@ }, { "id": 22932, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "blue", "backgroundImageURL": "https://picsum.photos/seed/22932/600/400", "createdAt": "2023-12-21T05:29:02Z", @@ -779,10 +779,10 @@ { "id": 88963, "recipientId": 2194, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/317/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 81", + "content": "Suwon Kim님의 메세지 내용 81", "font": "Nanum Gothic", "createdAt": "2023-03-12T08:38:10Z" } @@ -992,7 +992,7 @@ }, { "id": 45901, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "purple", "backgroundImageURL": null, "createdAt": "2023-06-14T15:34:31Z", @@ -1165,10 +1165,10 @@ { "id": 99518, "recipientId": 84532, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/2/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 83", + "content": "Suwon Kim님의 메세지 내용 83", "font": "Nanum Gothic", "createdAt": "2023-07-12T22:08:05Z" }, @@ -1243,10 +1243,10 @@ { "id": 72173, "recipientId": 85839, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/137/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 84", + "content": "Suwon Kim님의 메세지 내용 84", "font": "Pretendard", "createdAt": "2023-04-01T12:40:19Z" } @@ -1359,10 +1359,10 @@ { "id": 20559, "recipientId": 76172, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/315/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 53", + "content": "Suwon Kim님의 메세지 내용 53", "font": "Roboto", "createdAt": "2023-07-06T05:06:42Z" }, @@ -1475,10 +1475,10 @@ { "id": 26243, "recipientId": 525, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/470/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 36", + "content": "Suwon Kim님의 메세지 내용 36", "font": "Noto Sans", "createdAt": "2024-02-01T22:09:11Z" }, @@ -1642,10 +1642,10 @@ { "id": 8442, "recipientId": 76854, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/391/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 6", + "content": "Suwon Kim님의 메세지 내용 6", "font": "Pretendard", "createdAt": "2023-12-21T09:27:19Z" }, @@ -1690,10 +1690,10 @@ { "id": 3111, "recipientId": 50919, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/384/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 80", + "content": "Suwon Kim님의 메세지 내용 80", "font": "Pretendard", "createdAt": "2023-08-12T11:51:00Z" }, @@ -1971,7 +1971,7 @@ }, { "id": 5465, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "beige", "backgroundImageURL": null, "createdAt": "2023-01-10T18:10:25Z", @@ -2353,10 +2353,10 @@ { "id": 66552, "recipientId": 90385, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/498/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 36", + "content": "Suwon Kim님의 메세지 내용 36", "font": "Noto Sans", "createdAt": "2023-10-17T11:54:41Z" } @@ -2497,10 +2497,10 @@ { "id": 59673, "recipientId": 39122, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/467/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 15", + "content": "Suwon Kim님의 메세지 내용 15", "font": "Nanum Gothic", "createdAt": "2023-03-20T07:58:11Z" }, @@ -2570,10 +2570,10 @@ { "id": 87956, "recipientId": 36279, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/362/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 45", + "content": "Suwon Kim님의 메세지 내용 45", "font": "Pretendard", "createdAt": "2023-01-10T01:43:19Z" } @@ -2802,10 +2802,10 @@ { "id": 60985, "recipientId": 2640, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/440/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 52", + "content": "Suwon Kim님의 메세지 내용 52", "font": "Pretendard", "createdAt": "2023-05-11T23:03:58Z" }, @@ -3256,20 +3256,20 @@ { "id": 96788, "recipientId": 73648, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/249/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 54", + "content": "Suwon Kim님의 메세지 내용 54", "font": "Nanum Gothic", "createdAt": "2023-09-16T01:58:06Z" }, { "id": 20726, "recipientId": 73648, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/431/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 78", + "content": "Suwon Kim님의 메세지 내용 78", "font": "Pretendard", "createdAt": "2023-07-25T07:59:44Z" } @@ -3725,10 +3725,10 @@ { "id": 65998, "recipientId": 73391, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/117/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 7", + "content": "Suwon Kim님의 메세지 내용 7", "font": "Noto Sans", "createdAt": "2023-06-29T21:54:39Z" } @@ -3953,7 +3953,7 @@ }, { "id": 26744, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "beige", "backgroundImageURL": null, "createdAt": "2023-03-23T03:14:00Z", @@ -4098,10 +4098,10 @@ { "id": 35228, "recipientId": 90477, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/94/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 63", + "content": "Suwon Kim님의 메세지 내용 63", "font": "Roboto", "createdAt": "2023-05-25T06:02:55Z" }, @@ -4457,7 +4457,7 @@ }, { "id": 31714, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "beige", "backgroundImageURL": "https://picsum.photos/seed/31714/600/400", "createdAt": "2023-01-13T08:26:56Z", @@ -4529,10 +4529,10 @@ { "id": 88820, "recipientId": 24976, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/355/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 72", + "content": "Suwon Kim님의 메세지 내용 72", "font": "Pretendard", "createdAt": "2023-12-02T16:28:28Z" } @@ -4713,10 +4713,10 @@ { "id": 35658, "recipientId": 9191, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/62/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 27", + "content": "Suwon Kim님의 메세지 내용 27", "font": "Nanum Gothic", "createdAt": "2023-04-09T12:56:46Z" }, @@ -4733,10 +4733,10 @@ { "id": 20041, "recipientId": 9191, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/114/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 72", + "content": "Suwon Kim님의 메세지 내용 72", "font": "Pretendard", "createdAt": "2023-11-11T12:43:30Z" } @@ -4834,10 +4834,10 @@ { "id": 53736, "recipientId": 625, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/411/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 98", + "content": "Suwon Kim님의 메세지 내용 98", "font": "Nanum Gothic", "createdAt": "2023-06-06T17:47:12Z" }, @@ -4907,10 +4907,10 @@ { "id": 53607, "recipientId": 23417, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/402/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 96", + "content": "Suwon Kim님의 메세지 내용 96", "font": "Noto Sans", "createdAt": "2023-06-28T04:25:20Z" } @@ -5081,10 +5081,10 @@ { "id": 76625, "recipientId": 48647, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/256/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 98", + "content": "Suwon Kim님의 메세지 내용 98", "font": "Pretendard", "createdAt": "2023-03-21T02:42:08Z" }, @@ -5144,10 +5144,10 @@ { "id": 90888, "recipientId": 7110, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/19/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 42", + "content": "Suwon Kim님의 메세지 내용 42", "font": "Roboto", "createdAt": "2023-09-16T18:15:50Z" }, @@ -5256,7 +5256,7 @@ }, { "id": 75973, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "beige", "backgroundImageURL": "https://picsum.photos/seed/75973/600/400", "createdAt": "2023-04-29T23:14:33Z", @@ -5265,10 +5265,10 @@ { "id": 85401, "recipientId": 75973, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/269/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 90", + "content": "Suwon Kim님의 메세지 내용 90", "font": "Noto Sans", "createdAt": "2023-11-12T05:17:44Z" }, @@ -5755,7 +5755,7 @@ }, { "id": 32314, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "purple", "backgroundImageURL": null, "createdAt": "2023-06-09T07:16:23Z", @@ -5774,10 +5774,10 @@ { "id": 10034, "recipientId": 32314, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/288/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 22", + "content": "Suwon Kim님의 메세지 내용 22", "font": "Pretendard", "createdAt": "2023-09-14T13:27:24Z" }, @@ -5938,10 +5938,10 @@ { "id": 50489, "recipientId": 63219, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/11/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 77", + "content": "Suwon Kim님의 메세지 내용 77", "font": "Noto Sans", "createdAt": "2023-11-27T08:16:32Z" } @@ -5962,7 +5962,7 @@ }, { "id": 32218, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "beige", "backgroundImageURL": null, "createdAt": "2023-07-22T22:33:51Z", @@ -6107,10 +6107,10 @@ { "id": 24988, "recipientId": 1341, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/423/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 64", + "content": "Suwon Kim님의 메세지 내용 64", "font": "Roboto", "createdAt": "2023-01-06T05:53:05Z" } @@ -6184,7 +6184,7 @@ }, { "id": 93438, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "blue", "backgroundImageURL": "https://picsum.photos/seed/93438/600/400", "createdAt": "2023-04-02T11:00:53Z", @@ -6203,10 +6203,10 @@ { "id": 6156, "recipientId": 93438, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/109/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 59", + "content": "Suwon Kim님의 메세지 내용 59", "font": "Noto Sans", "createdAt": "2023-01-24T10:30:39Z" }, @@ -6232,7 +6232,7 @@ }, { "id": 44334, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "blue", "backgroundImageURL": "https://picsum.photos/seed/44334/600/400", "createdAt": "2023-12-30T01:42:47Z", @@ -6353,7 +6353,7 @@ }, { "id": 44928, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "beige", "backgroundImageURL": null, "createdAt": "2023-11-24T12:12:26Z", @@ -6405,10 +6405,10 @@ { "id": 31761, "recipientId": 94539, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/62/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 53", + "content": "Suwon Kim님의 메세지 내용 53", "font": "Pretendard", "createdAt": "2023-04-17T18:23:36Z" }, @@ -6970,10 +6970,10 @@ { "id": 41596, "recipientId": 43809, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/439/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 36", + "content": "Suwon Kim님의 메세지 내용 36", "font": "Roboto", "createdAt": "2023-02-12T07:13:07Z" }, @@ -7086,10 +7086,10 @@ { "id": 62162, "recipientId": 62125, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/293/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 93", + "content": "Suwon Kim님의 메세지 내용 93", "font": "Roboto", "createdAt": "2023-04-29T23:05:56Z" } @@ -7207,10 +7207,10 @@ { "id": 91516, "recipientId": 58844, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/108/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 82", + "content": "Suwon Kim님의 메세지 내용 82", "font": "Pretendard", "createdAt": "2023-08-27T12:05:46Z" } @@ -7260,10 +7260,10 @@ { "id": 29903, "recipientId": 72437, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/106/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 40", + "content": "Suwon Kim님의 메세지 내용 40", "font": "Roboto", "createdAt": "2023-04-29T16:49:48Z" } @@ -7323,10 +7323,10 @@ { "id": 91691, "recipientId": 31124, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/461/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 53", + "content": "Suwon Kim님의 메세지 내용 53", "font": "Roboto", "createdAt": "2023-05-21T09:55:42Z" } @@ -7347,7 +7347,7 @@ }, { "id": 73111, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "blue", "backgroundImageURL": null, "createdAt": "2023-12-29T11:24:51Z", @@ -7419,10 +7419,10 @@ { "id": 2974, "recipientId": 44599, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/46/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 13", + "content": "Suwon Kim님의 메세지 내용 13", "font": "Roboto", "createdAt": "2023-11-11T07:56:34Z" }, @@ -7710,7 +7710,7 @@ }, { "id": 72332, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "purple", "backgroundImageURL": "https://picsum.photos/seed/72332/600/400", "createdAt": "2023-10-08T20:12:12Z", @@ -7815,10 +7815,10 @@ { "id": 47612, "recipientId": 6048, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/97/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 72", + "content": "Suwon Kim님의 메세지 내용 72", "font": "Pretendard", "createdAt": "2023-12-11T12:42:57Z" }, @@ -7888,10 +7888,10 @@ { "id": 54283, "recipientId": 7768, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/368/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 8", + "content": "Suwon Kim님의 메세지 내용 8", "font": "Nanum Gothic", "createdAt": "2023-02-19T15:25:55Z" }, @@ -7946,10 +7946,10 @@ { "id": 66344, "recipientId": 60032, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/444/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 47", + "content": "Suwon Kim님의 메세지 내용 47", "font": "Pretendard", "createdAt": "2023-07-26T07:54:55Z" } @@ -8418,10 +8418,10 @@ { "id": 48175, "recipientId": 96506, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/145/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 86", + "content": "Suwon Kim님의 메세지 내용 86", "font": "Pretendard", "createdAt": "2023-03-13T10:17:35Z" }, @@ -8607,10 +8607,10 @@ { "id": 11805, "recipientId": 10732, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/76/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 48", + "content": "Suwon Kim님의 메세지 내용 48", "font": "Nanum Gothic", "createdAt": "2023-12-29T05:06:21Z" } @@ -8708,10 +8708,10 @@ { "id": 94450, "recipientId": 64061, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/353/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 61", + "content": "Suwon Kim님의 메세지 내용 61", "font": "Pretendard", "createdAt": "2023-12-02T06:48:01Z" }, @@ -8737,7 +8737,7 @@ }, { "id": 15549, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "blue", "backgroundImageURL": null, "createdAt": "2023-12-13T10:07:11Z", @@ -8819,10 +8819,10 @@ { "id": 67124, "recipientId": 84213, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/482/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 81", + "content": "Suwon Kim님의 메세지 내용 81", "font": "Pretendard", "createdAt": "2023-04-16T14:42:59Z" }, @@ -8930,10 +8930,10 @@ { "id": 91701, "recipientId": 83558, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/169/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 97", + "content": "Suwon Kim님의 메세지 내용 97", "font": "Noto Sans", "createdAt": "2023-11-22T09:50:03Z" }, @@ -9061,10 +9061,10 @@ { "id": 86215, "recipientId": 1220, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/419/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 25", + "content": "Suwon Kim님의 메세지 내용 25", "font": "Pretendard", "createdAt": "2023-05-10T21:59:12Z" } @@ -9085,7 +9085,7 @@ }, { "id": 53959, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "blue", "backgroundImageURL": "https://picsum.photos/seed/53959/600/400", "createdAt": "2023-08-24T05:22:48Z", @@ -9114,10 +9114,10 @@ { "id": 59151, "recipientId": 53959, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/10/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 4", + "content": "Suwon Kim님의 메세지 내용 4", "font": "Nanum Gothic", "createdAt": "2023-03-11T07:04:18Z" } @@ -9216,7 +9216,7 @@ }, { "id": 51432, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "beige", "backgroundImageURL": "https://picsum.photos/seed/51432/600/400", "createdAt": "2023-11-07T07:07:37Z", @@ -9235,10 +9235,10 @@ { "id": 33808, "recipientId": 51432, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/478/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 8", + "content": "Suwon Kim님의 메세지 내용 8", "font": "Pretendard", "createdAt": "2023-04-04T10:06:15Z" }, @@ -9742,10 +9742,10 @@ { "id": 93059, "recipientId": 73798, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/252/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 99", + "content": "Suwon Kim님의 메세지 내용 99", "font": "Roboto", "createdAt": "2023-11-21T09:01:45Z" }, @@ -9868,10 +9868,10 @@ { "id": 33941, "recipientId": 3992, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/364/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 93", + "content": "Suwon Kim님의 메세지 내용 93", "font": "Pretendard", "createdAt": "2023-02-13T23:03:26Z" }, @@ -9964,10 +9964,10 @@ { "id": 89359, "recipientId": 63758, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/401/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 53", + "content": "Suwon Kim님의 메세지 내용 53", "font": "Roboto", "createdAt": "2023-05-10T19:04:15Z" }, @@ -10084,7 +10084,7 @@ }, { "id": 63096, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "blue", "backgroundImageURL": "https://picsum.photos/seed/63096/600/400", "createdAt": "2023-08-25T09:30:08Z", @@ -10093,10 +10093,10 @@ { "id": 72995, "recipientId": 63096, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/368/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 44", + "content": "Suwon Kim님의 메세지 내용 44", "font": "Pretendard", "createdAt": "2023-10-07T18:41:59Z" }, @@ -10151,10 +10151,10 @@ { "id": 44494, "recipientId": 13289, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/118/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 64", + "content": "Suwon Kim님의 메세지 내용 64", "font": "Nanum Gothic", "createdAt": "2024-01-29T16:37:33Z" }, @@ -10534,10 +10534,10 @@ { "id": 33150, "recipientId": 66190, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/26/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 47", + "content": "Suwon Kim님의 메세지 내용 47", "font": "Roboto", "createdAt": "2024-01-22T00:03:15Z" } @@ -10558,7 +10558,7 @@ }, { "id": 68635, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "beige", "backgroundImageURL": null, "createdAt": "2023-10-22T10:14:45Z", @@ -10625,10 +10625,10 @@ { "id": 8378, "recipientId": 52236, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/383/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 53", + "content": "Suwon Kim님의 메세지 내용 53", "font": "Pretendard", "createdAt": "2023-12-03T19:03:51Z" } @@ -10663,10 +10663,10 @@ { "id": 14027, "recipientId": 81115, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/400/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 48", + "content": "Suwon Kim님의 메세지 내용 48", "font": "Noto Sans", "createdAt": "2023-09-18T14:09:01Z" }, @@ -10885,10 +10885,10 @@ { "id": 16314, "recipientId": 60, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/345/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 52", + "content": "Suwon Kim님의 메세지 내용 52", "font": "Roboto", "createdAt": "2023-03-07T04:55:33Z" } @@ -10928,10 +10928,10 @@ { "id": 81467, "recipientId": 66554, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/487/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 17", + "content": "Suwon Kim님의 메세지 내용 17", "font": "Nanum Gothic", "createdAt": "2023-03-16T05:19:39Z" }, @@ -11155,10 +11155,10 @@ { "id": 19962, "recipientId": 31459, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/80/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 11", + "content": "Suwon Kim님의 메세지 내용 11", "font": "Nanum Gothic", "createdAt": "2023-11-26T04:31:20Z" } @@ -11402,10 +11402,10 @@ { "id": 24156, "recipientId": 41885, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/360/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 14", + "content": "Suwon Kim님의 메세지 내용 14", "font": "Noto Sans", "createdAt": "2023-07-13T21:35:18Z" }, @@ -11816,20 +11816,20 @@ { "id": 86564, "recipientId": 46642, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/36/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 78", + "content": "Suwon Kim님의 메세지 내용 78", "font": "Noto Sans", "createdAt": "2023-09-23T23:48:17Z" }, { "id": 46880, "recipientId": 46642, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/453/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 92", + "content": "Suwon Kim님의 메세지 내용 92", "font": "Noto Sans", "createdAt": "2023-06-07T09:44:08Z" }, @@ -11928,7 +11928,7 @@ }, { "id": 93469, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "beige", "backgroundImageURL": "https://picsum.photos/seed/93469/600/400", "createdAt": "2023-08-05T08:37:01Z", @@ -11991,7 +11991,7 @@ }, { "id": 45950, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "green", "backgroundImageURL": "https://picsum.photos/seed/45950/600/400", "createdAt": "2023-04-24T21:39:46Z", @@ -12489,10 +12489,10 @@ { "id": 46241, "recipientId": 30047, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/397/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 64", + "content": "Suwon Kim님의 메세지 내용 64", "font": "Roboto", "createdAt": "2023-04-12T04:50:45Z" }, @@ -12833,7 +12833,7 @@ }, { "id": 44091, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "blue", "backgroundImageURL": "https://picsum.photos/seed/44091/600/400", "createdAt": "2023-06-17T19:51:45Z", @@ -13349,10 +13349,10 @@ { "id": 58525, "recipientId": 62965, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/103/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 1", + "content": "Suwon Kim님의 메세지 내용 1", "font": "Noto Sans", "createdAt": "2023-04-24T14:22:46Z" }, @@ -13387,10 +13387,10 @@ { "id": 86114, "recipientId": 61614, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/1/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 48", + "content": "Suwon Kim님의 메세지 내용 48", "font": "Noto Sans", "createdAt": "2023-11-16T04:24:55Z" }, @@ -13494,7 +13494,7 @@ }, { "id": 31146, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "green", "backgroundImageURL": null, "createdAt": "2023-09-27T13:42:38Z", @@ -13551,10 +13551,10 @@ { "id": 80875, "recipientId": 99123, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/42/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 14", + "content": "Suwon Kim님의 메세지 내용 14", "font": "Roboto", "createdAt": "2023-11-30T19:44:40Z" }, @@ -13682,10 +13682,10 @@ { "id": 9237, "recipientId": 16143, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/437/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 14", + "content": "Suwon Kim님의 메세지 내용 14", "font": "Pretendard", "createdAt": "2023-03-17T21:44:08Z" } @@ -13793,10 +13793,10 @@ { "id": 31892, "recipientId": 98422, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/8/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 43", + "content": "Suwon Kim님의 메세지 내용 43", "font": "Pretendard", "createdAt": "2023-09-02T03:23:20Z" } @@ -13841,10 +13841,10 @@ { "id": 85445, "recipientId": 53532, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/363/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 51", + "content": "Suwon Kim님의 메세지 내용 51", "font": "Noto Sans", "createdAt": "2023-09-23T11:29:56Z" }, @@ -13904,10 +13904,10 @@ { "id": 86518, "recipientId": 93792, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/204/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 9", + "content": "Suwon Kim님의 메세지 내용 9", "font": "Roboto", "createdAt": "2023-01-22T13:44:09Z" }, @@ -13924,10 +13924,10 @@ { "id": 9752, "recipientId": 93792, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/171/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 68", + "content": "Suwon Kim님의 메세지 내용 68", "font": "Roboto", "createdAt": "2023-02-15T23:39:35Z" } @@ -13992,10 +13992,10 @@ { "id": 84648, "recipientId": 12242, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/112/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 4", + "content": "Suwon Kim님의 메세지 내용 4", "font": "Pretendard", "createdAt": "2024-01-06T11:37:10Z" } @@ -14098,10 +14098,10 @@ { "id": 35816, "recipientId": 76148, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/488/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 96", + "content": "Suwon Kim님의 메세지 내용 96", "font": "Nanum Gothic", "createdAt": "2023-04-09T14:21:56Z" } @@ -14179,10 +14179,10 @@ { "id": 76780, "recipientId": 38642, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/253/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 24", + "content": "Suwon Kim님의 메세지 내용 24", "font": "Nanum Gothic", "createdAt": "2023-07-12T11:54:03Z" }, @@ -14391,10 +14391,10 @@ { "id": 78207, "recipientId": 55884, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/155/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 87", + "content": "Suwon Kim님의 메세지 내용 87", "font": "Pretendard", "createdAt": "2023-06-01T07:21:37Z" }, @@ -14454,10 +14454,10 @@ { "id": 2300, "recipientId": 65809, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/358/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 60", + "content": "Suwon Kim님의 메세지 내용 60", "font": "Roboto", "createdAt": "2023-05-12T09:25:19Z" }, @@ -14527,10 +14527,10 @@ { "id": 12155, "recipientId": 47549, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/247/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 80", + "content": "Suwon Kim님의 메세지 내용 80", "font": "Pretendard", "createdAt": "2023-03-09T22:19:14Z" }, @@ -14620,10 +14620,10 @@ { "id": 64811, "recipientId": 7135, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/184/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 9", + "content": "Suwon Kim님의 메세지 내용 9", "font": "Roboto", "createdAt": "2023-10-17T00:36:13Z" } @@ -15117,10 +15117,10 @@ { "id": 65322, "recipientId": 21977, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/156/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 79", + "content": "Suwon Kim님의 메세지 내용 79", "font": "Nanum Gothic", "createdAt": "2023-09-13T04:30:55Z" } @@ -15155,10 +15155,10 @@ { "id": 37649, "recipientId": 67245, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/160/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 84", + "content": "Suwon Kim님의 메세지 내용 84", "font": "Roboto", "createdAt": "2023-05-09T12:36:18Z" }, @@ -15654,10 +15654,10 @@ { "id": 7778, "recipientId": 37498, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/202/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 24", + "content": "Suwon Kim님의 메세지 내용 24", "font": "Pretendard", "createdAt": "2023-12-27T07:03:22Z" }, @@ -15887,7 +15887,7 @@ }, { "id": 12700, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "purple", "backgroundImageURL": null, "createdAt": "2023-08-18T22:43:12Z", @@ -15916,10 +15916,10 @@ { "id": 4746, "recipientId": 12700, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/260/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 44", + "content": "Suwon Kim님의 메세지 내용 44", "font": "Noto Sans", "createdAt": "2023-02-17T03:59:23Z" } @@ -16181,10 +16181,10 @@ { "id": 47661, "recipientId": 56031, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/395/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 62", + "content": "Suwon Kim님의 메세지 내용 62", "font": "Nanum Gothic", "createdAt": "2023-08-20T17:27:35Z" }, @@ -17115,7 +17115,7 @@ }, { "id": 31249, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "blue", "backgroundImageURL": null, "createdAt": "2023-05-16T17:41:45Z", @@ -17134,10 +17134,10 @@ { "id": 54855, "recipientId": 31249, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/188/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 84", + "content": "Suwon Kim님의 메세지 내용 84", "font": "Pretendard", "createdAt": "2023-07-01T14:34:04Z" } @@ -17163,7 +17163,7 @@ }, { "id": 87008, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "purple", "backgroundImageURL": null, "createdAt": "2023-05-31T18:24:49Z", @@ -17182,10 +17182,10 @@ { "id": 29069, "recipientId": 87008, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/25/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 19", + "content": "Suwon Kim님의 메세지 내용 19", "font": "Roboto", "createdAt": "2024-01-14T03:59:30Z" }, From 541f747854193b699d3b8cd974f54614277f8c19 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Fri, 15 Aug 2025 09:16:51 +0900 Subject: [PATCH 094/253] =?UTF-8?q?fix:=20Merge=20conflict=20text=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/test-page.jsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index fcaad0f..f691c69 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -54,7 +54,6 @@ function TestPage() { const { showsModal, setShowsModal } = useModal(); const handleModalClick = () => setShowsModal(true); -<<<<<<< HEAD /* Popover */ const { popoverPosition, showsPopover, openPopopver, closePopover } = usePopover(); @@ -74,8 +73,6 @@ function TestPage() { }); }; -======= ->>>>>>> upstream/develop return (
Date: Thu, 14 Aug 2025 15:45:50 +0900 Subject: [PATCH 095/253] =?UTF-8?q?refactor=20[#34]=20=EC=9D=B4=EB=A6=84?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD:=20`RecipientPostPage`=20->=20`MessagesPa?= =?UTF-8?q?ge`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.jsx | 4 ++-- src/pages/messages-page.jsx | 5 +++++ src/pages/recipient-post-page.jsx | 5 ----- 3 files changed, 7 insertions(+), 7 deletions(-) create mode 100644 src/pages/messages-page.jsx delete mode 100644 src/pages/recipient-post-page.jsx diff --git a/src/app.jsx b/src/app.jsx index 0052846..33541ea 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -7,7 +7,7 @@ import OnboardingLayout from "./layouts/onboarding-layout"; import CreatePostPage from "./pages/create-post-page"; import MainPage from "./pages/main-page"; import MessagePage from "./pages/message-list"; -import RecipientPostPage from "./pages/recipient-post-page"; +import MessagesPage from "./pages/messages-page"; import SendMessagePage from "./pages/send-message-page"; import TestPage from "./pages/test-page"; @@ -63,7 +63,7 @@ function App() { path=":id" element={ - + } /> diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx new file mode 100644 index 0000000..849b688 --- /dev/null +++ b/src/pages/messages-page.jsx @@ -0,0 +1,5 @@ +function MessagesPage() { + return

Messages Page

; +} + +export default MessagesPage; diff --git a/src/pages/recipient-post-page.jsx b/src/pages/recipient-post-page.jsx deleted file mode 100644 index 26765cb..0000000 --- a/src/pages/recipient-post-page.jsx +++ /dev/null @@ -1,5 +0,0 @@ -function RecipientPostPage() { - return

Recipient Post Page

; -} - -export default RecipientPostPage; From a08deba51cbb434474b1162d94110ad2f7b2fef9 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 14 Aug 2025 22:40:17 +0900 Subject: [PATCH 096/253] =?UTF-8?q?feat=20[#34]=20`MessagesPage`=EC=9D=98?= =?UTF-8?q?=20sub=20header=20=EA=B5=AC=ED=98=84,=20recipient=20=EC=9D=B4?= =?UTF-8?q?=EB=A6=84=20=ED=91=9C=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/rolling-paper-header.jsx | 46 +++++++++++++++++++ src/pages/messages-page.jsx | 11 ++++- 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/features/rolling-paper/components/rolling-paper-header.jsx diff --git a/src/features/rolling-paper/components/rolling-paper-header.jsx b/src/features/rolling-paper/components/rolling-paper-header.jsx new file mode 100644 index 0000000..934db4d --- /dev/null +++ b/src/features/rolling-paper/components/rolling-paper-header.jsx @@ -0,0 +1,46 @@ +import styled from "styled-components"; +import Colors from "../../../components/color/colors"; +import { media } from "../../../utils/media"; + +const StyledRollingPaperHeader = styled.div` + display: flex; + justify-content: center; + align-items: center; + height: 68px; + border-bottom: 1px solid #ededed; + padding: 0 24px; + + ${media.mobile} { + padding: 0 16px; + } +`; + +const HeaderContent = styled.div` + width: 100%; + max-width: 1200px; + display: flex; + justify-content: space-between; + align-items: center; +`; + +const RecipientName = styled.h2` + margin: 0; + font-size: 28px; + font-weight: 700; + line-height: 42px; + color: ${Colors.gray(800)}; +`; + +function RollingPaperHeader({ recipientName }) { + return ( + + +
+ {`To. ${recipientName}`} +
+
+
+ ); +} + +export default RollingPaperHeader; diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx index 849b688..ea2cda0 100644 --- a/src/pages/messages-page.jsx +++ b/src/pages/messages-page.jsx @@ -1,5 +1,14 @@ +import RollingPaperHeader from "../features/rolling-paper/components/rolling-paper-header"; + function MessagesPage() { - return

Messages Page

; + return ( + <> + +
+

Messages Page

+
+ + ); } export default MessagesPage; From 3afd179a81a6ad17325f6fc8623bccd7d3c4fb4b Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 14 Aug 2025 22:41:31 +0900 Subject: [PATCH 097/253] =?UTF-8?q?feat=20[#34]=20`MessagesPage`=20sub=20h?= =?UTF-8?q?eader=EC=97=90=20message=20=EC=B6=94=EA=B0=80,=20=EA=B3=B5?= =?UTF-8?q?=EC=9C=A0=20=EB=B2=84=ED=8A=BC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/ic-share.svg | 3 ++ src/components/button/button.jsx | 10 +++- .../components/rolling-paper-header.jsx | 47 +++++++++++++++++++ 3 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 src/assets/ic-share.svg diff --git a/src/assets/ic-share.svg b/src/assets/ic-share.svg new file mode 100644 index 0000000..f1a707c --- /dev/null +++ b/src/assets/ic-share.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/button/button.jsx b/src/components/button/button.jsx index 283cf4f..e991737 100644 --- a/src/components/button/button.jsx +++ b/src/components/button/button.jsx @@ -192,9 +192,15 @@ const Icon = styled.div` } `; -function OutlinedButton({ title, icon, size, ...props }) { +function OutlinedButton({ className, title, icon, size, ...props }) { return ( - + {icon && size !== BUTTON_SIZE.large ? ( diff --git a/src/features/rolling-paper/components/rolling-paper-header.jsx b/src/features/rolling-paper/components/rolling-paper-header.jsx index 934db4d..a69c515 100644 --- a/src/features/rolling-paper/components/rolling-paper-header.jsx +++ b/src/features/rolling-paper/components/rolling-paper-header.jsx @@ -1,4 +1,8 @@ import styled from "styled-components"; +import addImage from "../../../assets/ic-face-smile-add.svg"; +import shareImage from "../../../assets/ic-share.svg"; +import { OutlinedButton } from "../../../components/button/button"; +import BUTTON_SIZE from "../../../components/button/button-size"; import Colors from "../../../components/color/colors"; import { media } from "../../../utils/media"; @@ -31,6 +35,39 @@ const RecipientName = styled.h2` color: ${Colors.gray(800)}; `; +const Divider = styled.div` + width: 1px; + height: 28px; + background-color: ${Colors.gray(200)}; +`; + +const StyledDividedContainer = styled.div` + display: flex; + align-items: center; + gap: 28px; +`; + +function DividedContainer({ children }) { + return ( + + {children[0]} + + {children[1]} + + ); +} + +const HeaderTrailing = styled.div` + display: flex; + gap: 8px; + align-items: center; +`; + +const ShareButton = styled(OutlinedButton)` + width: auto; + padding: 0 16px; +`; + function RollingPaperHeader({ recipientName }) { return ( @@ -38,6 +75,16 @@ function RollingPaperHeader({ recipientName }) {
{`To. ${recipientName}`}
+ + + + + +
); From 129b561826aee4d3747cbca613c7bbbd2715ef37 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 14 Aug 2025 22:42:18 +0900 Subject: [PATCH 098/253] =?UTF-8?q?feat=20[#34]=20`MessagesPage`=20sub=20h?= =?UTF-8?q?eader=EC=97=90=20message=20=EB=82=A8=EA=B8=B4=20=EC=82=AC?= =?UTF-8?q?=EB=9E=8C=20=EB=B0=8F=20reaction=20=ED=91=9C=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/rolling-paper-header.jsx | 24 +++++++ .../components/rolling-paper-reactions.jsx | 38 ++++++++++++ .../rolling-paper-sender-avatars.jsx | 62 +++++++++++++++++++ .../components/rolling-paper-senders.jsx | 19 ++++++ 4 files changed, 143 insertions(+) create mode 100644 src/features/rolling-paper/components/rolling-paper-reactions.jsx create mode 100644 src/features/rolling-paper/components/rolling-paper-sender-avatars.jsx create mode 100644 src/features/rolling-paper/components/rolling-paper-senders.jsx diff --git a/src/features/rolling-paper/components/rolling-paper-header.jsx b/src/features/rolling-paper/components/rolling-paper-header.jsx index a69c515..7a950be 100644 --- a/src/features/rolling-paper/components/rolling-paper-header.jsx +++ b/src/features/rolling-paper/components/rolling-paper-header.jsx @@ -5,6 +5,8 @@ import { OutlinedButton } from "../../../components/button/button"; import BUTTON_SIZE from "../../../components/button/button-size"; import Colors from "../../../components/color/colors"; import { media } from "../../../utils/media"; +import RollingPaperReactions from "./rolling-paper-reactions"; +import RollingPaperSenders from "./rolling-paper-senders"; const StyledRollingPaperHeader = styled.div` display: flex; @@ -69,6 +71,24 @@ const ShareButton = styled(OutlinedButton)` `; function RollingPaperHeader({ recipientName }) { + const profiles = [ + "https://picsum.photos/20", + "https://picsum.photos/20", + "https://picsum.photos/20", + "https://picsum.photos/20", + "https://picsum.photos/20", + "https://picsum.photos/20", + "https://picsum.photos/20", + "https://picsum.photos/20", + "https://picsum.photos/20", + ]; + + const reactions = [ + { emoji: "😀", count: 24 }, + { emoji: "😄", count: 16 }, + { emoji: "☺️", count: 6 }, + ]; + return ( @@ -76,6 +96,10 @@ function RollingPaperHeader({ recipientName }) { {`To. ${recipientName}`}
+ + + + + + {reactions.map(({ emoji, count }) => ( + + ))} + + + 열기 버튼 + + + ); +} + +export default RollingPaperReactions; diff --git a/src/features/rolling-paper/components/rolling-paper-sender-avatars.jsx b/src/features/rolling-paper/components/rolling-paper-sender-avatars.jsx new file mode 100644 index 0000000..53de441 --- /dev/null +++ b/src/features/rolling-paper/components/rolling-paper-sender-avatars.jsx @@ -0,0 +1,62 @@ +import styled from "styled-components"; +import Avatar from "../../../components/avatar/avatar"; +import AVATAR_SIZE from "../../../components/avatar/avatar-size"; + +const METRICS = { + size: AVATAR_SIZE.extraSmall, + leftMargin: 16, + overlap: 12, +}; + +const Positioned = styled.div` + position: absolute; + top: 0; + bottom: 0; + left: ${({ $index }) => $index * METRICS.leftMargin}px; +`; + +const RestCount = styled(Positioned)` + height: ${METRICS.size}px; + padding: 0 6px; + border: 1px solid #e3e3e3; + border-radius: 14px; + font-size: 12px; + font-weight: 500; + line-height: 18px; + color: #484848; + display: flex; + justify-content: center; + align-items: center; + background-color: white; +`; + +const StyledRollingPaperSenderAvatars = styled.div` + position: relative; + width: ${({ $count }) => + METRICS.size * $count - METRICS.overlap * ($count - 1)}px; + height: ${METRICS.size}px; +`; + +function RollingPaperSenderAvatars({ profiles }) { + const numberOfAvatars = Math.min(profiles.length, 3); + const restCount = profiles.length - numberOfAvatars; + const range = Array.from({ length: numberOfAvatars }, (e, i) => i); + const itemCount = numberOfAvatars + Math.min(restCount, 1); + + return ( + + {range.map((index) => ( + + + + ))} + {restCount > 0 && {`+${restCount}`}} + + ); +} + +export default RollingPaperSenderAvatars; diff --git a/src/features/rolling-paper/components/rolling-paper-senders.jsx b/src/features/rolling-paper/components/rolling-paper-senders.jsx new file mode 100644 index 0000000..f542bb8 --- /dev/null +++ b/src/features/rolling-paper/components/rolling-paper-senders.jsx @@ -0,0 +1,19 @@ +import styled from "styled-components"; +import RollingPaperSenderAvatars from "./rolling-paper-sender-avatars"; + +const StyledRollingPaperSenders = styled.div` + display: flex; + align-items: center; + gap: 12px; +`; + +function RollingPaperSenders({ profiles }) { + return ( + + +

{`${profiles.length}명이 작성했어요!`}

+
+ ); +} + +export default RollingPaperSenders; From b91b746a668bcd7bd457bb542407d524316db638 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 14 Aug 2025 23:09:25 +0900 Subject: [PATCH 099/253] =?UTF-8?q?feat=20[#34]=20`MessagesPage`=20sub=20h?= =?UTF-8?q?eader=EC=97=90=20mock=20json=20data=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit API 연동은 별도로 진행할 예정입니다. --- .../rolling-paper/api/mock-recipient.json | 353 ++++++++++++++++++ src/features/rolling-paper/api/recipients.js | 8 + .../components/rolling-paper-header.jsx | 26 +- .../components/rolling-paper-reactions.jsx | 6 +- src/pages/messages-page.jsx | 24 +- 5 files changed, 389 insertions(+), 28 deletions(-) create mode 100644 src/features/rolling-paper/api/mock-recipient.json create mode 100644 src/features/rolling-paper/api/recipients.js diff --git a/src/features/rolling-paper/api/mock-recipient.json b/src/features/rolling-paper/api/mock-recipient.json new file mode 100644 index 0000000..3ef6d7e --- /dev/null +++ b/src/features/rolling-paper/api/mock-recipient.json @@ -0,0 +1,353 @@ +{ + "id": 2, + "name": "강영훈", + "backgroundColor": "green", + "backgroundImageURL": null, + "createdAt": "2023-10-26T13:19:31.401765Z", + "messageCount": 30, + "recentMessages": [ + { + "id": 1, + "recipientId": 2, + "sender": "김하은", + "profileImageURL": "https://fastly.picsum.photos/id/311/200/200.jpg?hmac=CHiYGYQ3Xpesshw5eYWH7U0Kyl9zMTZLQuRDU4OtyH8", + "relationship": "가족", + "content": "열심히 일하는 모습 멋있습니다.", + "font": "Pretendard", + "createdAt": "2023-11-01T08:05:25.399056Z" + }, + { + "id": 2, + "recipientId": 2, + "sender": "이영준", + "profileImageURL": "https://fastly.picsum.photos/id/312/200/200.jpg?hmac=XYZ123ABC456DEF", + "relationship": "지인", + "content": "항상 응원합니다", + "font": "Noto Sans", + "createdAt": "2023-11-01T08:04:12.852691Z" + }, + { + "id": 3, + "recipientId": 2, + "sender": "박민지", + "profileImageURL": "https://fastly.picsum.photos/id/313/200/200.jpg?hmac=ABC789XYZ123GHI", + "relationship": "친구", + "content": "오늘도 좋은 하루 보내세요!", + "font": "Pretendard", + "createdAt": "2023-11-01T07:58:45.123456Z" + }, + { + "id": 4, + "recipientId": 2, + "sender": "최수현", + "profileImageURL": "https://fastly.picsum.photos/id/314/200/200.jpg?hmac=DEF456GHI789JKL", + "relationship": "동료", + "content": "프로젝트 성공을 기원합니다", + "font": "Noto Sans", + "createdAt": "2023-11-01T07:42:18.987654Z" + }, + { + "id": 5, + "recipientId": 2, + "sender": "정다은", + "profileImageURL": "https://fastly.picsum.photos/id/315/200/200.jpg?hmac=GHI123JKL456MNO", + "relationship": "친구", + "content": "건강 챙기시고 화이팅!", + "font": "Pretendard", + "createdAt": "2023-11-01T07:30:22.654321Z" + }, + { + "id": 6, + "recipientId": 2, + "sender": "윤서준", + "profileImageURL": "https://fastly.picsum.photos/id/316/200/200.jpg?hmac=JKL789MNO123PQR", + "relationship": "지인", + "content": "좋은 결과 있길 바래요", + "font": "Noto Sans", + "createdAt": "2023-11-01T07:15:33.111111Z" + }, + { + "id": 7, + "recipientId": 2, + "sender": "강예원", + "profileImageURL": "https://fastly.picsum.photos/id/317/200/200.jpg?hmac=MNO456PQR789STU", + "relationship": "가족", + "content": "항상 자랑스러워요", + "font": "Pretendard", + "createdAt": "2023-11-01T06:58:47.222222Z" + }, + { + "id": 8, + "recipientId": 2, + "sender": "임하늘", + "profileImageURL": "https://fastly.picsum.photos/id/318/200/200.jpg?hmac=PQR123STU456VWX", + "relationship": "동료", + "content": "멋진 하루 되세요!", + "font": "Noto Sans", + "createdAt": "2023-11-01T06:45:12.333333Z" + }, + { + "id": 9, + "recipientId": 2, + "sender": "신지우", + "profileImageURL": "https://fastly.picsum.photos/id/319/200/200.jpg?hmac=STU789VWX123YZA", + "relationship": "친구", + "content": "언제나 응원할게요", + "font": "Pretendard", + "createdAt": "2023-11-01T06:32:55.444444Z" + }, + { + "id": 10, + "recipientId": 2, + "sender": "배소영", + "profileImageURL": "https://fastly.picsum.photos/id/320/200/200.jpg?hmac=VWX456YZA789BCD", + "relationship": "지인", + "content": "오늘도 힘내세요!", + "font": "Noto Sans", + "createdAt": "2023-11-01T06:18:41.555555Z" + }, + { + "id": 11, + "recipientId": 2, + "sender": "한민수", + "profileImageURL": "https://fastly.picsum.photos/id/321/200/200.jpg?hmac=YZA123BCD456EFG", + "relationship": "동료", + "content": "성공적인 하루 보내시길", + "font": "Pretendard", + "createdAt": "2023-11-01T06:05:28.666666Z" + }, + { + "id": 12, + "recipientId": 2, + "sender": "조아름", + "profileImageURL": "https://fastly.picsum.photos/id/322/200/200.jpg?hmac=BCD789EFG123HIJ", + "relationship": "친구", + "content": "늘 감사해요", + "font": "Noto Sans", + "createdAt": "2023-11-01T05:52:16.777777Z" + }, + { + "id": 13, + "recipientId": 2, + "sender": "송태현", + "profileImageURL": "https://fastly.picsum.photos/id/323/200/200.jpg?hmac=EFG456HIJ789KLM", + "relationship": "가족", + "content": "건강이 최고에요", + "font": "Pretendard", + "createdAt": "2023-11-01T05:38:53.888888Z" + }, + { + "id": 14, + "recipientId": 2, + "sender": "오지현", + "profileImageURL": "https://fastly.picsum.photos/id/324/200/200.jpg?hmac=HIJ123KLM456NOP", + "relationship": "지인", + "content": "좋은 일만 가득하세요", + "font": "Noto Sans", + "createdAt": "2023-11-01T05:25:39.999999Z" + }, + { + "id": 15, + "recipientId": 2, + "sender": "남도윤", + "profileImageURL": "https://fastly.picsum.photos/id/325/200/200.jpg?hmac=KLM789NOP123QRS", + "relationship": "동료", + "content": "멋진 성과 기대합니다", + "font": "Pretendard", + "createdAt": "2023-11-01T05:12:14.101010Z" + }, + { + "id": 16, + "recipientId": 2, + "sender": "유채린", + "profileImageURL": "https://fastly.picsum.photos/id/326/200/200.jpg?hmac=NOP456QRS789TUV", + "relationship": "친구", + "content": "화이팅!! 잘 하고 계세요", + "font": "Noto Sans", + "createdAt": "2023-11-01T04:58:27.121212Z" + }, + { + "id": 17, + "recipientId": 2, + "sender": "서준호", + "profileImageURL": "https://fastly.picsum.photos/id/327/200/200.jpg?hmac=QRS123TUV456WXY", + "relationship": "가족", + "content": "항상 믿고 있어요", + "font": "Pretendard", + "createdAt": "2023-11-01T04:45:51.131313Z" + }, + { + "id": 18, + "recipientId": 2, + "sender": "문예진", + "profileImageURL": "https://fastly.picsum.photos/id/328/200/200.jpg?hmac=TUV789WXY123ZAB", + "relationship": "지인", + "content": "좋은 소식 기다려요", + "font": "Noto Sans", + "createdAt": "2023-11-01T04:32:38.141414Z" + }, + { + "id": 19, + "recipientId": 2, + "sender": "홍승우", + "profileImageURL": "https://fastly.picsum.photos/id/329/200/200.jpg?hmac=WXY456ZAB789CDE", + "relationship": "동료", + "content": "오늘도 수고 많으셨어요", + "font": "Pretendard", + "createdAt": "2023-11-01T04:19:22.151515Z" + }, + { + "id": 20, + "recipientId": 2, + "sender": "전소민", + "profileImageURL": "https://fastly.picsum.photos/id/330/200/200.jpg?hmac=ZAB123CDE456FGH", + "relationship": "친구", + "content": "멋진 하루 만들어가세요", + "font": "Noto Sans", + "createdAt": "2023-11-01T04:06:47.161616Z" + }, + { + "id": 21, + "recipientId": 2, + "sender": "황지아", + "profileImageURL": "https://fastly.picsum.photos/id/331/200/200.jpg?hmac=CDE789FGH123IJK", + "relationship": "가족", + "content": "언제나 응원해요", + "font": "Pretendard", + "createdAt": "2023-11-01T03:53:15.171717Z" + }, + { + "id": 22, + "recipientId": 2, + "sender": "김도현", + "profileImageURL": "https://fastly.picsum.photos/id/332/200/200.jpg?hmac=FGH456IJK789LMN", + "relationship": "지인", + "content": "좋은 결과가 있길 바라요", + "font": "Noto Sans", + "createdAt": "2023-11-01T03:40:33.181818Z" + }, + { + "id": 23, + "recipientId": 2, + "sender": "이서연", + "profileImageURL": "https://fastly.picsum.photos/id/333/200/200.jpg?hmac=IJK123LMN456OPQ", + "relationship": "동료", + "content": "항상 최고입니다", + "font": "Pretendard", + "createdAt": "2023-11-01T03:27:49.191919Z" + }, + { + "id": 24, + "recipientId": 2, + "sender": "박준영", + "profileImageURL": "https://fastly.picsum.photos/id/334/200/200.jpg?hmac=LMN789OPQ123RST", + "relationship": "친구", + "content": "건강하고 행복하세요", + "font": "Noto Sans", + "createdAt": "2023-11-01T03:14:26.202020Z" + }, + { + "id": 25, + "recipientId": 2, + "sender": "최은지", + "profileImageURL": "https://fastly.picsum.photos/id/335/200/200.jpg?hmac=OPQ456RST789UVW", + "relationship": "가족", + "content": "오늘도 화이팅!", + "font": "Pretendard", + "createdAt": "2023-11-01T03:01:44.212121Z" + }, + { + "id": 26, + "recipientId": 2, + "sender": "정민호", + "profileImageURL": "https://fastly.picsum.photos/id/336/200/200.jpg?hmac=RST123UVW456XYZ", + "relationship": "지인", + "content": "좋은 에너지 전해드려요", + "font": "Noto Sans", + "createdAt": "2023-11-01T02:48:57.222222Z" + }, + { + "id": 27, + "recipientId": 2, + "sender": "윤하영", + "profileImageURL": "https://fastly.picsum.photos/id/337/200/200.jpg?hmac=UVW789XYZ123ABC", + "relationship": "동료", + "content": "성공을 위해 응원합니다", + "font": "Pretendard", + "createdAt": "2023-11-01T02:35:31.232323Z" + }, + { + "id": 28, + "recipientId": 2, + "sender": "강시우", + "profileImageURL": "https://fastly.picsum.photos/id/338/200/200.jpg?hmac=XYZ456ABC789DEF", + "relationship": "친구", + "content": "멋진 모습 항상 보기 좋아요", + "font": "Noto Sans", + "createdAt": "2023-11-01T02:22:18.242424Z" + }, + { + "id": 29, + "recipientId": 2, + "sender": "임수빈", + "profileImageURL": "https://fastly.picsum.photos/id/339/200/200.jpg?hmac=ABC123DEF456GHI", + "relationship": "가족", + "content": "늘 자랑스럽습니다", + "font": "Pretendard", + "createdAt": "2023-11-01T02:09:42.252525Z" + }, + { + "id": 30, + "recipientId": 2, + "sender": "신예린", + "profileImageURL": "https://fastly.picsum.photos/id/340/200/200.jpg?hmac=DEF789GHI123JKL", + "relationship": "지인", + "content": "오늘도 좋은 하루 되시길!", + "font": "Noto Sans", + "createdAt": "2023-11-01T01:56:27.262626Z" + } + ], + "reactionCount": 8, + "topReactions": [ + { + "id": 1, + "emoji": "😀", + "count": 247 + }, + { + "id": 2, + "emoji": "🥹", + "count": 189 + }, + { + "id": 3, + "emoji": "❤️", + "count": 156 + }, + { + "id": 4, + "emoji": "👍", + "count": 98 + }, + { + "id": 5, + "emoji": "🎉", + "count": 67 + }, + { + "id": 6, + "emoji": "💪", + "count": 34 + }, + { + "id": 7, + "emoji": "🙏", + "count": 23 + }, + { + "id": 8, + "emoji": "✨", + "count": 8 + } + ] +} diff --git a/src/features/rolling-paper/api/recipients.js b/src/features/rolling-paper/api/recipients.js new file mode 100644 index 0000000..1e0a566 --- /dev/null +++ b/src/features/rolling-paper/api/recipients.js @@ -0,0 +1,8 @@ +import mockRecipient from "./mock-recipient.json"; + +async function getRecipient() { + // NOTE: API를 연동하기 전에 mock data로 먼저 개발합니다. + return mockRecipient; +} + +export { getRecipient }; diff --git a/src/features/rolling-paper/components/rolling-paper-header.jsx b/src/features/rolling-paper/components/rolling-paper-header.jsx index 7a950be..82e0511 100644 --- a/src/features/rolling-paper/components/rolling-paper-header.jsx +++ b/src/features/rolling-paper/components/rolling-paper-header.jsx @@ -70,25 +70,7 @@ const ShareButton = styled(OutlinedButton)` padding: 0 16px; `; -function RollingPaperHeader({ recipientName }) { - const profiles = [ - "https://picsum.photos/20", - "https://picsum.photos/20", - "https://picsum.photos/20", - "https://picsum.photos/20", - "https://picsum.photos/20", - "https://picsum.photos/20", - "https://picsum.photos/20", - "https://picsum.photos/20", - "https://picsum.photos/20", - ]; - - const reactions = [ - { emoji: "😀", count: 24 }, - { emoji: "😄", count: 16 }, - { emoji: "☺️", count: 6 }, - ]; - +function RollingPaperHeader({ recipientName, messages, reactions }) { return ( @@ -97,8 +79,10 @@ function RollingPaperHeader({ recipientName }) { - - + message.profileImageURL)} + /> + - {reactions.map(({ emoji, count }) => ( - + {reactions.slice(0, 3).map(({ id, emoji, count }) => ( + ))} diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx index ea2cda0..eb4fb64 100644 --- a/src/pages/messages-page.jsx +++ b/src/pages/messages-page.jsx @@ -1,12 +1,28 @@ +import { useEffect, useState } from "react"; +import { getRecipient } from "../features/rolling-paper/api/recipients"; import RollingPaperHeader from "../features/rolling-paper/components/rolling-paper-header"; function MessagesPage() { + const [recipient, setRecipient] = useState(); + + useEffect(() => { + getRecipient().then(setRecipient); + }, []); + return ( <> - -
-

Messages Page

-
+ {recipient && ( + <> + +
+

Messages Page

+
+ + )} ); } From bd75df22e700fa3b1e860882ded1be5f2ee5f2a5 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 14 Aug 2025 23:15:53 +0900 Subject: [PATCH 100/253] =?UTF-8?q?feat=20[#34]=20Message=20sender=20count?= =?UTF-8?q?=20=EB=AC=B8=EA=B5=AC=EC=97=90=20style=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/rolling-paper-senders.jsx | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/features/rolling-paper/components/rolling-paper-senders.jsx b/src/features/rolling-paper/components/rolling-paper-senders.jsx index f542bb8..4d6aab2 100644 --- a/src/features/rolling-paper/components/rolling-paper-senders.jsx +++ b/src/features/rolling-paper/components/rolling-paper-senders.jsx @@ -1,6 +1,17 @@ import styled from "styled-components"; import RollingPaperSenderAvatars from "./rolling-paper-sender-avatars"; +const SenderCountDescription = styled.p` + margin: 0; + font-size: 18px; + font-weight: 400; + line-height: 27px; + + span { + font-weight: 700; + } +`; + const StyledRollingPaperSenders = styled.div` display: flex; align-items: center; @@ -11,7 +22,9 @@ function RollingPaperSenders({ profiles }) { return ( -

{`${profiles.length}명이 작성했어요!`}

+ + {profiles.length}명이 작성했어요! +
); } From f3bb00526c65febd3ac75ff7ad5fcbedd59a581e Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 14 Aug 2025 23:38:44 +0900 Subject: [PATCH 101/253] =?UTF-8?q?fix=20[#34]=20Sender=EA=B0=80=204?= =?UTF-8?q?=EB=AA=85=20=EC=9D=B4=EC=83=81=EC=9D=BC=20=EB=95=8C=20`+n`?= =?UTF-8?q?=EC=9D=98=20=EC=8B=A4=EC=A0=9C=20=EB=84=88=EB=B9=84=EB=A5=BC=20?= =?UTF-8?q?=EA=B8=B0=EC=A4=80=EC=9C=BC=EB=A1=9C=20avatars=20container=20?= =?UTF-8?q?=EB=84=88=EB=B9=84=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `+n`에서 `n`이 10 이상이면 avatar와 달리 너비가 28px보다 커질 수 있으므로 실제 너비를 계산합니다. --- .../rolling-paper-sender-avatars.jsx | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/features/rolling-paper/components/rolling-paper-sender-avatars.jsx b/src/features/rolling-paper/components/rolling-paper-sender-avatars.jsx index 53de441..9a127f9 100644 --- a/src/features/rolling-paper/components/rolling-paper-sender-avatars.jsx +++ b/src/features/rolling-paper/components/rolling-paper-sender-avatars.jsx @@ -1,3 +1,4 @@ +import { useEffect, useRef, useState } from "react"; import styled from "styled-components"; import Avatar from "../../../components/avatar/avatar"; import AVATAR_SIZE from "../../../components/avatar/avatar-size"; @@ -30,21 +31,35 @@ const RestCount = styled(Positioned)` background-color: white; `; +function calculateWidth({ $numberOfAvatars, $restCountWidth }) { + const contentWidth = METRICS.size * $numberOfAvatars; + const overlapedWidth = METRICS.overlap * ($numberOfAvatars - 1); + const restCountWidth = Math.max(0, $restCountWidth - METRICS.overlap); + return contentWidth - overlapedWidth + restCountWidth; +} + const StyledRollingPaperSenderAvatars = styled.div` position: relative; - width: ${({ $count }) => - METRICS.size * $count - METRICS.overlap * ($count - 1)}px; + width: ${(props) => calculateWidth(props)}px; height: ${METRICS.size}px; `; function RollingPaperSenderAvatars({ profiles }) { + const countRef = useRef(); + const [restCountWidth, setRestCountWidth] = useState(METRICS.size); const numberOfAvatars = Math.min(profiles.length, 3); const restCount = profiles.length - numberOfAvatars; const range = Array.from({ length: numberOfAvatars }, (e, i) => i); - const itemCount = numberOfAvatars + Math.min(restCount, 1); + + useEffect(() => { + setRestCountWidth(countRef.current?.getBoundingClientRect().width ?? 0); + }, [countRef]); return ( - + {range.map((index) => ( ))} - {restCount > 0 && {`+${restCount}`}} + {restCount > 0 && ( + {`+${restCount}`} + )} ); } From 3d40b8e0251925f64ceb0eb65eca33a2b0c0568a Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Fri, 15 Aug 2025 10:52:34 +0900 Subject: [PATCH 102/253] =?UTF-8?q?feat=20[#34]=20=EC=B5=9C=EB=8C=80=208?= =?UTF-8?q?=EA=B0=9C=20reaction=EC=9D=84=20=EB=B3=B4=EC=97=AC=EC=A3=BC?= =?UTF-8?q?=EB=8A=94=20popover=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/rolling-paper-reactions.jsx | 42 +++++++++++++++++-- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/src/features/rolling-paper/components/rolling-paper-reactions.jsx b/src/features/rolling-paper/components/rolling-paper-reactions.jsx index d3e8f79..3b2e97f 100644 --- a/src/features/rolling-paper/components/rolling-paper-reactions.jsx +++ b/src/features/rolling-paper/components/rolling-paper-reactions.jsx @@ -1,6 +1,10 @@ +import { useRef } from "react"; import styled from "styled-components"; import arrowDownImage from "../../../assets/ic-chevron-down.svg"; import EmojiBadge from "../../../components/badge/emoji-badge"; +import Popover from "../../../components/popover/popover"; +import POPOVER_ALIGNMENT from "../../../components/popover/popover-alignment"; +import { usePopover } from "../../../hooks/use-popover"; const MoreButton = styled.button` background: none; @@ -10,27 +14,57 @@ const MoreButton = styled.button` cursor: pointer; `; -const Reactions = styled.div` +const TopThreeReactions = styled.div` display: flex; gap: 8px; `; +const AllReactions = styled.div` + padding: 24px; + display: grid; + grid-template-columns: repeat(4, min-content); + row-gap: 10px; + column-gap: 8px; +`; + const StyledRollingPaperReactions = styled.div` display: flex; gap: 2px; `; function RollingPaperReactions({ reactions }) { + const { popoverPosition, showsPopover, openPopopver, closePopover } = + usePopover(); + const targetRef = useRef(); + + const handleMoreClick = () => { + openPopopver({ + target: targetRef.current, + alignment: POPOVER_ALIGNMENT.right, + }); + }; + return ( - + {reactions.slice(0, 3).map(({ id, emoji, count }) => ( ))} - - + + 열기 버튼 + + + {reactions.slice(0, 8).map(({ id, emoji, count }) => ( + + ))} + + ); } From 0b808bbbb5b6a64059b3f615977a0ea0606624aa Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Fri, 15 Aug 2025 15:25:27 +0900 Subject: [PATCH 103/253] =?UTF-8?q?feat=20[#34]=20Device=20match=20?= =?UTF-8?q?=EC=97=AC=EB=B6=80=EB=A5=BC=20=EB=B0=98=ED=99=98=ED=95=98?= =?UTF-8?q?=EB=8A=94=20`useMedia`=20custom=20hook=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/use-media.jsx | 65 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 src/hooks/use-media.jsx diff --git a/src/hooks/use-media.jsx b/src/hooks/use-media.jsx new file mode 100644 index 0000000..efa2cfc --- /dev/null +++ b/src/hooks/use-media.jsx @@ -0,0 +1,65 @@ +import { useEffect, useRef, useState } from "react"; + +const mediaQueryString = { + desktop: "(min-width: 1200px)", + tablet: "(min-width: 768px) and (max-width: 1199px)", + mobile: "(max-width: 767px)", +}; + +function useMedia() { + const desktop = useRef(matchMedia(mediaQueryString.desktop)).current; + const tablet = useRef(matchMedia(mediaQueryString.tablet)).current; + const mobile = useRef(matchMedia(mediaQueryString.mobile)).current; + + const [matches, setMatches] = useState({ + isDesktop: desktop.matches, + isTablet: tablet.matches, + isMobile: mobile.matches, + }); + + useEffect(() => { + const handleDesktopMatch = (event) => { + const matches = event.matches; + if (!matches) return; + setMatches({ + isDesktop: matches, + isTablet: false, + isMobile: false, + }); + }; + + const handleTabletMatch = (event) => { + const matches = event.matches; + if (!matches) return; + setMatches({ + isDesktop: false, + isTablet: matches, + isMobile: false, + }); + }; + + const handleMobileMatch = (event) => { + const matches = event.matches; + if (!matches) return; + setMatches({ + isDesktop: false, + isTablet: false, + isMobile: matches, + }); + }; + + desktop.addEventListener("change", handleDesktopMatch); + tablet.addEventListener("change", handleTabletMatch); + mobile.addEventListener("change", handleMobileMatch); + + return () => { + desktop.removeEventListener("change", handleDesktopMatch); + tablet.removeEventListener("change", handleTabletMatch); + mobile.removeEventListener("change", handleMobileMatch); + }; + }, [desktop, tablet, mobile]); + + return matches; +} + +export { useMedia }; From 266b2e7b78a7fb484084461946f1f347802a79d8 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Fri, 15 Aug 2025 16:34:43 +0900 Subject: [PATCH 104/253] =?UTF-8?q?feat=20[#34]=20Sub=20header=EC=97=90=20?= =?UTF-8?q?=EB=B0=98=EC=9D=91=ED=98=95=20=EB=94=94=EC=9E=90=EC=9D=B8=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.jsx | 9 +- src/components/badge/emoji-badge.jsx | 17 ++- .../components/rolling-paper-header.jsx | 100 ++++++++++++------ .../components/rolling-paper-reactions.jsx | 10 +- src/pages/messages-page.jsx | 7 +- 5 files changed, 99 insertions(+), 44 deletions(-) diff --git a/src/app.jsx b/src/app.jsx index 33541ea..b2c39e5 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -59,14 +59,7 @@ function App() { } /> - - - - } - /> + } /> } /> diff --git a/src/components/badge/emoji-badge.jsx b/src/components/badge/emoji-badge.jsx index a674b72..45c3bba 100644 --- a/src/components/badge/emoji-badge.jsx +++ b/src/components/badge/emoji-badge.jsx @@ -1,18 +1,29 @@ import styled from "styled-components"; +import { media } from "../../utils/media"; const StyledEmojiBadge = styled.div` background-color: rgba(0, 0, 0, 0.54); color: white; - font-size: 16px; - font-weight: 400; - line-height: 20px; padding: 8px 12px; border-radius: 32px; + + ${media.mobile} { + padding: 4px 8px; + } `; const Content = styled.div` display: flex; gap: 4px; + font-size: 16px; + font-weight: 400; + line-height: 20px; + + ${media.mobile} { + gap: 6px; + font-size: 14px; + line-height: 20px; + } `; function EmojiBadge({ emoji, count }) { diff --git a/src/features/rolling-paper/components/rolling-paper-header.jsx b/src/features/rolling-paper/components/rolling-paper-header.jsx index 82e0511..a13f4c5 100644 --- a/src/features/rolling-paper/components/rolling-paper-header.jsx +++ b/src/features/rolling-paper/components/rolling-paper-header.jsx @@ -4,37 +4,22 @@ import shareImage from "../../../assets/ic-share.svg"; import { OutlinedButton } from "../../../components/button/button"; import BUTTON_SIZE from "../../../components/button/button-size"; import Colors from "../../../components/color/colors"; +import { useMedia } from "../../../hooks/use-media"; import { media } from "../../../utils/media"; import RollingPaperReactions from "./rolling-paper-reactions"; import RollingPaperSenders from "./rolling-paper-senders"; -const StyledRollingPaperHeader = styled.div` - display: flex; - justify-content: center; - align-items: center; - height: 68px; - border-bottom: 1px solid #ededed; - padding: 0 24px; - - ${media.mobile} { - padding: 0 16px; - } -`; - -const HeaderContent = styled.div` - width: 100%; - max-width: 1200px; - display: flex; - justify-content: space-between; - align-items: center; -`; - const RecipientName = styled.h2` margin: 0; font-size: 28px; font-weight: 700; line-height: 42px; color: ${Colors.gray(800)}; + + ${media.mobile} { + font-size: 18px; + line-height: 28px; + } `; const Divider = styled.div` @@ -47,13 +32,17 @@ const StyledDividedContainer = styled.div` display: flex; align-items: center; gap: 28px; + + ${media.mobile} { + gap: 16px; + } `; function DividedContainer({ children }) { return ( {children[0]} - + {children[0] && } {children[1]} ); @@ -65,35 +54,84 @@ const HeaderTrailing = styled.div` align-items: center; `; +const AddButton = styled(OutlinedButton)` + ${media.mobile} { + padding: 0 8px; + } +`; + const ShareButton = styled(OutlinedButton)` width: auto; padding: 0 16px; + + ${media.mobile} { + padding: 0 8px; + } +`; + +const RollingPaperHeaderContent = styled.div` + width: 100%; + max-width: 1200px; + height: 68px; + border-bottom: 1px solid #ededed; + display: flex; + justify-content: space-between; + align-items: center; + + ${media.mobile} { + height: 54px; + } +`; + +const StyledRollingPaperHeader = styled.div` + display: flex; + justify-content: center; + align-items: center; + padding: 0 24px; + + ${media.mobile} { + padding: 0 16px; + flex-direction: column; + justify-content: flex-start; + align-items: flex-start; + } `; function RollingPaperHeader({ recipientName, messages, reactions }) { + const { isDesktop, isMobile } = useMedia(); + return ( - -
+ {isMobile && ( + {`To. ${recipientName}`} -
+ + )} + + {isMobile || ( +
+ {`To. ${recipientName}`} +
+ )} - message.profileImageURL)} - /> + {isDesktop && ( + message.profileImageURL)} + /> + )} - -
+
); } diff --git a/src/features/rolling-paper/components/rolling-paper-reactions.jsx b/src/features/rolling-paper/components/rolling-paper-reactions.jsx index 3b2e97f..8c4dc4b 100644 --- a/src/features/rolling-paper/components/rolling-paper-reactions.jsx +++ b/src/features/rolling-paper/components/rolling-paper-reactions.jsx @@ -4,7 +4,9 @@ import arrowDownImage from "../../../assets/ic-chevron-down.svg"; import EmojiBadge from "../../../components/badge/emoji-badge"; import Popover from "../../../components/popover/popover"; import POPOVER_ALIGNMENT from "../../../components/popover/popover-alignment"; +import { useMedia } from "../../../hooks/use-media"; import { usePopover } from "../../../hooks/use-popover"; +import { media } from "../../../utils/media"; const MoreButton = styled.button` background: none; @@ -25,14 +27,20 @@ const AllReactions = styled.div` grid-template-columns: repeat(4, min-content); row-gap: 10px; column-gap: 8px; + + ${media.mobile} { + grid-template-columns: repeat(3, min-content); + } `; const StyledRollingPaperReactions = styled.div` display: flex; gap: 2px; + align-items: center; `; function RollingPaperReactions({ reactions }) { + const { isMobile } = useMedia(); const { popoverPosition, showsPopover, openPopopver, closePopover } = usePopover(); const targetRef = useRef(); @@ -60,7 +68,7 @@ function RollingPaperReactions({ reactions }) { position={popoverPosition} > - {reactions.slice(0, 8).map(({ id, emoji, count }) => ( + {reactions.slice(0, isMobile ? 6 : 8).map(({ id, emoji, count }) => ( ))} diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx index eb4fb64..3a2cf17 100644 --- a/src/pages/messages-page.jsx +++ b/src/pages/messages-page.jsx @@ -1,15 +1,18 @@ import { useEffect, useState } from "react"; import { getRecipient } from "../features/rolling-paper/api/recipients"; import RollingPaperHeader from "../features/rolling-paper/components/rolling-paper-header"; +import { useMedia } from "../hooks/use-media"; +import ContentLayout from "../layouts/content-layout"; function MessagesPage() { + const { isMobile } = useMedia(); const [recipient, setRecipient] = useState(); useEffect(() => { getRecipient().then(setRecipient); }, []); - return ( + const content = ( <> {recipient && ( <> @@ -25,6 +28,8 @@ function MessagesPage() { )} ); + + return isMobile ? content : {content}; } export default MessagesPage; From a372e6489422a37037d06d5c44499eee39d20e2b Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Fri, 15 Aug 2025 16:37:51 +0900 Subject: [PATCH 105/253] =?UTF-8?q?fix=20[]=20Mobile=20media=20query=20?= =?UTF-8?q?=EA=B8=B0=EC=A4=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/media.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/media.js b/src/utils/media.js index a389097..35e0f74 100644 --- a/src/utils/media.js +++ b/src/utils/media.js @@ -1,7 +1,7 @@ const media = { desktop: "@media (min-width: 1200px)", tablet: "@media (max-width: 1199px)", - mobile: "@media (max-width: 797px)", + mobile: "@media (max-width: 767px)", }; export { media }; From f513b1a8962e03301110dd5e84c53c86290b1acf Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Fri, 15 Aug 2025 16:38:23 +0900 Subject: [PATCH 106/253] =?UTF-8?q?feat=20[#34]=20Header=20=EB=84=88?= =?UTF-8?q?=EB=B9=84=EA=B0=80=201248px=20=EC=9D=B4=ED=95=98=EC=9D=BC=20?= =?UTF-8?q?=EB=95=8C=EB=B6=80=ED=84=B0=20=EC=A2=8C=EC=9A=B0=20padding?= =?UTF-8?q?=EC=9D=84=2024px=EB=A1=9C=20=EA=B3=A0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rolling-paper/components/rolling-paper-header.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/features/rolling-paper/components/rolling-paper-header.jsx b/src/features/rolling-paper/components/rolling-paper-header.jsx index a13f4c5..0552e44 100644 --- a/src/features/rolling-paper/components/rolling-paper-header.jsx +++ b/src/features/rolling-paper/components/rolling-paper-header.jsx @@ -87,7 +87,10 @@ const StyledRollingPaperHeader = styled.div` display: flex; justify-content: center; align-items: center; - padding: 0 24px; + + @media (max-width: 1248px) { + padding: 0 24px; + } ${media.mobile} { padding: 0 16px; From 56525c5ed66206b2373a2baba5b25c0ff8c090c8 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Sat, 16 Aug 2025 13:02:01 +0900 Subject: [PATCH 107/253] =?UTF-8?q?refactor=20#22=20onSelect=20->=20onOpti?= =?UTF-8?q?onClick=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/option/background-select.jsx | 4 ++-- src/pages/create-post-page.jsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/option/background-select.jsx b/src/components/option/background-select.jsx index f982fc3..d571cfd 100644 --- a/src/components/option/background-select.jsx +++ b/src/components/option/background-select.jsx @@ -39,7 +39,7 @@ const CircleButtonWrapper = styled.div` } `; -function BackgroundSelect({ type, selected, onSelect }) { +function BackgroundSelect({ type, selected, onOptionClick }) { const [imageUrls, setImageUrls] = useState([]); const colorOptions = [ @@ -93,7 +93,7 @@ function BackgroundSelect({ type, selected, onSelect }) { type={type} color={option.color} url={option.url} - onClick={() => onSelect(index)} + onClick={() => onOptionClick(index)} > {selected === index && ( diff --git a/src/pages/create-post-page.jsx b/src/pages/create-post-page.jsx index 0635c47..1debc4a 100644 --- a/src/pages/create-post-page.jsx +++ b/src/pages/create-post-page.jsx @@ -116,7 +116,7 @@ function CreatePostPage() { Date: Sat, 16 Aug 2025 13:04:53 +0900 Subject: [PATCH 108/253] =?UTF-8?q?refactor=20#22=20onOptionClick=20?= =?UTF-8?q?=EC=9E=98=EB=AA=BB=20=EB=B3=80=EA=B2=BD=ED=95=B4=EC=84=9C=20?= =?UTF-8?q?=EB=8B=A4=EC=8B=9C=20=EC=9B=90=EB=9E=98=EB=8C=80=EB=A1=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/option/background-select.jsx | 4 ++-- src/pages/create-post-page.jsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/option/background-select.jsx b/src/components/option/background-select.jsx index d571cfd..f982fc3 100644 --- a/src/components/option/background-select.jsx +++ b/src/components/option/background-select.jsx @@ -39,7 +39,7 @@ const CircleButtonWrapper = styled.div` } `; -function BackgroundSelect({ type, selected, onOptionClick }) { +function BackgroundSelect({ type, selected, onSelect }) { const [imageUrls, setImageUrls] = useState([]); const colorOptions = [ @@ -93,7 +93,7 @@ function BackgroundSelect({ type, selected, onOptionClick }) { type={type} color={option.color} url={option.url} - onClick={() => onOptionClick(index)} + onClick={() => onSelect(index)} > {selected === index && ( diff --git a/src/pages/create-post-page.jsx b/src/pages/create-post-page.jsx index 1debc4a..0635c47 100644 --- a/src/pages/create-post-page.jsx +++ b/src/pages/create-post-page.jsx @@ -116,7 +116,7 @@ function CreatePostPage() { Date: Sat, 16 Aug 2025 13:11:39 +0900 Subject: [PATCH 109/253] =?UTF-8?q?refactor=20#22=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=ED=95=98=EA=B8=B0=20=EB=B2=84=ED=8A=BC=20=EC=8A=A4=ED=83=80?= =?UTF-8?q?=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/create-post-page.jsx | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/pages/create-post-page.jsx b/src/pages/create-post-page.jsx index 0635c47..8272b8b 100644 --- a/src/pages/create-post-page.jsx +++ b/src/pages/create-post-page.jsx @@ -39,13 +39,10 @@ const ToggleButtonWrapper = styled.div` const ButtonWrapper = styled.div` padding-top: 50px; width: 720px; - display: flex; - justify-content: center; - align-items: center; +`; - & > * { - flex: 1; - } +const CreateButton = styled(PrimaryButton)` + width: 100%; `; function CreatePostPage() { @@ -119,7 +116,7 @@ function CreatePostPage() { onSelect={setSelected} /> - Date: Sat, 16 Aug 2025 13:22:37 +0900 Subject: [PATCH 110/253] =?UTF-8?q?refactor=20#22=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=ED=95=98=EA=B8=B0=20=EB=B2=84=ED=8A=BC=20disabled=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/create-post-page.jsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/pages/create-post-page.jsx b/src/pages/create-post-page.jsx index 8272b8b..059cf0b 100644 --- a/src/pages/create-post-page.jsx +++ b/src/pages/create-post-page.jsx @@ -7,6 +7,7 @@ import styled from "styled-components"; import { PrimaryButton } from "../components/button/button"; import BackgroundSelect from "../components/option/background-select"; import { useNavigate } from "react-router"; +import BUTTON_SIZE from "../components/button/button-size"; const PostContainer = styled.div` display: flex; @@ -81,6 +82,8 @@ function CreatePostPage() { navigate(`/post/${randomID}`); }; + const canCreate = name !== "" || name !== name.trim(); + return ( @@ -118,8 +121,8 @@ function CreatePostPage() { From 70ea20208e651c8fa8742e488d819b360b7a6d77 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Sat, 16 Aug 2025 13:43:39 +0900 Subject: [PATCH 111/253] =?UTF-8?q?refactor=20#29=20InputTextField=20->=20?= =?UTF-8?q?TextField=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/send-message-page.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/send-message-page.jsx b/src/pages/send-message-page.jsx index 37bfe2c..600082a 100644 --- a/src/pages/send-message-page.jsx +++ b/src/pages/send-message-page.jsx @@ -1,5 +1,5 @@ import { useState } from "react"; -import InputTextField from "../components/text-field/text-field"; +import TextField from "../components/text-field/text-field"; import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; import Colors from "../components/color/colors"; import ToggleButton from "../components/button/toggle-button"; @@ -60,7 +60,7 @@ function SendMessagePage() { From. - Date: Sat, 16 Aug 2025 13:45:53 +0900 Subject: [PATCH 112/253] =?UTF-8?q?=EB=8F=99=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/send-message-page.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/send-message-page.jsx b/src/pages/send-message-page.jsx index 600082a..f5b6528 100644 --- a/src/pages/send-message-page.jsx +++ b/src/pages/send-message-page.jsx @@ -75,7 +75,7 @@ function SendMessagePage() { 상대와의 관계 - Date: Sat, 16 Aug 2025 13:54:23 +0900 Subject: [PATCH 113/253] =?UTF-8?q?fix=20#22=20=EC=84=A0=ED=83=9D=EB=90=9C?= =?UTF-8?q?=20=EC=98=B5=EC=85=98=20=EB=B6=88=ED=88=AC=EB=AA=85=EB=8F=84...?= =?UTF-8?q?=E3=85=A0=E3=85=A0..?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/option/background-select.jsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/option/background-select.jsx b/src/components/option/background-select.jsx index f982fc3..cc6cb27 100644 --- a/src/components/option/background-select.jsx +++ b/src/components/option/background-select.jsx @@ -25,6 +25,7 @@ const OptionItem = styled.div` background-position: center; background-size: cover; background-repeat: no-repeat; + opacity: ${({ selected }) => (selected ? 0.3 : 1)}; `; const CircleButtonWrapper = styled.div` @@ -94,6 +95,7 @@ function BackgroundSelect({ type, selected, onSelect }) { color={option.color} url={option.url} onClick={() => onSelect(index)} + selected={selected === index} > {selected === index && ( From 07d55145ea05af70647a10148b2c24aea1ead2f6 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Sat, 16 Aug 2025 14:24:32 +0900 Subject: [PATCH 114/253] =?UTF-8?q?feat=20#29=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=84=A0=ED=83=9D=20?= =?UTF-8?q?=EC=95=84=EB=B0=94=ED=83=80=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/avatar/avatar-size.js | 2 +- src/components/avatar/avatar.jsx | 2 +- src/pages/send-message-page.jsx | 73 ++++++++++++++++++++++++++-- src/pages/test-page.jsx | 4 +- 4 files changed, 74 insertions(+), 7 deletions(-) diff --git a/src/components/avatar/avatar-size.js b/src/components/avatar/avatar-size.js index 9bb1492..5de514d 100644 --- a/src/components/avatar/avatar-size.js +++ b/src/components/avatar/avatar-size.js @@ -1,7 +1,7 @@ const AVATAR_SIZE = Object.freeze({ large: 80, medium: 56, - small: 40, + medium: 40, extraSmall: 28, }); diff --git a/src/components/avatar/avatar.jsx b/src/components/avatar/avatar.jsx index d5146e8..efbd9d5 100644 --- a/src/components/avatar/avatar.jsx +++ b/src/components/avatar/avatar.jsx @@ -6,7 +6,7 @@ import AVATAR_SIZE from "./avatar-size"; const borderWidth = { [AVATAR_SIZE.large]: 0, [AVATAR_SIZE.medium]: 1, - [AVATAR_SIZE.small]: 1, + [AVATAR_SIZE.medium]: 1, [AVATAR_SIZE.extraSmall]: 1.5, }; diff --git a/src/pages/send-message-page.jsx b/src/pages/send-message-page.jsx index f5b6528..286c5d3 100644 --- a/src/pages/send-message-page.jsx +++ b/src/pages/send-message-page.jsx @@ -4,6 +4,8 @@ import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; import Colors from "../components/color/colors"; import ToggleButton from "../components/button/toggle-button"; import styled from "styled-components"; +import Avatar from "../components/avatar/avatar"; +import AVATAR_SIZE from "../components/avatar/avatar-size"; const SendContainer = styled.div` display: flex; @@ -23,9 +25,27 @@ const SendTitle = styled.h2` font-weight: 700; `; -const SendSummary = styled.p` +const AvatarWrapper = styled.div` + display: flex; + align-items: center; + gap: 32px; +`; + +const AvatarSummaryWrapper = styled.div` + display: flex; + flex-direction: column; + justify-content: center; + width: 80%; +`; + +const AvatarSummary = styled.p` font-weight: 400; - color: Colors.gray(500); + color: ${Colors.gray(500)}; +`; + +const AvatarOption = styled.div` + display: flex; + justify-content: space-between; `; const ToggleButtonWrapper = styled.div` @@ -71,7 +91,54 @@ function SendMessagePage() { 프로필 이미지 - 프로필 이미지를 선택해 주세요! + + + + 프로필 이미지를 선택해 주세요! + + + + + + + + + + + + + + 상대와의 관계 diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index f691c69..a505fac 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -257,11 +257,11 @@ function TestPage() {
- + - + Date: Thu, 14 Aug 2025 15:12:41 +0900 Subject: [PATCH 115/253] =?UTF-8?q?[#37]=20=20=ED=95=A8=EC=88=98=EB=AA=85?= =?UTF-8?q?=20handle~=EA=B5=AC=EC=A1=B0=EB=A1=9C=20=EB=B3=80=EA=B2=BD,=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=20=EA=B0=84=EB=9E=B5=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit (pr수정사항 누락된부분 추가 수정) --- src/pages/rolling-paper-list-page.jsx | 62 +++++++++++++-------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/src/pages/rolling-paper-list-page.jsx b/src/pages/rolling-paper-list-page.jsx index 8812315..be7816d 100644 --- a/src/pages/rolling-paper-list-page.jsx +++ b/src/pages/rolling-paper-list-page.jsx @@ -96,7 +96,7 @@ const CardItem = styled.div` } `; -const NextBtnWpr = styled.div` +const NextButtonWrapper = styled.div` position: absolute; right: -20px; top: 50%; @@ -104,7 +104,7 @@ const NextBtnWpr = styled.div` z-index: 10; `; -const PrevBtnWpr = styled.div` +const PreviewButtonWrapper = styled.div` position: absolute; left: -20px; top: 50%; @@ -112,7 +112,7 @@ const PrevBtnWpr = styled.div` z-index: 10; `; -const MakingBtn = styled(PrimaryButton)` +const MakingButton = styled(PrimaryButton)` margin-top: 64px; font-weight: 400; padding: 14px 60px; @@ -157,27 +157,17 @@ function ShowMessageList() { ); }, [popularCurrentPage, recentCurrentPage, testData]); - const nextPage = (mode) => { - if (mode) { - if (popularCurrentPage < totalPages - 1) { - setPopularCurrentPage((pprCurrentNum) => pprCurrentNum + 1); - } - } else { - if (recentCurrentPage < totalPages - 1) { - setRecentCurrentPage((currentNum) => currentNum + 1); - } - } - }; + const handleTurnCards = (direction, mode) => { + const current = mode === "popular" ? popularCurrentPage : recentCurrentPage; + const setter = + mode === "popular" ? setPopularCurrentPage : setRecentCurrentPage; + const total = totalPages; + + const additionalPageIndex = direction === "next" ? 1 : -1; + const newPageIndex = current + additionalPageIndex; - const prevPage = (mode) => { - if (mode) { - if (popularCurrentPage > 0) { - setPopularCurrentPage((pprCurrentNum) => pprCurrentNum - 1); - } - } else { - if (recentCurrentPage > 0) { - setRecentCurrentPage((currentNum) => currentNum - 1); - } + if (newPageIndex >= 0 && newPageIndex < total) { + setter(newPageIndex); } }; @@ -212,14 +202,18 @@ function ShowMessageList() { ))} {popularCurrentPage > 0 ? ( - prevPage("ppr")}> + handleTurnCards("preview", "popular")} + > - + ) : null} {popularCurrentPage < totalPages - 1 ? ( - nextPage("ppr")}> + handleTurnCards("next", "popular")} + > - + ) : null} @@ -251,19 +245,23 @@ function ShowMessageList() { ))} {recentCurrentPage > 0 ? ( - prevPage()}> + handleTurnCards("preview", "recent")} + > - + ) : null} {recentCurrentPage < totalPages - 1 ? ( - nextPage()}> + handleTurnCards("next", "recent")} + > - + ) : null} - + ); } From e635b9b297eff23f03a4e06c380374d18885ba90 Mon Sep 17 00:00:00 2001 From: luli Date: Fri, 15 Aug 2025 06:18:09 +0900 Subject: [PATCH 116/253] =?UTF-8?q?[#43]=20rolling=20paper=20list=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80,=20=EB=82=B4=EB=B6=80=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EB=B6=84=EB=A6=AC=20=EB=B0=8F=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=A0=95=EB=A0=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rolling paper list 페이지, 내부 컴포넌트 분리 및 데이터 정렬 --- .../components/rolling-paper-list.jsx | 144 +++++++ src/pages/rolling-paper-list-page.jsx | 222 +++------- src/pages/test_recipients_data.json | 400 +++++++++--------- 3 files changed, 395 insertions(+), 371 deletions(-) diff --git a/src/features/rolling-paper/components/rolling-paper-list.jsx b/src/features/rolling-paper/components/rolling-paper-list.jsx index e69de29..37b58c1 100644 --- a/src/features/rolling-paper/components/rolling-paper-list.jsx +++ b/src/features/rolling-paper/components/rolling-paper-list.jsx @@ -0,0 +1,144 @@ +import ArrowButton from "../../../components/button/arrow-button"; +import ARROW_BUTTON_DIRECTION from "../../../components/button/arrow-button-direction"; +import { + OutlinedButton, + PrimaryButton, + SecondaryButton, +} from "../../../components/button/button"; +import BUTTON_SIZE from "../../../components/button/button-size"; +import ToggleButton from "../../../components/button/toggle-button"; + +import React, { useEffect, useState } from "react"; + +import styled from "styled-components"; + +const backgroundColors = { + beige: "#FFD382", + purple: "#DCB9FF", + green: "#9BE282", + blue: "#9DDDFF", +}; + +const CardContainer = styled.div` + display: grid; + grid-template-columns: 275px 275px 275px 275px; + gap: 20px; + width: fit-content; + + position: relative; + overflow: visible; +`; + +const CardItem = styled.div.withConfig({ + shouldForwardProp: (prop) => prop !== "backgroundColor", +})` + width: 275px; + height: 260px; + border-radius: 16px; + text-align: left; + padding: 30px 24px 20px 24px; + box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1); + + display: grid; + grid-template-rows: 1fr 1fr auto; + + background-color: ${(props) => + backgroundColors[props.backgroundColor] || "white"}; + + img { + height: 28px; + width: 28px; + border-radius: 50%; + border: 1px solid #ffffff; + + margin-left: -12px; + &:first-child { + margin-left: 0; + } + } + + div.message-images { + display: flex; + } + + div.over-profile { + height: 28px; + width: 28px; + background-color: #ffffff; + border-radius: 50%; + + margin-left: -12px; + + display: flex; + justify-content: center; + align-items: center; + font-size: 12px; + } + + h2 { + margin: 0; + } + + div.emoji-div { + border-top: 1px solid red; + } +`; + +const NextButtonWrapper = styled.div` + position: absolute; + right: -20px; + top: 50%; + transform: translateY(-50%); + z-index: 10; +`; + +const PreviewButtonWrapper = styled.div` + position: absolute; + left: -20px; + top: 50%; + transform: translateY(-50%); + z-index: 10; +`; + +function RollingPaperList({ cardData, totalPages, currentPage, onTurnCards }) { + return ( + + {cardData.map((item) => ( + +

To. {item.name}

+
+ {item.recentMessages.slice(0, 3).map((messageItem, index) => ( + {`profile-${index}`} + ))} + {item.messageCount > 3 ? ( +
+ +{item.messageCount - 3} +
+ ) : null} +
+ + {item.messageCount}명이 작성했어요! + +
test
+
+ ))} + {currentPage > 0 ? ( + onTurnCards("preview")}> + + + ) : null} + {currentPage < totalPages - 1 ? ( + onTurnCards("next")}> + + + ) : null} +
+ ); +} + +export default RollingPaperList; diff --git a/src/pages/rolling-paper-list-page.jsx b/src/pages/rolling-paper-list-page.jsx index be7816d..3b6e839 100644 --- a/src/pages/rolling-paper-list-page.jsx +++ b/src/pages/rolling-paper-list-page.jsx @@ -13,13 +13,7 @@ import axiosInstance from "../api/axios-instance"; import testDataFile from "./test_recipients_data.json"; import styled from "styled-components"; - -const backgroundColors = { - beige: "#FFD382", - purple: "#DCB9FF", - green: "#9BE282", - blue: "#9DDDFF", -}; +import RollingPaperList from "../features/rolling-paper/components/rolling-paper-list"; const TopContainer = styled.div` text-align: center; @@ -33,93 +27,25 @@ const CardTitle = styled.h2` text-align: left; `; -const CardContainer = styled.div` - border: 1px solid red; - display: grid; - grid-template-columns: 275px 275px 275px 275px; - gap: 20px; - width: fit-content; - - position: relative; - overflow: visible; -`; - -const CardItem = styled.div` - width: 275px; - height: 260px; - border: 1px solid red; - text-align: left; - padding: 30px 24px 20px 24px; - - display: grid; - grid-template-rows: 1fr 1fr auto; - - background-color: ${(props) => - backgroundColors[props.backgroundColor] || "white"}; - - img { - height: 28px; - width: 28px; - border-radius: 50%; - border: 1px solid #ffffff; - - margin-left: -12px; - &:first-child { - margin-left: 0; - } - } - - div.message-images { - display: flex; - } - - div.over-profile { - height: 28px; - width: 28px; - background-color: #ffffff; - border-radius: 50%; - - margin-left: -12px; - - display: flex; - justify-content: center; - align-items: center; - font-size: 12px; - } - - h2 { - margin: 0; - } - - div.emoji-div { - border-top: 1px solid red; - } -`; - -const NextButtonWrapper = styled.div` - position: absolute; - right: -20px; - top: 50%; - transform: translateY(-50%); - z-index: 10; -`; - -const PreviewButtonWrapper = styled.div` - position: absolute; - left: -20px; - top: 50%; - transform: translateY(-50%); - z-index: 10; -`; - const MakingButton = styled(PrimaryButton)` margin-top: 64px; font-weight: 400; padding: 14px 60px; `; +const cache = {}; +function getCachedImage(url) { + if (!cache[url]) { + cache[url] = new Image(); + cache[url].src = url; + } + return cache[url].src; +} + function ShowMessageList() { const [testData, setTestData] = useState([]); + const [popularDataList, setPopularDataList] = useState([]); + const [recentDataList, setRecentDataList] = useState([]); const [popularCurrentPage, setPopularCurrentPage] = useState(0); const [recentCurrentPage, setRecentCurrentPage] = useState(0); const [popularrecentShowCards, setPopularrecentShowCards] = useState([]); @@ -139,6 +65,24 @@ function ShowMessageList() { // }); }, []); + useEffect(() => { + testData.forEach((item) => { + getCachedImage(item.imageURL); + }); + }, [testData]); + + useEffect(() => { + const sortedPopular = testData + .slice() + .sort((a, b) => b.messageCount - a.messageCount); + setPopularDataList(sortedPopular); + + const sortedRecent = testData + .slice() + .sort((a, b) => b.createdAt - a.createdAt); + setRecentDataList(sortedRecent); + }, [testData]); + const totalPages = Math.ceil(testData.length / cardCount); useEffect(() => { @@ -148,14 +92,17 @@ function ShowMessageList() { const popularStartPageNum = popularCurrentPage * cardCount; const popularEndPageNum = popularStartPageNum + cardCount; - /* createdAt(생성된 시점)에 따라서 정렬 */ - setRecentShowCards(testData.slice(startPageNum, endPageNum)); - - /* 여기서 messageCount(메시지수)에 따라서 정렬 */ setPopularrecentShowCards( - testData.slice(popularStartPageNum, popularEndPageNum) + popularDataList.slice(popularStartPageNum, popularEndPageNum) ); - }, [popularCurrentPage, recentCurrentPage, testData]); + setRecentShowCards(recentDataList.slice(startPageNum, endPageNum)); + }, [ + popularCurrentPage, + recentCurrentPage, + testData, + popularDataList, + recentDataList, + ]); const handleTurnCards = (direction, mode) => { const current = mode === "popular" ? popularCurrentPage : recentCurrentPage; @@ -176,89 +123,22 @@ function ShowMessageList() {
인기 롤링 페이퍼 🔥 - - {popularrecentShowCards.map((item) => ( - -

To. {item.name}

-
- {item.recentMessages.slice(0, 3).map((messageItem, index) => ( - {`profile-${index}`} - ))} - {item.messageCount > 3 ? ( -
- +{item.messageCount - 3} -
- ) : null} -
- - {item.messageCount}명이 작성했어요! - -
test
-
- ))} - {popularCurrentPage > 0 ? ( - handleTurnCards("preview", "popular")} - > - - - ) : null} - {popularCurrentPage < totalPages - 1 ? ( - handleTurnCards("next", "popular")} - > - - - ) : null} -
+ handleTurnCards(direction, "popular")} + />
최근에 만든 롤링 페이퍼 ⭐ - - {recentShowCards.map((item) => ( - -

To. {item.name}

-
- {item.recentMessages.slice(0, 3).map((messageItem, index) => ( - {`profile-${index}`} - ))} - {item.messageCount > 3 ? ( -
- +{item.messageCount - 3} -
- ) : null} -
- - {item.messageCount}명이 작성했어요! - -
- ))} - {recentCurrentPage > 0 ? ( - handleTurnCards("preview", "recent")} - > - - - ) : null} - {recentCurrentPage < totalPages - 1 ? ( - handleTurnCards("next", "recent")} - > - - - ) : null} -
+ handleTurnCards(direction, "recent")} + />
diff --git a/src/pages/test_recipients_data.json b/src/pages/test_recipients_data.json index 3111f67..3d307a2 100644 --- a/src/pages/test_recipients_data.json +++ b/src/pages/test_recipients_data.json @@ -1,7 +1,7 @@ [ { "id": 7024, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "beige", "backgroundImageURL": null, "createdAt": "2023-10-22T19:15:11Z", @@ -151,10 +151,10 @@ { "id": 30238, "recipientId": 43558, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/340/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 32", + "content": "Suwon Kim님의 메세지 내용 32", "font": "Nanum Gothic", "createdAt": "2023-06-17T00:31:29Z" }, @@ -263,7 +263,7 @@ }, { "id": 18499, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "beige", "backgroundImageURL": "https://picsum.photos/seed/18499/600/400", "createdAt": "2023-06-03T04:15:47Z", @@ -272,10 +272,10 @@ { "id": 48979, "recipientId": 18499, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/11/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 77", + "content": "Suwon Kim님의 메세지 내용 77", "font": "Nanum Gothic", "createdAt": "2023-08-25T00:15:25Z" }, @@ -292,10 +292,10 @@ { "id": 35753, "recipientId": 18499, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/173/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 67", + "content": "Suwon Kim님의 메세지 내용 67", "font": "Nanum Gothic", "createdAt": "2023-07-23T23:14:30Z" } @@ -467,7 +467,7 @@ }, { "id": 13425, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "beige", "backgroundImageURL": "https://picsum.photos/seed/13425/600/400", "createdAt": "2023-07-06T20:30:52Z", @@ -567,10 +567,10 @@ { "id": 34424, "recipientId": 97436, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/141/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 6", + "content": "Suwon Kim님의 메세지 내용 6", "font": "Nanum Gothic", "createdAt": "2023-06-01T12:35:35Z" }, @@ -616,7 +616,7 @@ }, { "id": 22932, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "blue", "backgroundImageURL": "https://picsum.photos/seed/22932/600/400", "createdAt": "2023-12-21T05:29:02Z", @@ -779,10 +779,10 @@ { "id": 88963, "recipientId": 2194, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/317/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 81", + "content": "Suwon Kim님의 메세지 내용 81", "font": "Nanum Gothic", "createdAt": "2023-03-12T08:38:10Z" } @@ -992,7 +992,7 @@ }, { "id": 45901, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "purple", "backgroundImageURL": null, "createdAt": "2023-06-14T15:34:31Z", @@ -1165,10 +1165,10 @@ { "id": 99518, "recipientId": 84532, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/2/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 83", + "content": "Suwon Kim님의 메세지 내용 83", "font": "Nanum Gothic", "createdAt": "2023-07-12T22:08:05Z" }, @@ -1243,10 +1243,10 @@ { "id": 72173, "recipientId": 85839, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/137/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 84", + "content": "Suwon Kim님의 메세지 내용 84", "font": "Pretendard", "createdAt": "2023-04-01T12:40:19Z" } @@ -1359,10 +1359,10 @@ { "id": 20559, "recipientId": 76172, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/315/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 53", + "content": "Suwon Kim님의 메세지 내용 53", "font": "Roboto", "createdAt": "2023-07-06T05:06:42Z" }, @@ -1475,10 +1475,10 @@ { "id": 26243, "recipientId": 525, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/470/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 36", + "content": "Suwon Kim님의 메세지 내용 36", "font": "Noto Sans", "createdAt": "2024-02-01T22:09:11Z" }, @@ -1642,10 +1642,10 @@ { "id": 8442, "recipientId": 76854, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/391/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 6", + "content": "Suwon Kim님의 메세지 내용 6", "font": "Pretendard", "createdAt": "2023-12-21T09:27:19Z" }, @@ -1690,10 +1690,10 @@ { "id": 3111, "recipientId": 50919, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/384/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 80", + "content": "Suwon Kim님의 메세지 내용 80", "font": "Pretendard", "createdAt": "2023-08-12T11:51:00Z" }, @@ -1971,7 +1971,7 @@ }, { "id": 5465, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "beige", "backgroundImageURL": null, "createdAt": "2023-01-10T18:10:25Z", @@ -2353,10 +2353,10 @@ { "id": 66552, "recipientId": 90385, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/498/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 36", + "content": "Suwon Kim님의 메세지 내용 36", "font": "Noto Sans", "createdAt": "2023-10-17T11:54:41Z" } @@ -2497,10 +2497,10 @@ { "id": 59673, "recipientId": 39122, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/467/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 15", + "content": "Suwon Kim님의 메세지 내용 15", "font": "Nanum Gothic", "createdAt": "2023-03-20T07:58:11Z" }, @@ -2570,10 +2570,10 @@ { "id": 87956, "recipientId": 36279, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/362/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 45", + "content": "Suwon Kim님의 메세지 내용 45", "font": "Pretendard", "createdAt": "2023-01-10T01:43:19Z" } @@ -2802,10 +2802,10 @@ { "id": 60985, "recipientId": 2640, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/440/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 52", + "content": "Suwon Kim님의 메세지 내용 52", "font": "Pretendard", "createdAt": "2023-05-11T23:03:58Z" }, @@ -3256,20 +3256,20 @@ { "id": 96788, "recipientId": 73648, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/249/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 54", + "content": "Suwon Kim님의 메세지 내용 54", "font": "Nanum Gothic", "createdAt": "2023-09-16T01:58:06Z" }, { "id": 20726, "recipientId": 73648, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/431/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 78", + "content": "Suwon Kim님의 메세지 내용 78", "font": "Pretendard", "createdAt": "2023-07-25T07:59:44Z" } @@ -3725,10 +3725,10 @@ { "id": 65998, "recipientId": 73391, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/117/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 7", + "content": "Suwon Kim님의 메세지 내용 7", "font": "Noto Sans", "createdAt": "2023-06-29T21:54:39Z" } @@ -3953,7 +3953,7 @@ }, { "id": 26744, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "beige", "backgroundImageURL": null, "createdAt": "2023-03-23T03:14:00Z", @@ -4098,10 +4098,10 @@ { "id": 35228, "recipientId": 90477, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/94/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 63", + "content": "Suwon Kim님의 메세지 내용 63", "font": "Roboto", "createdAt": "2023-05-25T06:02:55Z" }, @@ -4457,7 +4457,7 @@ }, { "id": 31714, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "beige", "backgroundImageURL": "https://picsum.photos/seed/31714/600/400", "createdAt": "2023-01-13T08:26:56Z", @@ -4529,10 +4529,10 @@ { "id": 88820, "recipientId": 24976, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/355/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 72", + "content": "Suwon Kim님의 메세지 내용 72", "font": "Pretendard", "createdAt": "2023-12-02T16:28:28Z" } @@ -4713,10 +4713,10 @@ { "id": 35658, "recipientId": 9191, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/62/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 27", + "content": "Suwon Kim님의 메세지 내용 27", "font": "Nanum Gothic", "createdAt": "2023-04-09T12:56:46Z" }, @@ -4733,10 +4733,10 @@ { "id": 20041, "recipientId": 9191, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/114/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 72", + "content": "Suwon Kim님의 메세지 내용 72", "font": "Pretendard", "createdAt": "2023-11-11T12:43:30Z" } @@ -4834,10 +4834,10 @@ { "id": 53736, "recipientId": 625, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/411/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 98", + "content": "Suwon Kim님의 메세지 내용 98", "font": "Nanum Gothic", "createdAt": "2023-06-06T17:47:12Z" }, @@ -4907,10 +4907,10 @@ { "id": 53607, "recipientId": 23417, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/402/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 96", + "content": "Suwon Kim님의 메세지 내용 96", "font": "Noto Sans", "createdAt": "2023-06-28T04:25:20Z" } @@ -5081,10 +5081,10 @@ { "id": 76625, "recipientId": 48647, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/256/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 98", + "content": "Suwon Kim님의 메세지 내용 98", "font": "Pretendard", "createdAt": "2023-03-21T02:42:08Z" }, @@ -5144,10 +5144,10 @@ { "id": 90888, "recipientId": 7110, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/19/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 42", + "content": "Suwon Kim님의 메세지 내용 42", "font": "Roboto", "createdAt": "2023-09-16T18:15:50Z" }, @@ -5256,7 +5256,7 @@ }, { "id": 75973, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "beige", "backgroundImageURL": "https://picsum.photos/seed/75973/600/400", "createdAt": "2023-04-29T23:14:33Z", @@ -5265,10 +5265,10 @@ { "id": 85401, "recipientId": 75973, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/269/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 90", + "content": "Suwon Kim님의 메세지 내용 90", "font": "Noto Sans", "createdAt": "2023-11-12T05:17:44Z" }, @@ -5755,7 +5755,7 @@ }, { "id": 32314, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "purple", "backgroundImageURL": null, "createdAt": "2023-06-09T07:16:23Z", @@ -5774,10 +5774,10 @@ { "id": 10034, "recipientId": 32314, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/288/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 22", + "content": "Suwon Kim님의 메세지 내용 22", "font": "Pretendard", "createdAt": "2023-09-14T13:27:24Z" }, @@ -5938,10 +5938,10 @@ { "id": 50489, "recipientId": 63219, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/11/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 77", + "content": "Suwon Kim님의 메세지 내용 77", "font": "Noto Sans", "createdAt": "2023-11-27T08:16:32Z" } @@ -5962,7 +5962,7 @@ }, { "id": 32218, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "beige", "backgroundImageURL": null, "createdAt": "2023-07-22T22:33:51Z", @@ -6107,10 +6107,10 @@ { "id": 24988, "recipientId": 1341, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/423/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 64", + "content": "Suwon Kim님의 메세지 내용 64", "font": "Roboto", "createdAt": "2023-01-06T05:53:05Z" } @@ -6184,7 +6184,7 @@ }, { "id": 93438, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "blue", "backgroundImageURL": "https://picsum.photos/seed/93438/600/400", "createdAt": "2023-04-02T11:00:53Z", @@ -6203,10 +6203,10 @@ { "id": 6156, "recipientId": 93438, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/109/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 59", + "content": "Suwon Kim님의 메세지 내용 59", "font": "Noto Sans", "createdAt": "2023-01-24T10:30:39Z" }, @@ -6232,7 +6232,7 @@ }, { "id": 44334, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "blue", "backgroundImageURL": "https://picsum.photos/seed/44334/600/400", "createdAt": "2023-12-30T01:42:47Z", @@ -6353,7 +6353,7 @@ }, { "id": 44928, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "beige", "backgroundImageURL": null, "createdAt": "2023-11-24T12:12:26Z", @@ -6405,10 +6405,10 @@ { "id": 31761, "recipientId": 94539, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/62/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 53", + "content": "Suwon Kim님의 메세지 내용 53", "font": "Pretendard", "createdAt": "2023-04-17T18:23:36Z" }, @@ -6970,10 +6970,10 @@ { "id": 41596, "recipientId": 43809, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/439/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 36", + "content": "Suwon Kim님의 메세지 내용 36", "font": "Roboto", "createdAt": "2023-02-12T07:13:07Z" }, @@ -7086,10 +7086,10 @@ { "id": 62162, "recipientId": 62125, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/293/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 93", + "content": "Suwon Kim님의 메세지 내용 93", "font": "Roboto", "createdAt": "2023-04-29T23:05:56Z" } @@ -7207,10 +7207,10 @@ { "id": 91516, "recipientId": 58844, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/108/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 82", + "content": "Suwon Kim님의 메세지 내용 82", "font": "Pretendard", "createdAt": "2023-08-27T12:05:46Z" } @@ -7260,10 +7260,10 @@ { "id": 29903, "recipientId": 72437, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/106/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 40", + "content": "Suwon Kim님의 메세지 내용 40", "font": "Roboto", "createdAt": "2023-04-29T16:49:48Z" } @@ -7323,10 +7323,10 @@ { "id": 91691, "recipientId": 31124, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/461/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 53", + "content": "Suwon Kim님의 메세지 내용 53", "font": "Roboto", "createdAt": "2023-05-21T09:55:42Z" } @@ -7347,7 +7347,7 @@ }, { "id": 73111, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "blue", "backgroundImageURL": null, "createdAt": "2023-12-29T11:24:51Z", @@ -7419,10 +7419,10 @@ { "id": 2974, "recipientId": 44599, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/46/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 13", + "content": "Suwon Kim님의 메세지 내용 13", "font": "Roboto", "createdAt": "2023-11-11T07:56:34Z" }, @@ -7710,7 +7710,7 @@ }, { "id": 72332, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "purple", "backgroundImageURL": "https://picsum.photos/seed/72332/600/400", "createdAt": "2023-10-08T20:12:12Z", @@ -7815,10 +7815,10 @@ { "id": 47612, "recipientId": 6048, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/97/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 72", + "content": "Suwon Kim님의 메세지 내용 72", "font": "Pretendard", "createdAt": "2023-12-11T12:42:57Z" }, @@ -7888,10 +7888,10 @@ { "id": 54283, "recipientId": 7768, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/368/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 8", + "content": "Suwon Kim님의 메세지 내용 8", "font": "Nanum Gothic", "createdAt": "2023-02-19T15:25:55Z" }, @@ -7946,10 +7946,10 @@ { "id": 66344, "recipientId": 60032, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/444/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 47", + "content": "Suwon Kim님의 메세지 내용 47", "font": "Pretendard", "createdAt": "2023-07-26T07:54:55Z" } @@ -8418,10 +8418,10 @@ { "id": 48175, "recipientId": 96506, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/145/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 86", + "content": "Suwon Kim님의 메세지 내용 86", "font": "Pretendard", "createdAt": "2023-03-13T10:17:35Z" }, @@ -8607,10 +8607,10 @@ { "id": 11805, "recipientId": 10732, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/76/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 48", + "content": "Suwon Kim님의 메세지 내용 48", "font": "Nanum Gothic", "createdAt": "2023-12-29T05:06:21Z" } @@ -8708,10 +8708,10 @@ { "id": 94450, "recipientId": 64061, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/353/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 61", + "content": "Suwon Kim님의 메세지 내용 61", "font": "Pretendard", "createdAt": "2023-12-02T06:48:01Z" }, @@ -8737,7 +8737,7 @@ }, { "id": 15549, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "blue", "backgroundImageURL": null, "createdAt": "2023-12-13T10:07:11Z", @@ -8819,10 +8819,10 @@ { "id": 67124, "recipientId": 84213, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/482/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 81", + "content": "Suwon Kim님의 메세지 내용 81", "font": "Pretendard", "createdAt": "2023-04-16T14:42:59Z" }, @@ -8930,10 +8930,10 @@ { "id": 91701, "recipientId": 83558, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/169/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 97", + "content": "Suwon Kim님의 메세지 내용 97", "font": "Noto Sans", "createdAt": "2023-11-22T09:50:03Z" }, @@ -9061,10 +9061,10 @@ { "id": 86215, "recipientId": 1220, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/419/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 25", + "content": "Suwon Kim님의 메세지 내용 25", "font": "Pretendard", "createdAt": "2023-05-10T21:59:12Z" } @@ -9085,7 +9085,7 @@ }, { "id": 53959, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "blue", "backgroundImageURL": "https://picsum.photos/seed/53959/600/400", "createdAt": "2023-08-24T05:22:48Z", @@ -9114,10 +9114,10 @@ { "id": 59151, "recipientId": 53959, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/10/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 4", + "content": "Suwon Kim님의 메세지 내용 4", "font": "Nanum Gothic", "createdAt": "2023-03-11T07:04:18Z" } @@ -9216,7 +9216,7 @@ }, { "id": 51432, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "beige", "backgroundImageURL": "https://picsum.photos/seed/51432/600/400", "createdAt": "2023-11-07T07:07:37Z", @@ -9235,10 +9235,10 @@ { "id": 33808, "recipientId": 51432, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/478/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 8", + "content": "Suwon Kim님의 메세지 내용 8", "font": "Pretendard", "createdAt": "2023-04-04T10:06:15Z" }, @@ -9742,10 +9742,10 @@ { "id": 93059, "recipientId": 73798, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/252/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 99", + "content": "Suwon Kim님의 메세지 내용 99", "font": "Roboto", "createdAt": "2023-11-21T09:01:45Z" }, @@ -9868,10 +9868,10 @@ { "id": 33941, "recipientId": 3992, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/364/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 93", + "content": "Suwon Kim님의 메세지 내용 93", "font": "Pretendard", "createdAt": "2023-02-13T23:03:26Z" }, @@ -9964,10 +9964,10 @@ { "id": 89359, "recipientId": 63758, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/401/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 53", + "content": "Suwon Kim님의 메세지 내용 53", "font": "Roboto", "createdAt": "2023-05-10T19:04:15Z" }, @@ -10084,7 +10084,7 @@ }, { "id": 63096, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "blue", "backgroundImageURL": "https://picsum.photos/seed/63096/600/400", "createdAt": "2023-08-25T09:30:08Z", @@ -10093,10 +10093,10 @@ { "id": 72995, "recipientId": 63096, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/368/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 44", + "content": "Suwon Kim님의 메세지 내용 44", "font": "Pretendard", "createdAt": "2023-10-07T18:41:59Z" }, @@ -10151,10 +10151,10 @@ { "id": 44494, "recipientId": 13289, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/118/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 64", + "content": "Suwon Kim님의 메세지 내용 64", "font": "Nanum Gothic", "createdAt": "2024-01-29T16:37:33Z" }, @@ -10534,10 +10534,10 @@ { "id": 33150, "recipientId": 66190, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/26/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 47", + "content": "Suwon Kim님의 메세지 내용 47", "font": "Roboto", "createdAt": "2024-01-22T00:03:15Z" } @@ -10558,7 +10558,7 @@ }, { "id": 68635, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "beige", "backgroundImageURL": null, "createdAt": "2023-10-22T10:14:45Z", @@ -10625,10 +10625,10 @@ { "id": 8378, "recipientId": 52236, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/383/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 53", + "content": "Suwon Kim님의 메세지 내용 53", "font": "Pretendard", "createdAt": "2023-12-03T19:03:51Z" } @@ -10663,10 +10663,10 @@ { "id": 14027, "recipientId": 81115, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/400/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 48", + "content": "Suwon Kim님의 메세지 내용 48", "font": "Noto Sans", "createdAt": "2023-09-18T14:09:01Z" }, @@ -10885,10 +10885,10 @@ { "id": 16314, "recipientId": 60, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/345/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 52", + "content": "Suwon Kim님의 메세지 내용 52", "font": "Roboto", "createdAt": "2023-03-07T04:55:33Z" } @@ -10928,10 +10928,10 @@ { "id": 81467, "recipientId": 66554, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/487/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 17", + "content": "Suwon Kim님의 메세지 내용 17", "font": "Nanum Gothic", "createdAt": "2023-03-16T05:19:39Z" }, @@ -11155,10 +11155,10 @@ { "id": 19962, "recipientId": 31459, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/80/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 11", + "content": "Suwon Kim님의 메세지 내용 11", "font": "Nanum Gothic", "createdAt": "2023-11-26T04:31:20Z" } @@ -11402,10 +11402,10 @@ { "id": 24156, "recipientId": 41885, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/360/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 14", + "content": "Suwon Kim님의 메세지 내용 14", "font": "Noto Sans", "createdAt": "2023-07-13T21:35:18Z" }, @@ -11816,20 +11816,20 @@ { "id": 86564, "recipientId": 46642, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/36/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 78", + "content": "Suwon Kim님의 메세지 내용 78", "font": "Noto Sans", "createdAt": "2023-09-23T23:48:17Z" }, { "id": 46880, "recipientId": 46642, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/453/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 92", + "content": "Suwon Kim님의 메세지 내용 92", "font": "Noto Sans", "createdAt": "2023-06-07T09:44:08Z" }, @@ -11928,7 +11928,7 @@ }, { "id": 93469, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "beige", "backgroundImageURL": "https://picsum.photos/seed/93469/600/400", "createdAt": "2023-08-05T08:37:01Z", @@ -11991,7 +11991,7 @@ }, { "id": 45950, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "green", "backgroundImageURL": "https://picsum.photos/seed/45950/600/400", "createdAt": "2023-04-24T21:39:46Z", @@ -12489,10 +12489,10 @@ { "id": 46241, "recipientId": 30047, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/397/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 64", + "content": "Suwon Kim님의 메세지 내용 64", "font": "Roboto", "createdAt": "2023-04-12T04:50:45Z" }, @@ -12833,7 +12833,7 @@ }, { "id": 44091, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "blue", "backgroundImageURL": "https://picsum.photos/seed/44091/600/400", "createdAt": "2023-06-17T19:51:45Z", @@ -13349,10 +13349,10 @@ { "id": 58525, "recipientId": 62965, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/103/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 1", + "content": "Suwon Kim님의 메세지 내용 1", "font": "Noto Sans", "createdAt": "2023-04-24T14:22:46Z" }, @@ -13387,10 +13387,10 @@ { "id": 86114, "recipientId": 61614, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/1/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 48", + "content": "Suwon Kim님의 메세지 내용 48", "font": "Noto Sans", "createdAt": "2023-11-16T04:24:55Z" }, @@ -13494,7 +13494,7 @@ }, { "id": 31146, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "green", "backgroundImageURL": null, "createdAt": "2023-09-27T13:42:38Z", @@ -13551,10 +13551,10 @@ { "id": 80875, "recipientId": 99123, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/42/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 14", + "content": "Suwon Kim님의 메세지 내용 14", "font": "Roboto", "createdAt": "2023-11-30T19:44:40Z" }, @@ -13682,10 +13682,10 @@ { "id": 9237, "recipientId": 16143, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/437/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 14", + "content": "Suwon Kim님의 메세지 내용 14", "font": "Pretendard", "createdAt": "2023-03-17T21:44:08Z" } @@ -13793,10 +13793,10 @@ { "id": 31892, "recipientId": 98422, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/8/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 43", + "content": "Suwon Kim님의 메세지 내용 43", "font": "Pretendard", "createdAt": "2023-09-02T03:23:20Z" } @@ -13841,10 +13841,10 @@ { "id": 85445, "recipientId": 53532, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/363/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 51", + "content": "Suwon Kim님의 메세지 내용 51", "font": "Noto Sans", "createdAt": "2023-09-23T11:29:56Z" }, @@ -13904,10 +13904,10 @@ { "id": 86518, "recipientId": 93792, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/204/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 9", + "content": "Suwon Kim님의 메세지 내용 9", "font": "Roboto", "createdAt": "2023-01-22T13:44:09Z" }, @@ -13924,10 +13924,10 @@ { "id": 9752, "recipientId": 93792, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/171/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 68", + "content": "Suwon Kim님의 메세지 내용 68", "font": "Roboto", "createdAt": "2023-02-15T23:39:35Z" } @@ -13992,10 +13992,10 @@ { "id": 84648, "recipientId": 12242, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/112/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 4", + "content": "Suwon Kim님의 메세지 내용 4", "font": "Pretendard", "createdAt": "2024-01-06T11:37:10Z" } @@ -14098,10 +14098,10 @@ { "id": 35816, "recipientId": 76148, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/488/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 96", + "content": "Suwon Kim님의 메세지 내용 96", "font": "Nanum Gothic", "createdAt": "2023-04-09T14:21:56Z" } @@ -14179,10 +14179,10 @@ { "id": 76780, "recipientId": 38642, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/253/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 24", + "content": "Suwon Kim님의 메세지 내용 24", "font": "Nanum Gothic", "createdAt": "2023-07-12T11:54:03Z" }, @@ -14391,10 +14391,10 @@ { "id": 78207, "recipientId": 55884, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/155/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 87", + "content": "Suwon Kim님의 메세지 내용 87", "font": "Pretendard", "createdAt": "2023-06-01T07:21:37Z" }, @@ -14454,10 +14454,10 @@ { "id": 2300, "recipientId": 65809, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/358/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 60", + "content": "Suwon Kim님의 메세지 내용 60", "font": "Roboto", "createdAt": "2023-05-12T09:25:19Z" }, @@ -14527,10 +14527,10 @@ { "id": 12155, "recipientId": 47549, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/247/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 80", + "content": "Suwon Kim님의 메세지 내용 80", "font": "Pretendard", "createdAt": "2023-03-09T22:19:14Z" }, @@ -14620,10 +14620,10 @@ { "id": 64811, "recipientId": 7135, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/184/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 9", + "content": "Suwon Kim님의 메세지 내용 9", "font": "Roboto", "createdAt": "2023-10-17T00:36:13Z" } @@ -15117,10 +15117,10 @@ { "id": 65322, "recipientId": 21977, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/156/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 79", + "content": "Suwon Kim님의 메세지 내용 79", "font": "Nanum Gothic", "createdAt": "2023-09-13T04:30:55Z" } @@ -15155,10 +15155,10 @@ { "id": 37649, "recipientId": 67245, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/160/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 84", + "content": "Suwon Kim님의 메세지 내용 84", "font": "Roboto", "createdAt": "2023-05-09T12:36:18Z" }, @@ -15654,10 +15654,10 @@ { "id": 7778, "recipientId": 37498, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/202/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 24", + "content": "Suwon Kim님의 메세지 내용 24", "font": "Pretendard", "createdAt": "2023-12-27T07:03:22Z" }, @@ -15887,7 +15887,7 @@ }, { "id": 12700, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "purple", "backgroundImageURL": null, "createdAt": "2023-08-18T22:43:12Z", @@ -15916,10 +15916,10 @@ { "id": 4746, "recipientId": 12700, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/260/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 44", + "content": "Suwon Kim님의 메세지 내용 44", "font": "Noto Sans", "createdAt": "2023-02-17T03:59:23Z" } @@ -16181,10 +16181,10 @@ { "id": 47661, "recipientId": 56031, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/395/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 62", + "content": "Suwon Kim님의 메세지 내용 62", "font": "Nanum Gothic", "createdAt": "2023-08-20T17:27:35Z" }, @@ -17115,7 +17115,7 @@ }, { "id": 31249, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "blue", "backgroundImageURL": null, "createdAt": "2023-05-16T17:41:45Z", @@ -17134,10 +17134,10 @@ { "id": 54855, "recipientId": 31249, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/188/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 84", + "content": "Suwon Kim님의 메세지 내용 84", "font": "Pretendard", "createdAt": "2023-07-01T14:34:04Z" } @@ -17163,7 +17163,7 @@ }, { "id": 87008, - "name": "이병헌", + "name": "Suwon Kim", "backgroundColor": "purple", "backgroundImageURL": null, "createdAt": "2023-05-31T18:24:49Z", @@ -17182,10 +17182,10 @@ { "id": 29069, "recipientId": 87008, - "sender": "이병헌", + "sender": "Suwon Kim", "profileImageURL": "https://picsum.photos/id/25/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 19", + "content": "Suwon Kim님의 메세지 내용 19", "font": "Roboto", "createdAt": "2024-01-14T03:59:30Z" }, From 91cfc560b867dd9ebc81b26a64d9682ea3e483c6 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Sat, 16 Aug 2025 15:07:02 +0900 Subject: [PATCH 117/253] =?UTF-8?q?feat=20#29=20=EC=95=84=EB=B0=94?= =?UTF-8?q?=ED=83=80=20=EC=98=B5=EC=85=98=20=EC=84=A0=ED=83=9D=20=EC=8B=9C?= =?UTF-8?q?=20=EB=B0=98=EC=98=81,=20=EB=8B=A4=EC=8B=9C=20=ED=81=B4?= =?UTF-8?q?=EB=A6=AD=ED=95=98=EB=A9=B4=20=EA=B8=B0=EB=B3=B8=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80=EB=A1=9C=20=EB=8F=8C=EC=95=84=EA=B0=80?= =?UTF-8?q?=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/send-message-page.jsx | 90 ++++++++++++++++----------------- 1 file changed, 44 insertions(+), 46 deletions(-) diff --git a/src/pages/send-message-page.jsx b/src/pages/send-message-page.jsx index 286c5d3..d29c76c 100644 --- a/src/pages/send-message-page.jsx +++ b/src/pages/send-message-page.jsx @@ -31,14 +31,14 @@ const AvatarWrapper = styled.div` gap: 32px; `; -const AvatarSummaryWrapper = styled.div` +const AvatarOptionWrapper = styled.div` display: flex; flex-direction: column; justify-content: center; width: 80%; `; -const AvatarSummary = styled.p` +const AvatarDescription = styled.p` font-weight: 400; color: ${Colors.gray(500)}; `; @@ -48,6 +48,16 @@ const AvatarOption = styled.div` justify-content: space-between; `; +const AvatarPreview = styled.div` + cursor: pointer; +`; + +const DefaultAvatar = styled.div` + cursor: pointer; +`; + +const DEFAULT_AVATAR = ; + const ToggleButtonWrapper = styled.div` width: 100%; display: flex; @@ -57,6 +67,7 @@ function SendMessagePage() { const [name, setName] = useState(""); const [nameError, setNameError] = useState(""); const [option, setOption] = useState("지인"); + const [selectedAvatar, setSelectedAvatar] = useState(null); const handleChange = (e) => { const value = e.target.value; @@ -76,6 +87,19 @@ function SendMessagePage() { } }; + const avatarList = [ + "https://i.pinimg.com/236x/49/86/62/4986627b45cecd1a5c4330bda777c2bf.jpg", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRok3sjZOWtm7o5kFf0BdW0w7IUHI1oAlC-Z6RCKAiCvvCExG_qq7qMzPOQlEzfknS3B3U&usqp=CAU", + "https://i.pinimg.com/236x/20/d1/6f/20d16f236500e8daa315a298a8586193.jpg", + "https://i.pinimg.com/474x/28/6c/fd/286cfdcdaeaf2768d4b285a226c33a02.jpg", + "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRvxR-Twic2lXwfF87JweyQ81vrGDUgn7zzYj60N-wD21DwS4JzOc0BLhzaOuUt4PGfLcI&usqp=CAU", + "https://i.pinimg.com/236x/74/68/89/7468894ce7592357a3514dbb8dc5f181.jpg", + "https://mblogthumb-phinf.pstatic.net/MjAyMTA5MDNfMjE1/MDAxNjMwNTk5NjE4NTc5.b-OgHjcav5kz8kt_9Cr2u1Z_eJYmKY_H9Ii9mOnwo74g.r0G6iGYg-oQMLnTymwyrjDlOMGLEnWGYJXefCSy2ixwg.JPEG.gmlwjd5363/FB_IMG_1630599533529.jpg?type=w800", + "https://mblogthumb-phinf.pstatic.net/MjAyMTA5MDNfMTIy/MDAxNjMwNTk5NjE5MDA5.w_wMeYmMF2kOhDAVXXxe0JgVqJhtGd0EuR0b2D2k3S0g.Nds6Oxagjks2DjjwFz5yWyjCGcEOL1iS84XqhAQw3wUg.JPEG.gmlwjd5363/FB_IMG_1630599535069.jpg?type=w800", + "https://mblogthumb-phinf.pstatic.net/MjAyMTA5MDNfNDQg/MDAxNjMwNTk5NjE5MzQ4.J4lhtJZRKMzEXj0HjrG1aH65qIcBv9GI1LdVQsWlC-Ug.10QCNt81CdbIyBkd1bFOAOAolDL6hxYXrb9dXgmS8zQg.JPEG.gmlwjd5363/FB_IMG_1630599536666.jpg?type=w800", + "https://mblogthumb-phinf.pstatic.net/MjAyMTA5MDNfMzAg/MDAxNjMwNTk5NjE5ODI2.cmwNyDHTza4N64bhN0rIRu2KaFHUxqv0BkuaX6GBHJ0g.ufZqe7x1GLrCLJg2zb6N_nJ_fTgFPXq09TTe_fhsMiog.JPEG.gmlwjd5363/FB_IMG_1630599538261.jpg?type=w800", + ]; + return ( @@ -92,52 +116,26 @@ function SendMessagePage() { 프로필 이미지 - - - 프로필 이미지를 선택해 주세요! + setSelectedAvatar((prev) => (prev ? null : prev))} + > + + + + + 프로필 이미지를 선택해 주세요! + - - - - - - - - - - + {avatarList.map((url, index) => ( + setSelectedAvatar(url)} + > + + + ))} - + From e9b89be22a7b68d96af1f63932f6c4a38d9b1c9f Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Sat, 16 Aug 2025 15:20:52 +0900 Subject: [PATCH 118/253] =?UTF-8?q?feat=20#29=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=ED=95=98=EA=B8=B0=20=EB=B2=84=ED=8A=BC=20=EC=9D=B4=EB=A6=84,?= =?UTF-8?q?=20=EC=95=84=EB=B0=94=ED=83=80=20=EC=9E=85=EB=A0=A5=20=EC=8B=9C?= =?UTF-8?q?=20=ED=99=9C=EC=84=B1=ED=99=94=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/create-post-page.jsx | 2 +- src/pages/send-message-page.jsx | 33 +++++++++++++++++++++++++-------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/src/pages/create-post-page.jsx b/src/pages/create-post-page.jsx index c94b407..03383b0 100644 --- a/src/pages/create-post-page.jsx +++ b/src/pages/create-post-page.jsx @@ -82,7 +82,7 @@ function CreatePostPage() { navigate(`/post/${randomID}`); }; - const canCreate = name !== "" || name !== name.trim(); + const canCreate = name.trim() !== ""; return ( diff --git a/src/pages/send-message-page.jsx b/src/pages/send-message-page.jsx index d29c76c..de178ee 100644 --- a/src/pages/send-message-page.jsx +++ b/src/pages/send-message-page.jsx @@ -2,10 +2,12 @@ import { useState } from "react"; import TextField from "../components/text-field/text-field"; import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; import Colors from "../components/color/colors"; -import ToggleButton from "../components/button/toggle-button"; import styled from "styled-components"; import Avatar from "../components/avatar/avatar"; import AVATAR_SIZE from "../components/avatar/avatar-size"; +import BUTTON_SIZE from "../components/button/button-size"; +import { useNavigate } from "react-router"; +import { PrimaryButton } from "../components/button/button"; const SendContainer = styled.div` display: flex; @@ -56,11 +58,13 @@ const DefaultAvatar = styled.div` cursor: pointer; `; -const DEFAULT_AVATAR = ; +const ButtonWrapper = styled.div` + padding-top: 50px; + width: 720px; +`; -const ToggleButtonWrapper = styled.div` +const CreateButton = styled(PrimaryButton)` width: 100%; - display: flex; `; function SendMessagePage() { @@ -68,6 +72,7 @@ function SendMessagePage() { const [nameError, setNameError] = useState(""); const [option, setOption] = useState("지인"); const [selectedAvatar, setSelectedAvatar] = useState(null); + const navigate = useNavigate(); const handleChange = (e) => { const value = e.target.value; @@ -100,6 +105,13 @@ function SendMessagePage() { "https://mblogthumb-phinf.pstatic.net/MjAyMTA5MDNfMzAg/MDAxNjMwNTk5NjE5ODI2.cmwNyDHTza4N64bhN0rIRu2KaFHUxqv0BkuaX6GBHJ0g.ufZqe7x1GLrCLJg2zb6N_nJ_fTgFPXq09TTe_fhsMiog.JPEG.gmlwjd5363/FB_IMG_1630599538261.jpg?type=w800", ]; + const handleCreate = () => { + const randomID = Math.floor(Math.random() * 10000); + navigate(`/post/${randomID}`); + }; + + const canCreate = name.trim() !== "" && selectedAvatar !== null; + return ( @@ -117,7 +129,7 @@ function SendMessagePage() { 프로필 이미지 setSelectedAvatar((prev) => (prev ? null : prev))} + onClick={() => setSelectedAvatar((prev) => (prev ? null : prev))} // 아바타 선택 상태에서 재클릭 시 기본 아바타로 > @@ -155,9 +167,14 @@ function SendMessagePage() { 폰트 선택 - - - + + + ); } From 0e331998a1a0f06b59982839d2e2ac8a879851eb Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Sat, 16 Aug 2025 15:22:26 +0900 Subject: [PATCH 119/253] =?UTF-8?q?fix=20#29=20=EC=83=9D=EC=84=B1=ED=95=98?= =?UTF-8?q?=EA=B8=B0=20=EB=B2=84=ED=8A=BC=20=ED=99=9C=EC=84=B1=ED=99=94=20?= =?UTF-8?q?=EC=A1=B0=EA=B1=B4=20=EC=95=84=EB=B0=94=ED=83=80=20=EC=A0=9C?= =?UTF-8?q?=EC=99=B8(=EC=B9=B4=EB=93=9C=20=EB=82=B4=EC=9A=A9=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20=EC=98=88=EC=A0=95)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/send-message-page.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/send-message-page.jsx b/src/pages/send-message-page.jsx index de178ee..71a5425 100644 --- a/src/pages/send-message-page.jsx +++ b/src/pages/send-message-page.jsx @@ -110,7 +110,7 @@ function SendMessagePage() { navigate(`/post/${randomID}`); }; - const canCreate = name.trim() !== "" && selectedAvatar !== null; + const canCreate = name.trim() !== ""; return ( From ca55063941e7a32a138490876b9964d500f415bd Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Sat, 16 Aug 2025 16:01:51 +0900 Subject: [PATCH 120/253] =?UTF-8?q?feat=20#47=20=ED=85=8D=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=97=90=EB=94=94=ED=84=B0=20=EB=AA=A8=EB=93=88=20?= =?UTF-8?q?=EC=84=A4=EC=B9=98=20=EB=B0=8F=20=ED=88=B4=EB=B0=94=20=EB=94=94?= =?UTF-8?q?=EC=9E=90=EC=9D=B8=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 4 ++ package-lock.json | 82 ++++++++++++++++++++++ package.json | 1 + src/components/text-editor/text-editor.tsx | 35 +++++++++ src/pages/send-message-page.jsx | 9 +++ 5 files changed, 131 insertions(+) create mode 100644 src/components/text-editor/text-editor.tsx diff --git a/index.html b/index.html index 07a9876..926d726 100644 --- a/index.html +++ b/index.html @@ -11,6 +11,10 @@ crossorigin href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css" /> + Rolling diff --git a/package-lock.json b/package-lock.json index 7d25d6a..d602993 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "axios": "^1.11.0", "react": "^19.1.1", "react-dom": "^19.1.1", + "react-quill-new": "^3.6.0", "react-router": "^7.8.0", "react-router-dom": "^7.8.0", "styled-components": "^6.1.19" @@ -2078,6 +2079,12 @@ "node": ">=0.10.0" } }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2085,6 +2092,12 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "license": "Apache-2.0" + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -2533,6 +2546,25 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "license": "MIT" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -2682,6 +2714,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parchment": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/parchment/-/parchment-3.0.0.tgz", + "integrity": "sha512-HUrJFQ/StvgmXRcQ1ftY6VEZUq3jA2t9ncFN4F84J/vN0/FPpQF+8FKXb3l6fLces6q0uOHj6NJn+2xvZnxO6A==", + "license": "BSD-3-Clause" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -2795,6 +2833,35 @@ "node": ">=6" } }, + "node_modules/quill": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/quill/-/quill-2.0.3.tgz", + "integrity": "sha512-xEYQBqfYx/sfb33VJiKnSJp8ehloavImQ2A6564GAbqG55PGw1dAWUn1MUbQB62t0azawUS2CZZhWCjO8gRvTw==", + "license": "BSD-3-Clause", + "dependencies": { + "eventemitter3": "^5.0.1", + "lodash-es": "^4.17.21", + "parchment": "^3.0.0", + "quill-delta": "^5.1.0" + }, + "engines": { + "npm": ">=8.2.3" + } + }, + "node_modules/quill-delta": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-5.1.0.tgz", + "integrity": "sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==", + "license": "MIT", + "dependencies": { + "fast-diff": "^1.3.0", + "lodash.clonedeep": "^4.5.0", + "lodash.isequal": "^4.5.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/react": { "version": "19.1.1", "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz", @@ -2816,6 +2883,21 @@ "react": "^19.1.1" } }, + "node_modules/react-quill-new": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/react-quill-new/-/react-quill-new-3.6.0.tgz", + "integrity": "sha512-weU6YfB2+7Cujw5Hjgmi0aN/qJd3B6ADWrxgUJMp2MO3tEvKX5kfB0sg3P0UdOVfU0z8icsKFzlnEIpeW1mLhw==", + "license": "MIT", + "dependencies": { + "lodash-es": "^4.17.21", + "quill": "~2.0.2" + }, + "peerDependencies": { + "quill-delta": "^5.1.0", + "react": "^16 || ^17 || ^18 || ^19", + "react-dom": "^16 || ^17 || ^18 || ^19" + } + }, "node_modules/react-refresh": { "version": "0.17.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", diff --git a/package.json b/package.json index 6364243..ba5eeb7 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "axios": "^1.11.0", "react": "^19.1.1", "react-dom": "^19.1.1", + "react-quill-new": "^3.6.0", "react-router": "^7.8.0", "react-router-dom": "^7.8.0", "styled-components": "^6.1.19" diff --git a/src/components/text-editor/text-editor.tsx b/src/components/text-editor/text-editor.tsx new file mode 100644 index 0000000..2b4ee18 --- /dev/null +++ b/src/components/text-editor/text-editor.tsx @@ -0,0 +1,35 @@ +import { useState } from "react"; +import ReactQuill from "react-quill-new"; +import "react-quill-new/dist/quill.snow.css"; + +interface TextEditorProps { + style?: any; + value?: string; + onChange: (value: string) => void; +} + +function TextEditor({ style, value, onChange }: TextEditorProps) { + const modules = { + toolbar: { + container: [ + ["bold", "italic", "underline"], + [{ align: "center" }, { align: "right" }, { align: "justify" }], + [{ list: "bullet" }, { list: "ordered" }], + [{ background: [] }, { color: [] }], + ], + }, + }; + + return ( + <> + + + ); +} + +export default TextEditor; diff --git a/src/pages/send-message-page.jsx b/src/pages/send-message-page.jsx index 71a5425..abe7c1f 100644 --- a/src/pages/send-message-page.jsx +++ b/src/pages/send-message-page.jsx @@ -8,6 +8,7 @@ import AVATAR_SIZE from "../components/avatar/avatar-size"; import BUTTON_SIZE from "../components/button/button-size"; import { useNavigate } from "react-router"; import { PrimaryButton } from "../components/button/button"; +import TextEditor from "../components/text-editor/text-editor"; const SendContainer = styled.div` display: flex; @@ -72,6 +73,7 @@ function SendMessagePage() { const [nameError, setNameError] = useState(""); const [option, setOption] = useState("지인"); const [selectedAvatar, setSelectedAvatar] = useState(null); + const [content, setContent] = useState(""); const navigate = useNavigate(); const handleChange = (e) => { @@ -163,6 +165,13 @@ function SendMessagePage() { 내용을 입력해 주세요 +
+ setContent(value)} + /> +
폰트 선택 From b9d058a6c03d8ffd94d30803219c61c9dfecaee3 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Sat, 16 Aug 2025 16:29:12 +0900 Subject: [PATCH 121/253] =?UTF-8?q?feat=20#47=20=ED=8F=B0=ED=8A=B8=20?= =?UTF-8?q?=EC=84=A0=ED=83=9D=20=EB=93=9C=EB=A1=AD=EB=8B=A4=EC=9A=B4=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9,=20=ED=85=8D=EC=8A=A4=ED=8A=B8=20=EC=97=90?= =?UTF-8?q?=EB=94=94=ED=84=B0=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/text-editor/text-editor.tsx | 14 +++++------ src/pages/send-message-page.jsx | 27 ++++++++++++++++------ 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/components/text-editor/text-editor.tsx b/src/components/text-editor/text-editor.tsx index 2b4ee18..b6d473e 100644 --- a/src/components/text-editor/text-editor.tsx +++ b/src/components/text-editor/text-editor.tsx @@ -21,14 +21,12 @@ function TextEditor({ style, value, onChange }: TextEditorProps) { }; return ( - <> - - + ); } diff --git a/src/pages/send-message-page.jsx b/src/pages/send-message-page.jsx index abe7c1f..f698217 100644 --- a/src/pages/send-message-page.jsx +++ b/src/pages/send-message-page.jsx @@ -71,9 +71,10 @@ const CreateButton = styled(PrimaryButton)` function SendMessagePage() { const [name, setName] = useState(""); const [nameError, setNameError] = useState(""); - const [option, setOption] = useState("지인"); + const [relationOption, setRelationOption] = useState("지인"); const [selectedAvatar, setSelectedAvatar] = useState(null); - const [content, setContent] = useState(""); + const [content, setContent] = useState("I am your reach text editor."); + const [fontOption, setFontOption] = useState("Noto Sans"); const navigate = useNavigate(); const handleChange = (e) => { @@ -156,18 +157,22 @@ function SendMessagePage() { 상대와의 관계 내용을 입력해 주세요
setContent(value)} /> @@ -175,6 +180,14 @@ function SendMessagePage() { 폰트 선택 + Date: Sat, 16 Aug 2025 17:35:47 +0900 Subject: [PATCH 122/253] =?UTF-8?q?feat=20#47=20=EC=97=90=EB=94=94?= =?UTF-8?q?=ED=84=B0=20=EC=84=A0=ED=83=9D=ED=95=9C=20=20=ED=8F=B0=ED=8A=B8?= =?UTF-8?q?=20=EC=98=B5=EC=85=98=20=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 18 +++++++++++++++ src/components/text-editor/text-editor.tsx | 27 +++++++++++++++++++--- src/pages/create-post-page.jsx | 1 + src/pages/send-message-page.jsx | 10 ++++++-- 4 files changed, 51 insertions(+), 5 deletions(-) diff --git a/index.html b/index.html index 926d726..5888c7d 100644 --- a/index.html +++ b/index.html @@ -15,6 +15,24 @@ rel="stylesheet" href="https://unpkg.com/react-quill@1.3.3/dist/quill.snow.css" /> + + + + + + + + + Rolling diff --git a/src/components/text-editor/text-editor.tsx b/src/components/text-editor/text-editor.tsx index b6d473e..7a8a078 100644 --- a/src/components/text-editor/text-editor.tsx +++ b/src/components/text-editor/text-editor.tsx @@ -1,14 +1,33 @@ -import { useState } from "react"; -import ReactQuill from "react-quill-new"; +import { useEffect, useRef, useState } from "react"; +import ReactQuill, { Quill } from "react-quill-new"; import "react-quill-new/dist/quill.snow.css"; interface TextEditorProps { style?: any; value?: string; onChange: (value: string) => void; + font?: string; } -function TextEditor({ style, value, onChange }: TextEditorProps) { +const Font = Quill.import("formats/font"); +Font.whitelist = [ + "Noto Sans", + "Pretendard", + "Nanum Gothic", + "Nanum Pen Script", +]; +Quill.register(Font, true); + +function TextEditor({ style, value, onChange, font }: TextEditorProps) { + const editorRef = useRef(null); + + useEffect(() => { + if (editorRef.current) { + const editor = editorRef.current.getEditor(); + editor.root.style.fontFamily = font || "Noto Sans"; + } + }, [font]); + const modules = { toolbar: { container: [ @@ -16,12 +35,14 @@ function TextEditor({ style, value, onChange }: TextEditorProps) { [{ align: "center" }, { align: "right" }, { align: "justify" }], [{ list: "bullet" }, { list: "ordered" }], [{ background: [] }, { color: [] }], + [{ size: [] }], ], }, }; return ( setContent(value)} + font={fontOption} />
@@ -185,7 +186,12 @@ function SendMessagePage() { dropdownId="dropdown2" placeholder={fontOption} value={fontOption} - options={["Noto Sans", "Pretendard", "", ""]} + options={[ + "Noto Sans", + "Pretendard", + "Nanum Gothic", + "Nanum Pen Script", + ]} onSelect={setFontOption} />
From 0ee7179c1d4ee7eeeba3af72f3dcb9d0d284b047 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Sat, 16 Aug 2025 17:43:10 +0900 Subject: [PATCH 123/253] =?UTF-8?q?fix=20#47=20ESLint=20=EC=98=A4=EB=A5=98?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/text-editor/text-editor.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/text-editor/text-editor.tsx b/src/components/text-editor/text-editor.tsx index 7a8a078..52aeb7b 100644 --- a/src/components/text-editor/text-editor.tsx +++ b/src/components/text-editor/text-editor.tsx @@ -9,7 +9,7 @@ interface TextEditorProps { font?: string; } -const Font = Quill.import("formats/font"); +const Font: any = Quill.import("formats/font"); Font.whitelist = [ "Noto Sans", "Pretendard", @@ -25,6 +25,7 @@ function TextEditor({ style, value, onChange, font }: TextEditorProps) { if (editorRef.current) { const editor = editorRef.current.getEditor(); editor.root.style.fontFamily = font || "Noto Sans"; + editor.root.style.fontSize = "20px"; } }, [font]); From 1560d40e8819bf52a10b3367cf058c0fa1195046 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Sat, 16 Aug 2025 17:50:24 +0900 Subject: [PATCH 124/253] =?UTF-8?q?refactor=20#47=20=ED=85=8D=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=97=90=EB=94=94=ED=84=B0=20width=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9=3F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/send-message-page.jsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/pages/send-message-page.jsx b/src/pages/send-message-page.jsx index 81a826a..f48386a 100644 --- a/src/pages/send-message-page.jsx +++ b/src/pages/send-message-page.jsx @@ -59,6 +59,10 @@ const DefaultAvatar = styled.div` cursor: pointer; `; +const TextEditorWrapper = styled.div` + width: 100%; +`; + const ButtonWrapper = styled.div` padding-top: 50px; padding-bottom: 150px; @@ -167,7 +171,7 @@ function SendMessagePage() { 내용을 입력해 주세요 -
+ setContent(value)} font={fontOption} /> -
+
폰트 선택 From be7c19de8902737367a2d681cf6e3f96f8c4f735 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Sat, 16 Aug 2025 18:12:24 +0900 Subject: [PATCH 125/253] =?UTF-8?q?fix=20#47=20=EC=95=84=EB=B0=94=ED=83=80?= =?UTF-8?q?=20=EC=82=AC=EC=9D=B4=EC=A6=88=20=EC=B6=94=EA=B0=80=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/avatar/avatar-size.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/avatar/avatar-size.js b/src/components/avatar/avatar-size.js index 5de514d..7e862c6 100644 --- a/src/components/avatar/avatar-size.js +++ b/src/components/avatar/avatar-size.js @@ -1,7 +1,6 @@ const AVATAR_SIZE = Object.freeze({ large: 80, medium: 56, - medium: 40, extraSmall: 28, }); From 3c40cd9df2e5170a0599c22a108037a339d888a4 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Sat, 16 Aug 2025 18:13:32 +0900 Subject: [PATCH 126/253] =?UTF-8?q?fix=20#47=20=EC=95=84=EB=B0=94=ED=83=80?= =?UTF-8?q?=20=EC=82=AC=EC=9D=B4=EC=A6=88=20small=EC=9D=B4=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EB=90=90=EB=8A=94=EB=8D=B0...=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/avatar/avatar-size.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/avatar/avatar-size.js b/src/components/avatar/avatar-size.js index 7e862c6..9bb1492 100644 --- a/src/components/avatar/avatar-size.js +++ b/src/components/avatar/avatar-size.js @@ -1,6 +1,7 @@ const AVATAR_SIZE = Object.freeze({ large: 80, medium: 56, + small: 40, extraSmall: 28, }); From d1c4c282b93cfedd80bcff464ac0cee7796be312 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Sat, 16 Aug 2025 18:19:49 +0900 Subject: [PATCH 127/253] =?UTF-8?q?fix=20#47=20=EC=95=84=EB=B0=94=ED=83=80?= =?UTF-8?q?=20=EC=82=AC=EC=9D=B4=EC=A6=88=20=EC=98=A4=EB=A5=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95..?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/avatar/avatar.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/avatar/avatar.jsx b/src/components/avatar/avatar.jsx index efbd9d5..2cb3ed4 100644 --- a/src/components/avatar/avatar.jsx +++ b/src/components/avatar/avatar.jsx @@ -6,7 +6,7 @@ import AVATAR_SIZE from "./avatar-size"; const borderWidth = { [AVATAR_SIZE.large]: 0, [AVATAR_SIZE.medium]: 1, - [AVATAR_SIZE.medium]: 1, + [AVATAR_SIZE.small]: 1.3, [AVATAR_SIZE.extraSmall]: 1.5, }; From 9705b837d51b9535c1ad28fde428e815b4c735c9 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Sun, 17 Aug 2025 21:22:52 +0900 Subject: [PATCH 128/253] =?UTF-8?q?=EC=95=84=EB=B0=94=ED=83=80=20=EC=82=AC?= =?UTF-8?q?=EC=9D=B4=EC=A6=88=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/avatar/avatar.jsx | 2 +- src/pages/send-message-page.jsx | 13 +++++-------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/components/avatar/avatar.jsx b/src/components/avatar/avatar.jsx index 2cb3ed4..d5146e8 100644 --- a/src/components/avatar/avatar.jsx +++ b/src/components/avatar/avatar.jsx @@ -6,7 +6,7 @@ import AVATAR_SIZE from "./avatar-size"; const borderWidth = { [AVATAR_SIZE.large]: 0, [AVATAR_SIZE.medium]: 1, - [AVATAR_SIZE.small]: 1.3, + [AVATAR_SIZE.small]: 1, [AVATAR_SIZE.extraSmall]: 1.5, }; diff --git a/src/pages/send-message-page.jsx b/src/pages/send-message-page.jsx index f48386a..1c5f84e 100644 --- a/src/pages/send-message-page.jsx +++ b/src/pages/send-message-page.jsx @@ -59,10 +59,6 @@ const DefaultAvatar = styled.div` cursor: pointer; `; -const TextEditorWrapper = styled.div` - width: 100%; -`; - const ButtonWrapper = styled.div` padding-top: 50px; padding-bottom: 150px; @@ -162,7 +158,7 @@ function SendMessagePage() { 상대와의 관계 내용을 입력해 주세요 - +
setContent(value)} font={fontOption} /> - +
폰트 선택 Date: Sun, 17 Aug 2025 21:25:07 +0900 Subject: [PATCH 129/253] =?UTF-8?q?=EC=95=84=EB=B0=94=ED=83=80=20=EC=82=AC?= =?UTF-8?q?=EC=9D=B4=EC=A6=88=20test-page=20=EB=82=B4=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/test-page.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index a505fac..f691c69 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -257,11 +257,11 @@ function TestPage() {
- + - + Date: Mon, 18 Aug 2025 01:37:51 +0900 Subject: [PATCH 130/253] =?UTF-8?q?[#43]=20pr=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EC=A0=81=EC=9A=A9,=20=EC=B9=B4=EB=93=9C?= =?UTF-8?q?=20=EB=B0=B0=EA=B2=BD=20=EB=8F=84=ED=98=95=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 삼한 연산자 변경, transient prop사용, styled-component를 최대한 사용하도록 변경, strong태그 변경 --- src/components/button/arrow-button.jsx | 2 +- .../components/rolling-paper-list.jsx | 192 +- src/pages/rolling-paper-list-page.jsx | 2 +- src/pages/test_recipients_data.json | 4951 +++-------------- 4 files changed, 1008 insertions(+), 4139 deletions(-) diff --git a/src/components/button/arrow-button.jsx b/src/components/button/arrow-button.jsx index 12b0919..6adcf64 100644 --- a/src/components/button/arrow-button.jsx +++ b/src/components/button/arrow-button.jsx @@ -10,7 +10,7 @@ const arrowImg = { }; const StyledArrowButton = styled.button` - background: none; + background: #ffffff; border: 1px solid ${Colors.gray(300)}; width: 40px; height: 40px; diff --git a/src/features/rolling-paper/components/rolling-paper-list.jsx b/src/features/rolling-paper/components/rolling-paper-list.jsx index 37b58c1..9c7e009 100644 --- a/src/features/rolling-paper/components/rolling-paper-list.jsx +++ b/src/features/rolling-paper/components/rolling-paper-list.jsx @@ -13,10 +13,10 @@ import React, { useEffect, useState } from "react"; import styled from "styled-components"; const backgroundColors = { - beige: "#FFD382", - purple: "#DCB9FF", - green: "#9BE282", - blue: "#9DDDFF", + beige: "#FFE2AD", + purple: "#ECD9FF", + green: "#D0F5C3", + blue: "#B1E4FF", }; const CardContainer = styled.div` @@ -24,66 +24,139 @@ const CardContainer = styled.div` grid-template-columns: 275px 275px 275px 275px; gap: 20px; width: fit-content; + font-family: Pretendard; position: relative; overflow: visible; `; -const CardItem = styled.div.withConfig({ - shouldForwardProp: (prop) => prop !== "backgroundColor", -})` +const CardItem = styled.div` width: 275px; height: 260px; border-radius: 16px; text-align: left; padding: 30px 24px 20px 24px; - box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.1); + border: 1px solid rgba(0, 0, 0, 0.1); + box-shadow: 0px 2px 12px 0px rgba(0, 0, 0, 0.08); display: grid; grid-template-rows: 1fr 1fr auto; - background-color: ${(props) => - backgroundColors[props.backgroundColor] || "white"}; + background: ${(props) => + props.$backgroundImageURL + ? `linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4)), url(${props.$backgroundImageURL}) center/cover no-repeat` + : backgroundColors[props.$backgroundColor] || "white"}; - img { - height: 28px; - width: 28px; - border-radius: 50%; - border: 1px solid #ffffff; - - margin-left: -12px; - &:first-child { - margin-left: 0; - } + position: relative; + overflow: hidden; + + /* 배경 도형 */ + &::before { + content: ""; + position: absolute; + z-index: 0; + ${(props) => { + if (!props.$backgroundImageURL) { + if ( + props.$backgroundColor === "purple" || + props.$backgroundColor === "green" + ) { + return ` + width: 336px; + height: 169px; + background-color: ${ + props.$backgroundColor === "purple" + ? "rgba(220,185,255,0.4)" + : "rgba(155, 226, 130, 0.3)" + }; + border-radius: 90.5px; + top: 124px; + left: 133px; + `; + } else if (props.$backgroundColor === "beige") { + return ` + width: 332px; + height: 318px; + border-radius: 51px; + background-color: #ffd382; + top: 124px; + left: 154px; + `; + } else if (props.$backgroundColor === "blue") { + const svgString = ``; + const encodedSvg = encodeURIComponent(svgString); + + return ` + width: 170px; + height: 200px; + background-image: url("data:image/svg+xml,${encodedSvg}"); + background-repeat: no-repeat; + background-position: center; + background-size: contain; + top: 108px; + left: 113px; + `; + } + } + return ""; + }} } - div.message-images { - display: flex; + & > * { + position: relative; + z-index: 1; } +`; - div.over-profile { - height: 28px; - width: 28px; - background-color: #ffffff; - border-radius: 50%; +const CardTitle = styled.h2` + margin: 0; + font-size: 24px; + font-weight: 700; + color: ${(props) => props.$fontColor || "black"}; +`; - margin-left: -12px; +const ProfileContainer = styled.div` + display: flex; +`; - display: flex; - justify-content: center; - align-items: center; - font-size: 12px; - } +const CardProfile = styled.img` + height: 28px; + width: 28px; + border-radius: 50%; + border: 1px solid #ffffff; - h2 { - margin: 0; + margin-left: -12px; + &:first-child { + margin-left: 0; } +`; - div.emoji-div { - border-top: 1px solid red; +const OverProfile = styled.div` + height: 28px; + width: 28px; + background-color: #ffffff; + border-radius: 50%; + + margin-left: -12px; + + display: flex; + justify-content: center; + align-items: center; + font-size: 12px; +`; + +const MessageCountText = styled.span` + color: ${(props) => props.$fontColor || "black"}; + em { + font-weight: 700; + font-style: normal; } `; +const CardEmoji = styled.div` + border-top: 1px solid rgba(0, 0, 0, 0.1); +`; + const NextButtonWrapper = styled.div` position: absolute; right: -20px; @@ -104,39 +177,48 @@ function RollingPaperList({ cardData, totalPages, currentPage, onTurnCards }) { return ( {cardData.map((item) => ( - -

To. {item.name}

-
+ + + To. {item.name} + + {item.recentMessages.slice(0, 3).map((messageItem, index) => ( - {`profile-${index}`} ))} - {item.messageCount > 3 ? ( -
+ {item.messageCount > 3 && ( + +{item.messageCount - 3} -
- ) : null} -
- - {item.messageCount}명이 작성했어요! - -
test
+ + )} + + + {item.messageCount}명이 작성했어요! + + {item.topReactions.map((emoji) => emoji.emoji)}
))} - {currentPage > 0 ? ( + {currentPage > 0 && ( onTurnCards("preview")}> - ) : null} - {currentPage < totalPages - 1 ? ( + )} + {currentPage < totalPages - 1 && ( onTurnCards("next")}> - ) : null} + )}
); } diff --git a/src/pages/rolling-paper-list-page.jsx b/src/pages/rolling-paper-list-page.jsx index 3b6e839..5fe8958 100644 --- a/src/pages/rolling-paper-list-page.jsx +++ b/src/pages/rolling-paper-list-page.jsx @@ -9,7 +9,7 @@ import BUTTON_SIZE from "../components/button/button-size"; import ToggleButton from "../components/button/toggle-button"; import React, { useEffect, useState } from "react"; -import axiosInstance from "../api/axios-instance"; +// import axiosInstance from "../api/axios-instance"; import testDataFile from "./test_recipients_data.json"; import styled from "styled-components"; diff --git a/src/pages/test_recipients_data.json b/src/pages/test_recipients_data.json index 3d307a2..a95aa23 100644 --- a/src/pages/test_recipients_data.json +++ b/src/pages/test_recipients_data.json @@ -1,11 +1,11 @@ [ { "id": 7024, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "beige", "backgroundImageURL": null, "createdAt": "2023-10-22T19:15:11Z", - "messageCount": 5, + "messageCount": 1, "recentMessages": [ { "id": 90163, @@ -16,54 +16,17 @@ "content": "김하은님의 메세지 내용 50", "font": "Roboto", "createdAt": "2023-08-18T21:20:29Z" - }, - { - "id": 90164, - "recipientId": 7024, - "sender": "강동원", - "profileImageURL": "https://picsum.photos/id/142/200/200", - "relationship": "친구", - "content": "강동원님의 메세지 내용 50", - "font": "Roboto", - "createdAt": "2023-08-19T21:20:29Z" - }, - { - "id": 90165, - "recipientId": 7024, - "sender": "고수", - "profileImageURL": "https://picsum.photos/id/142/200/200", - "relationship": "친구", - "content": "고수님의 메세지 내용 50", - "font": "Roboto", - "createdAt": "2023-08-20T21:20:29Z" } ], "reactionCount": 77, "topReactions": [ { - "id": 78000, - "emoji": "😁", - "count": 6 - }, - { - "id": 70479, "emoji": "🥹", - "count": 15 + "count": 159 }, { - "id": 32001, "emoji": "😁", - "count": 5 - }, - { - "id": 25196, - "emoji": "🥹", - "count": 18 - }, - { - "id": 15685, - "emoji": "🥹", - "count": 2 + "count": 923 } ] }, @@ -79,7 +42,7 @@ "id": 42811, "recipientId": 71200, "sender": "현빈", - "profileImageURL": "https://picsum.photos/id/435/200/200", + "profileImageURL": "https://picsum.photos/id/51/200/200", "relationship": "가족", "content": "현빈님의 메세지 내용 25", "font": "Roboto", @@ -109,34 +72,8 @@ "reactionCount": 66, "topReactions": [ { - "id": 84284, - "emoji": "🥹", - "count": 4 - }, - { - "id": 67905, - "emoji": "😁", - "count": 2 - }, - { - "id": 19092, - "emoji": "👍", - "count": 4 - }, - { - "id": 62998, "emoji": "😁", - "count": 5 - }, - { - "id": 49907, - "emoji": "🥹", - "count": 10 - }, - { - "id": 306, - "emoji": "🥹", - "count": 3 + "count": 962 } ] }, @@ -151,10 +88,10 @@ { "id": 30238, "recipientId": 43558, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/340/200/200", "relationship": "가족", - "content": "Suwon Kim님의 메세지 내용 32", + "content": "Sowon Kim님의 메세지 내용 32", "font": "Nanum Gothic", "createdAt": "2023-06-17T00:31:29Z" }, @@ -182,34 +119,16 @@ "reactionCount": 13, "topReactions": [ { - "id": 84326, "emoji": "😀", - "count": 13 - }, - { - "id": 29537, - "emoji": "🥹", - "count": 2 + "count": 46 }, { - "id": 78412, - "emoji": "😁", - "count": 4 - }, - { - "id": 91457, "emoji": "🎉", - "count": 6 - }, - { - "id": 50902, - "emoji": "🥹", - "count": 7 + "count": 585 }, { - "id": 5434, - "emoji": "🥹", - "count": 14 + "emoji": "😁", + "count": 311 } ] }, @@ -245,25 +164,14 @@ "reactionCount": 84, "topReactions": [ { - "id": 605, - "emoji": "🥹", - "count": 14 - }, - { - "id": 90894, "emoji": "🥹", - "count": 3 - }, - { - "id": 26499, - "emoji": "🥹", - "count": 5 + "count": 570 } ] }, { "id": 18499, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "beige", "backgroundImageURL": "https://picsum.photos/seed/18499/600/400", "createdAt": "2023-06-03T04:15:47Z", @@ -272,10 +180,10 @@ { "id": 48979, "recipientId": 18499, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/11/200/200", "relationship": "지인", - "content": "Suwon Kim님의 메세지 내용 77", + "content": "Sowon Kim님의 메세지 내용 77", "font": "Nanum Gothic", "createdAt": "2023-08-25T00:15:25Z" }, @@ -292,10 +200,10 @@ { "id": 35753, "recipientId": 18499, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/173/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 67", + "content": "Sowon Kim님의 메세지 내용 67", "font": "Nanum Gothic", "createdAt": "2023-07-23T23:14:30Z" } @@ -303,34 +211,16 @@ "reactionCount": 61, "topReactions": [ { - "id": 84545, - "emoji": "👍", - "count": 2 - }, - { - "id": 91678, "emoji": "❤️", - "count": 10 + "count": 847 }, { - "id": 13771, "emoji": "😀", - "count": 20 + "count": 141 }, { - "id": 45654, - "emoji": "❤️", - "count": 2 - }, - { - "id": 97554, - "emoji": "🥹", - "count": 6 - }, - { - "id": 78344, "emoji": "👍", - "count": 1 + "count": 396 } ] }, @@ -376,24 +266,12 @@ "reactionCount": 14, "topReactions": [ { - "id": 5423, - "emoji": "😁", - "count": 19 - }, - { - "id": 694, - "emoji": "😀", - "count": 2 - }, - { - "id": 2845, "emoji": "🥹", - "count": 13 + "count": 800 }, { - "id": 90938, - "emoji": "🥹", - "count": 19 + "emoji": "😁", + "count": 262 } ] }, @@ -439,35 +317,22 @@ "reactionCount": 87, "topReactions": [ { - "id": 71912, "emoji": "😀", - "count": 1 + "count": 846 }, { - "id": 53543, - "emoji": "❤️", - "count": 12 - }, - { - "id": 90369, - "emoji": "😀", - "count": 11 - }, - { - "id": 65448, "emoji": "😁", - "count": 17 + "count": 901 }, { - "id": 96672, - "emoji": "👍", - "count": 15 + "emoji": "❤️", + "count": 921 } ] }, { "id": 13425, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "beige", "backgroundImageURL": "https://picsum.photos/seed/13425/600/400", "createdAt": "2023-07-06T20:30:52Z", @@ -487,24 +352,12 @@ "reactionCount": 33, "topReactions": [ { - "id": 78114, - "emoji": "😁", - "count": 5 - }, - { - "id": 46240, - "emoji": "👍", - "count": 10 - }, - { - "id": 3995, "emoji": "❤️", - "count": 7 + "count": 865 }, { - "id": 47582, - "emoji": "👍", - "count": 11 + "emoji": "😁", + "count": 198 } ] }, @@ -550,9 +403,8 @@ "reactionCount": 61, "topReactions": [ { - "id": 58872, "emoji": "🥹", - "count": 13 + "count": 403 } ] }, @@ -567,10 +419,10 @@ { "id": 34424, "recipientId": 97436, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/141/200/200", "relationship": "지인", - "content": "Suwon Kim님의 메세지 내용 6", + "content": "Sowon Kim님의 메세지 내용 6", "font": "Nanum Gothic", "createdAt": "2023-06-01T12:35:35Z" }, @@ -598,25 +450,22 @@ "reactionCount": 61, "topReactions": [ { - "id": 34505, "emoji": "😀", - "count": 2 + "count": 264 }, { - "id": 97779, "emoji": "😁", - "count": 14 + "count": 580 }, { - "id": 64296, "emoji": "🥹", - "count": 17 + "count": 8 } ] }, { "id": 22932, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "blue", "backgroundImageURL": "https://picsum.photos/seed/22932/600/400", "createdAt": "2023-12-21T05:29:02Z", @@ -636,9 +485,8 @@ "reactionCount": 54, "topReactions": [ { - "id": 80894, "emoji": "👍", - "count": 6 + "count": 983 } ] }, @@ -684,14 +532,8 @@ "reactionCount": 67, "topReactions": [ { - "id": 20683, "emoji": "😁", - "count": 7 - }, - { - "id": 55812, - "emoji": "❤️", - "count": 8 + "count": 882 } ] }, @@ -737,14 +579,8 @@ "reactionCount": 29, "topReactions": [ { - "id": 60975, - "emoji": "🎉", - "count": 16 - }, - { - "id": 94228, "emoji": "🎉", - "count": 12 + "count": 137 } ] }, @@ -779,10 +615,10 @@ { "id": 88963, "recipientId": 2194, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/317/200/200", "relationship": "가족", - "content": "Suwon Kim님의 메세지 내용 81", + "content": "Sowon Kim님의 메세지 내용 81", "font": "Nanum Gothic", "createdAt": "2023-03-12T08:38:10Z" } @@ -790,34 +626,12 @@ "reactionCount": 32, "topReactions": [ { - "id": 60382, - "emoji": "🎉", - "count": 14 - }, - { - "id": 35188, - "emoji": "😁", - "count": 16 - }, - { - "id": 36631, - "emoji": "😁", - "count": 7 - }, - { - "id": 42371, "emoji": "❤️", - "count": 9 - }, - { - "id": 49401, - "emoji": "🥹", - "count": 14 + "count": 58 }, { - "id": 62636, - "emoji": "😀", - "count": 4 + "emoji": "😁", + "count": 334 } ] }, @@ -863,29 +677,8 @@ "reactionCount": 3, "topReactions": [ { - "id": 75158, - "emoji": "😁", - "count": 16 - }, - { - "id": 91157, - "emoji": "👍", - "count": 1 - }, - { - "id": 62992, - "emoji": "👍", - "count": 5 - }, - { - "id": 36793, "emoji": "😀", - "count": 11 - }, - { - "id": 47139, - "emoji": "👍", - "count": 18 + "count": 165 } ] }, @@ -931,9 +724,8 @@ "reactionCount": 18, "topReactions": [ { - "id": 88345, "emoji": "😀", - "count": 17 + "count": 19 } ] }, @@ -959,40 +751,14 @@ "reactionCount": 86, "topReactions": [ { - "id": 61646, - "emoji": "😁", - "count": 6 - }, - { - "id": 36266, - "emoji": "🎉", - "count": 11 - }, - { - "id": 19739, - "emoji": "🎉", - "count": 19 - }, - { - "id": 49081, - "emoji": "🎉", - "count": 7 - }, - { - "id": 60907, - "emoji": "👍", - "count": 11 - }, - { - "id": 82566, "emoji": "❤️", - "count": 14 + "count": 680 } ] }, { "id": 45901, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "purple", "backgroundImageURL": null, "createdAt": "2023-06-14T15:34:31Z", @@ -1032,29 +798,12 @@ "reactionCount": 15, "topReactions": [ { - "id": 32010, - "emoji": "❤️", - "count": 20 - }, - { - "id": 25614, "emoji": "❤️", - "count": 18 + "count": 648 }, { - "id": 44236, "emoji": "😁", - "count": 5 - }, - { - "id": 26955, - "emoji": "❤️", - "count": 12 - }, - { - "id": 68249, - "emoji": "😁", - "count": 9 + "count": 457 } ] }, @@ -1080,24 +829,16 @@ "reactionCount": 17, "topReactions": [ { - "id": 38691, - "emoji": "🎉", - "count": 14 + "emoji": "😀", + "count": 525 }, { - "id": 74561, - "emoji": "😁", - "count": 16 + "emoji": "🎉", + "count": 408 }, { - "id": 67482, "emoji": "🥹", - "count": 11 - }, - { - "id": 77948, - "emoji": "😀", - "count": 5 + "count": 160 } ] }, @@ -1133,24 +874,16 @@ "reactionCount": 36, "topReactions": [ { - "id": 41246, "emoji": "😀", - "count": 3 + "count": 472 }, { - "id": 91855, "emoji": "❤️", - "count": 17 + "count": 938 }, { - "id": 88660, "emoji": "🎉", - "count": 1 - }, - { - "id": 98907, - "emoji": "❤️", - "count": 15 + "count": 169 } ] }, @@ -1165,10 +898,10 @@ { "id": 99518, "recipientId": 84532, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/2/200/200", "relationship": "가족", - "content": "Suwon Kim님의 메세지 내용 83", + "content": "Sowon Kim님의 메세지 내용 83", "font": "Nanum Gothic", "createdAt": "2023-07-12T22:08:05Z" }, @@ -1196,19 +929,8 @@ "reactionCount": 27, "topReactions": [ { - "id": 24529, "emoji": "🥹", - "count": 15 - }, - { - "id": 72262, - "emoji": "😀", - "count": 20 - }, - { - "id": 85359, - "emoji": "🎉", - "count": 16 + "count": 55 } ] }, @@ -1243,10 +965,10 @@ { "id": 72173, "recipientId": 85839, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/137/200/200", "relationship": "동료", - "content": "Suwon Kim님의 메세지 내용 84", + "content": "Sowon Kim님의 메세지 내용 84", "font": "Pretendard", "createdAt": "2023-04-01T12:40:19Z" } @@ -1254,34 +976,8 @@ "reactionCount": 77, "topReactions": [ { - "id": 89993, - "emoji": "❤️", - "count": 5 - }, - { - "id": 92268, - "emoji": "👍", - "count": 18 - }, - { - "id": 77791, - "emoji": "🎉", - "count": 15 - }, - { - "id": 34959, - "emoji": "🥹", - "count": 11 - }, - { - "id": 7685, "emoji": "😀", - "count": 10 - }, - { - "id": 34844, - "emoji": "👍", - "count": 14 + "count": 634 } ] }, @@ -1327,14 +1023,8 @@ "reactionCount": 18, "topReactions": [ { - "id": 39441, - "emoji": "👍", - "count": 16 - }, - { - "id": 89350, "emoji": "🥹", - "count": 1 + "count": 398 } ] }, @@ -1359,10 +1049,10 @@ { "id": 20559, "recipientId": 76172, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/315/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 53", + "content": "Sowon Kim님의 메세지 내용 53", "font": "Roboto", "createdAt": "2023-07-06T05:06:42Z" }, @@ -1380,9 +1070,8 @@ "reactionCount": 55, "topReactions": [ { - "id": 1687, "emoji": "🥹", - "count": 15 + "count": 309 } ] }, @@ -1428,29 +1117,16 @@ "reactionCount": 11, "topReactions": [ { - "id": 3029, - "emoji": "👍", - "count": 13 + "emoji": "❤️", + "count": 698 }, { - "id": 76170, "emoji": "👍", - "count": 15 - }, - { - "id": 96379, - "emoji": "😀", - "count": 13 + "count": 583 }, { - "id": 89555, "emoji": "😀", - "count": 16 - }, - { - "id": 39796, - "emoji": "❤️", - "count": 17 + "count": 349 } ] }, @@ -1475,10 +1151,10 @@ { "id": 26243, "recipientId": 525, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/470/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 36", + "content": "Sowon Kim님의 메세지 내용 36", "font": "Noto Sans", "createdAt": "2024-02-01T22:09:11Z" }, @@ -1496,14 +1172,12 @@ "reactionCount": 40, "topReactions": [ { - "id": 92021, "emoji": "❤️", - "count": 17 + "count": 778 }, { - "id": 63448, "emoji": "😀", - "count": 11 + "count": 821 } ] }, @@ -1529,9 +1203,8 @@ "reactionCount": 2, "topReactions": [ { - "id": 6976, "emoji": "❤️", - "count": 1 + "count": 735 } ] }, @@ -1577,9 +1250,8 @@ "reactionCount": 28, "topReactions": [ { - "id": 38379, "emoji": "🥹", - "count": 3 + "count": 407 } ] }, @@ -1625,9 +1297,8 @@ "reactionCount": 54, "topReactions": [ { - "id": 63000, "emoji": "🎉", - "count": 12 + "count": 91 } ] }, @@ -1642,10 +1313,10 @@ { "id": 8442, "recipientId": 76854, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/391/200/200", "relationship": "지인", - "content": "Suwon Kim님의 메세지 내용 6", + "content": "Sowon Kim님의 메세지 내용 6", "font": "Pretendard", "createdAt": "2023-12-21T09:27:19Z" }, @@ -1673,9 +1344,8 @@ "reactionCount": 86, "topReactions": [ { - "id": 27143, "emoji": "🥹", - "count": 8 + "count": 334 } ] }, @@ -1690,10 +1360,10 @@ { "id": 3111, "recipientId": 50919, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/384/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 80", + "content": "Sowon Kim님의 메세지 내용 80", "font": "Pretendard", "createdAt": "2023-08-12T11:51:00Z" }, @@ -1721,24 +1391,12 @@ "reactionCount": 76, "topReactions": [ { - "id": 89101, - "emoji": "👍", - "count": 12 - }, - { - "id": 60242, - "emoji": "😁", - "count": 17 - }, - { - "id": 97519, - "emoji": "🎉", - "count": 11 + "emoji": "❤️", + "count": 902 }, { - "id": 65104, - "emoji": "❤️", - "count": 7 + "emoji": "👍", + "count": 427 } ] }, @@ -1784,19 +1442,12 @@ "reactionCount": 90, "topReactions": [ { - "id": 95691, - "emoji": "🎉", - "count": 3 - }, - { - "id": 89483, "emoji": "😁", - "count": 2 + "count": 357 }, { - "id": 56468, "emoji": "🎉", - "count": 13 + "count": 480 } ] }, @@ -1822,14 +1473,8 @@ "reactionCount": 88, "topReactions": [ { - "id": 72401, - "emoji": "❤️", - "count": 3 - }, - { - "id": 5640, "emoji": "❤️", - "count": 5 + "count": 148 } ] }, @@ -1875,29 +1520,12 @@ "reactionCount": 17, "topReactions": [ { - "id": 91559, - "emoji": "🥹", - "count": 3 - }, - { - "id": 56771, "emoji": "🎉", - "count": 3 - }, - { - "id": 15952, - "emoji": "❤️", - "count": 18 + "count": 493 }, { - "id": 90450, - "emoji": "👍", - "count": 15 - }, - { - "id": 52341, "emoji": "😀", - "count": 14 + "count": 464 } ] }, @@ -1943,35 +1571,22 @@ "reactionCount": 78, "topReactions": [ { - "id": 65046, - "emoji": "🎉", - "count": 12 - }, - { - "id": 94282, "emoji": "😀", - "count": 15 - }, - { - "id": 87051, - "emoji": "🎉", - "count": 12 + "count": 537 }, { - "id": 76472, "emoji": "😁", - "count": 12 + "count": 154 }, { - "id": 43401, "emoji": "🥹", - "count": 1 + "count": 801 } ] }, { "id": 5465, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "beige", "backgroundImageURL": null, "createdAt": "2023-01-10T18:10:25Z", @@ -2011,34 +1626,12 @@ "reactionCount": 25, "topReactions": [ { - "id": 59656, - "emoji": "😁", - "count": 15 - }, - { - "id": 91642, "emoji": "👍", - "count": 6 - }, - { - "id": 63844, - "emoji": "🎉", - "count": 9 - }, - { - "id": 38254, - "emoji": "🎉", - "count": 13 - }, - { - "id": 80222, - "emoji": "🎉", - "count": 3 + "count": 490 }, { - "id": 76177, - "emoji": "🎉", - "count": 10 + "emoji": "😁", + "count": 686 } ] }, @@ -2064,24 +1657,12 @@ "reactionCount": 60, "topReactions": [ { - "id": 21526, - "emoji": "❤️", - "count": 9 - }, - { - "id": 89624, "emoji": "😁", - "count": 9 - }, - { - "id": 92331, - "emoji": "🎉", - "count": 17 + "count": 127 }, { - "id": 56922, - "emoji": "🎉", - "count": 12 + "emoji": "❤️", + "count": 193 } ] }, @@ -2127,34 +1708,16 @@ "reactionCount": 3, "topReactions": [ { - "id": 75083, - "emoji": "🎉", - "count": 3 - }, - { - "id": 99458, "emoji": "👍", - "count": 8 - }, - { - "id": 58435, - "emoji": "🥹", - "count": 9 + "count": 366 }, { - "id": 35549, - "emoji": "😀", - "count": 12 - }, - { - "id": 89316, - "emoji": "🥹", - "count": 12 + "emoji": "🎉", + "count": 391 }, { - "id": 92464, "emoji": "😀", - "count": 12 + "count": 61 } ] }, @@ -2200,19 +1763,16 @@ "reactionCount": 50, "topReactions": [ { - "id": 16722, "emoji": "🎉", - "count": 11 + "count": 503 }, { - "id": 59575, - "emoji": "👍", - "count": 9 + "emoji": "😁", + "count": 761 }, { - "id": 92248, - "emoji": "😁", - "count": 2 + "emoji": "👍", + "count": 572 } ] }, @@ -2258,34 +1818,16 @@ "reactionCount": 19, "topReactions": [ { - "id": 40145, - "emoji": "😁", - "count": 19 - }, - { - "id": 85434, - "emoji": "❤️", - "count": 4 - }, - { - "id": 12101, - "emoji": "😁", - "count": 14 + "emoji": "😀", + "count": 894 }, { - "id": 81287, "emoji": "😁", - "count": 16 + "count": 106 }, { - "id": 4370, "emoji": "❤️", - "count": 6 - }, - { - "id": 37361, - "emoji": "😀", - "count": 3 + "count": 675 } ] }, @@ -2331,14 +1873,12 @@ "reactionCount": 89, "topReactions": [ { - "id": 68890, - "emoji": "😁", - "count": 8 + "emoji": "🥹", + "count": 714 }, { - "id": 36484, - "emoji": "🥹", - "count": 11 + "emoji": "😁", + "count": 930 } ] }, @@ -2353,10 +1893,10 @@ { "id": 66552, "recipientId": 90385, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/498/200/200", "relationship": "동료", - "content": "Suwon Kim님의 메세지 내용 36", + "content": "Sowon Kim님의 메세지 내용 36", "font": "Noto Sans", "createdAt": "2023-10-17T11:54:41Z" } @@ -2364,14 +1904,8 @@ "reactionCount": 73, "topReactions": [ { - "id": 88512, "emoji": "❤️", - "count": 4 - }, - { - "id": 33951, - "emoji": "🥹", - "count": 10 + "count": 423 } ] }, @@ -2407,9 +1941,8 @@ "reactionCount": 87, "topReactions": [ { - "id": 7092, "emoji": "🥹", - "count": 20 + "count": 422 } ] }, @@ -2455,34 +1988,8 @@ "reactionCount": 48, "topReactions": [ { - "id": 47934, - "emoji": "❤️", - "count": 7 - }, - { - "id": 38552, "emoji": "🥹", - "count": 12 - }, - { - "id": 97573, - "emoji": "❤️", - "count": 17 - }, - { - "id": 90066, - "emoji": "👍", - "count": 17 - }, - { - "id": 75594, - "emoji": "👍", - "count": 5 - }, - { - "id": 80625, - "emoji": "🥹", - "count": 10 + "count": 800 } ] }, @@ -2497,10 +2004,10 @@ { "id": 59673, "recipientId": 39122, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/467/200/200", "relationship": "동료", - "content": "Suwon Kim님의 메세지 내용 15", + "content": "Sowon Kim님의 메세지 내용 15", "font": "Nanum Gothic", "createdAt": "2023-03-20T07:58:11Z" }, @@ -2528,14 +2035,12 @@ "reactionCount": 54, "topReactions": [ { - "id": 21238, "emoji": "❤️", - "count": 7 + "count": 529 }, { - "id": 36319, "emoji": "🥹", - "count": 8 + "count": 458 } ] }, @@ -2570,10 +2075,10 @@ { "id": 87956, "recipientId": 36279, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/362/200/200", "relationship": "가족", - "content": "Suwon Kim님의 메세지 내용 45", + "content": "Sowon Kim님의 메세지 내용 45", "font": "Pretendard", "createdAt": "2023-01-10T01:43:19Z" } @@ -2581,19 +2086,8 @@ "reactionCount": 58, "topReactions": [ { - "id": 37731, - "emoji": "🎉", - "count": 19 - }, - { - "id": 95128, "emoji": "🥹", - "count": 12 - }, - { - "id": 65326, - "emoji": "🎉", - "count": 9 + "count": 191 } ] }, @@ -2639,29 +2133,12 @@ "reactionCount": 11, "topReactions": [ { - "id": 60036, "emoji": "🎉", - "count": 20 - }, - { - "id": 66223, - "emoji": "😁", - "count": 5 - }, - { - "id": 57559, - "emoji": "❤️", - "count": 14 + "count": 198 }, { - "id": 85462, "emoji": "❤️", - "count": 18 - }, - { - "id": 78366, - "emoji": "❤️", - "count": 10 + "count": 31 } ] }, @@ -2707,14 +2184,12 @@ "reactionCount": 1, "topReactions": [ { - "id": 85067, - "emoji": "❤️", - "count": 19 + "emoji": "🎉", + "count": 230 }, { - "id": 23463, - "emoji": "🎉", - "count": 14 + "emoji": "❤️", + "count": 31 } ] }, @@ -2760,24 +2235,16 @@ "reactionCount": 13, "topReactions": [ { - "id": 47472, "emoji": "🥹", - "count": 1 + "count": 836 }, { - "id": 73490, "emoji": "👍", - "count": 7 + "count": 817 }, { - "id": 9397, "emoji": "😁", - "count": 18 - }, - { - "id": 62463, - "emoji": "😀", - "count": 8 + "count": 375 } ] }, @@ -2802,10 +2269,10 @@ { "id": 60985, "recipientId": 2640, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/440/200/200", "relationship": "동료", - "content": "Suwon Kim님의 메세지 내용 52", + "content": "Sowon Kim님의 메세지 내용 52", "font": "Pretendard", "createdAt": "2023-05-11T23:03:58Z" }, @@ -2823,9 +2290,8 @@ "reactionCount": 39, "topReactions": [ { - "id": 68723, "emoji": "😁", - "count": 10 + "count": 706 } ] }, @@ -2861,24 +2327,16 @@ "reactionCount": 59, "topReactions": [ { - "id": 67796, - "emoji": "👍", - "count": 17 + "emoji": "😁", + "count": 573 }, { - "id": 73312, "emoji": "🎉", - "count": 14 + "count": 172 }, { - "id": 69831, - "emoji": "❤️", - "count": 6 - }, - { - "id": 68250, - "emoji": "😁", - "count": 15 + "emoji": "👍", + "count": 833 } ] }, @@ -2924,14 +2382,8 @@ "reactionCount": 3, "topReactions": [ { - "id": 61747, "emoji": "😁", - "count": 6 - }, - { - "id": 25034, - "emoji": "🥹", - "count": 7 + "count": 599 } ] }, @@ -2977,24 +2429,16 @@ "reactionCount": 64, "topReactions": [ { - "id": 3352, - "emoji": "👍", - "count": 10 - }, - { - "id": 39601, - "emoji": "😀", - "count": 10 + "emoji": "🎉", + "count": 385 }, { - "id": 11421, - "emoji": "🎉", - "count": 5 + "emoji": "👍", + "count": 512 }, { - "id": 35027, - "emoji": "🎉", - "count": 10 + "emoji": "😀", + "count": 705 } ] }, @@ -3020,14 +2464,8 @@ "reactionCount": 43, "topReactions": [ { - "id": 8574, "emoji": "🎉", - "count": 7 - }, - { - "id": 64170, - "emoji": "❤️", - "count": 8 + "count": 764 } ] }, @@ -3053,7 +2491,7 @@ "id": 20798, "recipientId": 28312, "sender": "한지민", - "profileImageURL": "https://picsum.photos/id/435/200/200", + "profileImageURL": "https://picsum.photos/id/51/200/200", "relationship": "가족", "content": "한지민님의 메세지 내용 83", "font": "Noto Sans", @@ -3073,19 +2511,8 @@ "reactionCount": 31, "topReactions": [ { - "id": 9532, - "emoji": "🎉", - "count": 15 - }, - { - "id": 71554, - "emoji": "🎉", - "count": 3 - }, - { - "id": 39488, "emoji": "👍", - "count": 14 + "count": 846 } ] }, @@ -3131,34 +2558,12 @@ "reactionCount": 33, "topReactions": [ { - "id": 52748, - "emoji": "👍", - "count": 10 - }, - { - "id": 16337, - "emoji": "😁", - "count": 12 - }, - { - "id": 61443, "emoji": "🥹", - "count": 20 - }, - { - "id": 68842, - "emoji": "😁", - "count": 16 - }, - { - "id": 32585, - "emoji": "🎉", - "count": 10 + "count": 584 }, { - "id": 71746, - "emoji": "😁", - "count": 9 + "emoji": "👍", + "count": 958 } ] }, @@ -3204,34 +2609,16 @@ "reactionCount": 74, "topReactions": [ { - "id": 47111, - "emoji": "👍", - "count": 12 - }, - { - "id": 67878, - "emoji": "😀", - "count": 16 - }, - { - "id": 49575, - "emoji": "😀", - "count": 10 + "emoji": "❤️", + "count": 222 }, { - "id": 72740, "emoji": "🎉", - "count": 15 - }, - { - "id": 66239, - "emoji": "❤️", - "count": 16 + "count": 8 }, { - "id": 78326, - "emoji": "🥹", - "count": 14 + "emoji": "😀", + "count": 947 } ] }, @@ -3256,20 +2643,20 @@ { "id": 96788, "recipientId": 73648, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/249/200/200", "relationship": "가족", - "content": "Suwon Kim님의 메세지 내용 54", + "content": "Sowon Kim님의 메세지 내용 54", "font": "Nanum Gothic", "createdAt": "2023-09-16T01:58:06Z" }, { "id": 20726, "recipientId": 73648, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/431/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 78", + "content": "Sowon Kim님의 메세지 내용 78", "font": "Pretendard", "createdAt": "2023-07-25T07:59:44Z" } @@ -3277,29 +2664,8 @@ "reactionCount": 45, "topReactions": [ { - "id": 86527, - "emoji": "😁", - "count": 15 - }, - { - "id": 59551, "emoji": "🥹", - "count": 16 - }, - { - "id": 3729, - "emoji": "😀", - "count": 2 - }, - { - "id": 29902, - "emoji": "🎉", - "count": 12 - }, - { - "id": 39150, - "emoji": "❤️", - "count": 19 + "count": 466 } ] }, @@ -3325,34 +2691,12 @@ "reactionCount": 59, "topReactions": [ { - "id": 93221, "emoji": "👍", - "count": 1 + "count": 787 }, { - "id": 95714, "emoji": "🎉", - "count": 8 - }, - { - "id": 8397, - "emoji": "🎉", - "count": 16 - }, - { - "id": 70176, - "emoji": "🎉", - "count": 9 - }, - { - "id": 67165, - "emoji": "🎉", - "count": 10 - }, - { - "id": 41000, - "emoji": "👍", - "count": 7 + "count": 995 } ] }, @@ -3378,19 +2722,8 @@ "reactionCount": 91, "topReactions": [ { - "id": 72115, "emoji": "👍", - "count": 5 - }, - { - "id": 91626, - "emoji": "❤️", - "count": 18 - }, - { - "id": 19336, - "emoji": "😀", - "count": 4 + "count": 571 } ] }, @@ -3436,19 +2769,12 @@ "reactionCount": 8, "topReactions": [ { - "id": 3482, - "emoji": "👍", - "count": 18 - }, - { - "id": 66591, "emoji": "🥹", - "count": 7 + "count": 229 }, { - "id": 38585, - "emoji": "🥹", - "count": 19 + "emoji": "👍", + "count": 597 } ] }, @@ -3494,24 +2820,12 @@ "reactionCount": 68, "topReactions": [ { - "id": 59908, - "emoji": "❤️", - "count": 9 + "emoji": "👍", + "count": 102 }, { - "id": 88137, "emoji": "❤️", - "count": 18 - }, - { - "id": 73395, - "emoji": "😀", - "count": 1 - }, - { - "id": 1194, - "emoji": "👍", - "count": 7 + "count": 306 } ] }, @@ -3557,34 +2871,8 @@ "reactionCount": 32, "topReactions": [ { - "id": 91871, - "emoji": "🎉", - "count": 13 - }, - { - "id": 78009, - "emoji": "🎉", - "count": 6 - }, - { - "id": 19885, - "emoji": "😁", - "count": 16 - }, - { - "id": 93729, "emoji": "❤️", - "count": 19 - }, - { - "id": 57682, - "emoji": "🥹", - "count": 19 - }, - { - "id": 6511, - "emoji": "🎉", - "count": 15 + "count": 759 } ] }, @@ -3630,29 +2918,8 @@ "reactionCount": 53, "topReactions": [ { - "id": 14727, - "emoji": "🥹", - "count": 20 - }, - { - "id": 66436, - "emoji": "🎉", - "count": 5 - }, - { - "id": 36308, "emoji": "👍", - "count": 14 - }, - { - "id": 21367, - "emoji": "😁", - "count": 18 - }, - { - "id": 12087, - "emoji": "😁", - "count": 9 + "count": 559 } ] }, @@ -3688,9 +2955,8 @@ "reactionCount": 97, "topReactions": [ { - "id": 57205, "emoji": "👍", - "count": 19 + "count": 780 } ] }, @@ -3725,10 +2991,10 @@ { "id": 65998, "recipientId": 73391, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/117/200/200", "relationship": "가족", - "content": "Suwon Kim님의 메세지 내용 7", + "content": "Sowon Kim님의 메세지 내용 7", "font": "Noto Sans", "createdAt": "2023-06-29T21:54:39Z" } @@ -3736,9 +3002,8 @@ "reactionCount": 64, "topReactions": [ { - "id": 87665, "emoji": "🎉", - "count": 12 + "count": 698 } ] }, @@ -3784,34 +3049,8 @@ "reactionCount": 18, "topReactions": [ { - "id": 55291, - "emoji": "😁", - "count": 15 - }, - { - "id": 90016, - "emoji": "❤️", - "count": 15 - }, - { - "id": 84184, - "emoji": "😁", - "count": 9 - }, - { - "id": 43715, "emoji": "🥹", - "count": 3 - }, - { - "id": 62315, - "emoji": "🎉", - "count": 6 - }, - { - "id": 34308, - "emoji": "🎉", - "count": 12 + "count": 609 } ] }, @@ -3857,34 +3096,16 @@ "reactionCount": 64, "topReactions": [ { - "id": 27890, - "emoji": "🥹", - "count": 12 - }, - { - "id": 56175, - "emoji": "👍", - "count": 17 - }, - { - "id": 91877, - "emoji": "🥹", - "count": 6 - }, - { - "id": 69359, "emoji": "😀", - "count": 7 + "count": 486 }, { - "id": 52444, "emoji": "❤️", - "count": 19 + "count": 416 }, { - "id": 40782, - "emoji": "😁", - "count": 13 + "emoji": "👍", + "count": 171 } ] }, @@ -3930,30 +3151,22 @@ "reactionCount": 36, "topReactions": [ { - "id": 76073, - "emoji": "🥹", - "count": 8 - }, - { - "id": 96332, "emoji": "🎉", - "count": 17 + "count": 231 }, { - "id": 10485, "emoji": "🥹", - "count": 5 + "count": 667 }, { - "id": 59065, "emoji": "👍", - "count": 7 + "count": 246 } ] }, { "id": 26744, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "beige", "backgroundImageURL": null, "createdAt": "2023-03-23T03:14:00Z", @@ -3993,34 +3206,16 @@ "reactionCount": 96, "topReactions": [ { - "id": 43701, "emoji": "😁", - "count": 11 + "count": 921 }, { - "id": 56499, - "emoji": "🎉", - "count": 3 - }, - { - "id": 84055, - "emoji": "😀", - "count": 11 - }, - { - "id": 17678, - "emoji": "🥹", - "count": 15 - }, - { - "id": 79009, "emoji": "❤️", - "count": 17 + "count": 453 }, { - "id": 77257, - "emoji": "😀", - "count": 8 + "emoji": "🎉", + "count": 433 } ] }, @@ -4063,27 +3258,11 @@ "createdAt": "2023-07-28T04:12:32Z" } ], - "reactionCount": 57, - "topReactions": [ - { - "id": 14687, - "emoji": "😀", - "count": 19 - }, - { - "id": 39344, - "emoji": "👍", - "count": 7 - }, - { - "id": 34161, - "emoji": "🎉", - "count": 13 - }, + "reactionCount": 57, + "topReactions": [ { - "id": 35565, - "emoji": "🎉", - "count": 16 + "emoji": "😀", + "count": 379 } ] }, @@ -4098,10 +3277,10 @@ { "id": 35228, "recipientId": 90477, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/94/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 63", + "content": "Sowon Kim님의 메세지 내용 63", "font": "Roboto", "createdAt": "2023-05-25T06:02:55Z" }, @@ -4129,19 +3308,12 @@ "reactionCount": 96, "topReactions": [ { - "id": 23630, - "emoji": "🥹", - "count": 19 - }, - { - "id": 94766, "emoji": "😁", - "count": 3 + "count": 286 }, { - "id": 59725, "emoji": "😀", - "count": 19 + "count": 100 } ] }, @@ -4187,24 +3359,16 @@ "reactionCount": 76, "topReactions": [ { - "id": 15262, - "emoji": "😀", - "count": 8 + "emoji": "❤️", + "count": 367 }, { - "id": 76672, "emoji": "👍", - "count": 12 + "count": 476 }, { - "id": 85829, "emoji": "😀", - "count": 14 - }, - { - "id": 86733, - "emoji": "❤️", - "count": 13 + "count": 449 } ] }, @@ -4250,19 +3414,8 @@ "reactionCount": 54, "topReactions": [ { - "id": 74781, - "emoji": "🎉", - "count": 3 - }, - { - "id": 8118, - "emoji": "😁", - "count": 19 - }, - { - "id": 42107, "emoji": "🥹", - "count": 7 + "count": 474 } ] }, @@ -4308,14 +3461,12 @@ "reactionCount": 89, "topReactions": [ { - "id": 12830, - "emoji": "🥹", - "count": 5 + "emoji": "😁", + "count": 393 }, { - "id": 70733, - "emoji": "😁", - "count": 8 + "emoji": "🥹", + "count": 30 } ] }, @@ -4361,24 +3512,8 @@ "reactionCount": 81, "topReactions": [ { - "id": 1589, - "emoji": "🥹", - "count": 15 - }, - { - "id": 78183, - "emoji": "🎉", - "count": 19 - }, - { - "id": 22247, "emoji": "🎉", - "count": 1 - }, - { - "id": 19112, - "emoji": "🥹", - "count": 17 + "count": 609 } ] }, @@ -4424,40 +3559,22 @@ "reactionCount": 59, "topReactions": [ { - "id": 34874, - "emoji": "❤️", - "count": 15 - }, - { - "id": 26479, - "emoji": "😁", - "count": 1 - }, - { - "id": 35105, "emoji": "🎉", - "count": 18 - }, - { - "id": 6384, - "emoji": "😀", - "count": 13 + "count": 205 }, { - "id": 70298, "emoji": "🥹", - "count": 9 + "count": 461 }, { - "id": 48862, - "emoji": "😁", - "count": 11 + "emoji": "😀", + "count": 580 } ] }, { "id": 31714, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "beige", "backgroundImageURL": "https://picsum.photos/seed/31714/600/400", "createdAt": "2023-01-13T08:26:56Z", @@ -4477,24 +3594,8 @@ "reactionCount": 15, "topReactions": [ { - "id": 84856, - "emoji": "😀", - "count": 2 - }, - { - "id": 37418, - "emoji": "😁", - "count": 16 - }, - { - "id": 68962, - "emoji": "🥹", - "count": 16 - }, - { - "id": 63309, "emoji": "🥹", - "count": 8 + "count": 854 } ] }, @@ -4529,10 +3630,10 @@ { "id": 88820, "recipientId": 24976, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/355/200/200", "relationship": "동료", - "content": "Suwon Kim님의 메세지 내용 72", + "content": "Sowon Kim님의 메세지 내용 72", "font": "Pretendard", "createdAt": "2023-12-02T16:28:28Z" } @@ -4540,34 +3641,12 @@ "reactionCount": 14, "topReactions": [ { - "id": 23520, - "emoji": "😁", - "count": 1 - }, - { - "id": 1327, "emoji": "🎉", - "count": 6 + "count": 534 }, { - "id": 99333, "emoji": "😀", - "count": 7 - }, - { - "id": 24221, - "emoji": "😁", - "count": 8 - }, - { - "id": 34796, - "emoji": "👍", - "count": 13 - }, - { - "id": 24544, - "emoji": "🎉", - "count": 5 + "count": 337 } ] }, @@ -4613,29 +3692,12 @@ "reactionCount": 26, "topReactions": [ { - "id": 67233, - "emoji": "🥹", - "count": 18 - }, - { - "id": 15477, - "emoji": "😁", - "count": 6 - }, - { - "id": 52552, - "emoji": "😁", - "count": 2 - }, - { - "id": 4534, "emoji": "❤️", - "count": 5 + "count": 655 }, { - "id": 81700, - "emoji": "🎉", - "count": 5 + "emoji": "😁", + "count": 504 } ] }, @@ -4681,24 +3743,8 @@ "reactionCount": 60, "topReactions": [ { - "id": 67321, - "emoji": "😀", - "count": 10 - }, - { - "id": 37472, - "emoji": "🥹", - "count": 12 - }, - { - "id": 38481, - "emoji": "😁", - "count": 5 - }, - { - "id": 10179, "emoji": "😁", - "count": 14 + "count": 41 } ] }, @@ -4713,10 +3759,10 @@ { "id": 35658, "recipientId": 9191, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/62/200/200", "relationship": "동료", - "content": "Suwon Kim님의 메세지 내용 27", + "content": "Sowon Kim님의 메세지 내용 27", "font": "Nanum Gothic", "createdAt": "2023-04-09T12:56:46Z" }, @@ -4733,10 +3779,10 @@ { "id": 20041, "recipientId": 9191, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/114/200/200", "relationship": "가족", - "content": "Suwon Kim님의 메세지 내용 72", + "content": "Sowon Kim님의 메세지 내용 72", "font": "Pretendard", "createdAt": "2023-11-11T12:43:30Z" } @@ -4744,34 +3790,16 @@ "reactionCount": 90, "topReactions": [ { - "id": 46794, - "emoji": "🎉", - "count": 2 - }, - { - "id": 78569, - "emoji": "😁", - "count": 20 - }, - { - "id": 71969, - "emoji": "😀", - "count": 14 - }, - { - "id": 8787, "emoji": "❤️", - "count": 10 + "count": 771 }, { - "id": 56094, - "emoji": "🥹", - "count": 3 + "emoji": "😀", + "count": 898 }, { - "id": 4661, - "emoji": "😁", - "count": 6 + "emoji": "🎉", + "count": 17 } ] }, @@ -4807,9 +3835,8 @@ "reactionCount": 53, "topReactions": [ { - "id": 33992, "emoji": "🎉", - "count": 13 + "count": 153 } ] }, @@ -4834,10 +3861,10 @@ { "id": 53736, "recipientId": 625, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/411/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 98", + "content": "Sowon Kim님의 메세지 내용 98", "font": "Nanum Gothic", "createdAt": "2023-06-06T17:47:12Z" }, @@ -4855,24 +3882,12 @@ "reactionCount": 66, "topReactions": [ { - "id": 36713, - "emoji": "❤️", - "count": 2 - }, - { - "id": 89567, - "emoji": "🥹", - "count": 2 - }, - { - "id": 98915, "emoji": "🥹", - "count": 7 + "count": 640 }, { - "id": 6789, "emoji": "😁", - "count": 10 + "count": 605 } ] }, @@ -4907,10 +3922,10 @@ { "id": 53607, "recipientId": 23417, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/402/200/200", "relationship": "지인", - "content": "Suwon Kim님의 메세지 내용 96", + "content": "Sowon Kim님의 메세지 내용 96", "font": "Noto Sans", "createdAt": "2023-06-28T04:25:20Z" } @@ -4918,29 +3933,12 @@ "reactionCount": 42, "topReactions": [ { - "id": 2457, - "emoji": "👍", - "count": 10 - }, - { - "id": 86246, - "emoji": "❤️", - "count": 2 + "emoji": "😁", + "count": 463 }, { - "id": 54698, "emoji": "❤️", - "count": 7 - }, - { - "id": 72375, - "emoji": "😀", - "count": 2 - }, - { - "id": 7835, - "emoji": "😁", - "count": 1 + "count": 510 } ] }, @@ -4986,29 +3984,16 @@ "reactionCount": 51, "topReactions": [ { - "id": 60510, "emoji": "😁", - "count": 5 - }, - { - "id": 183, - "emoji": "😀", - "count": 12 + "count": 808 }, { - "id": 70387, "emoji": "❤️", - "count": 5 - }, - { - "id": 5940, - "emoji": "🥹", - "count": 20 + "count": 905 }, { - "id": 69316, - "emoji": "🎉", - "count": 2 + "emoji": "😀", + "count": 541 } ] }, @@ -5054,19 +4039,16 @@ "reactionCount": 6, "topReactions": [ { - "id": 52593, - "emoji": "🥹", - "count": 1 - }, - { - "id": 49827, "emoji": "🎉", - "count": 12 + "count": 654 }, { - "id": 3837, "emoji": "👍", - "count": 9 + "count": 618 + }, + { + "emoji": "🥹", + "count": 827 } ] }, @@ -5081,10 +4063,10 @@ { "id": 76625, "recipientId": 48647, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/256/200/200", "relationship": "가족", - "content": "Suwon Kim님의 메세지 내용 98", + "content": "Sowon Kim님의 메세지 내용 98", "font": "Pretendard", "createdAt": "2023-03-21T02:42:08Z" }, @@ -5112,24 +4094,16 @@ "reactionCount": 28, "topReactions": [ { - "id": 38782, "emoji": "🎉", - "count": 10 - }, - { - "id": 30497, - "emoji": "❤️", - "count": 20 + "count": 993 }, { - "id": 65578, "emoji": "😀", - "count": 11 + "count": 939 }, { - "id": 54351, "emoji": "❤️", - "count": 2 + "count": 447 } ] }, @@ -5144,10 +4118,10 @@ { "id": 90888, "recipientId": 7110, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/19/200/200", "relationship": "지인", - "content": "Suwon Kim님의 메세지 내용 42", + "content": "Sowon Kim님의 메세지 내용 42", "font": "Roboto", "createdAt": "2023-09-16T18:15:50Z" }, @@ -5175,24 +4149,16 @@ "reactionCount": 75, "topReactions": [ { - "id": 71539, - "emoji": "👍", - "count": 15 - }, - { - "id": 86386, "emoji": "❤️", - "count": 4 + "count": 861 }, { - "id": 81736, - "emoji": "🎉", - "count": 12 + "emoji": "👍", + "count": 953 }, { - "id": 63021, - "emoji": "❤️", - "count": 13 + "emoji": "🎉", + "count": 390 } ] }, @@ -5238,25 +4204,22 @@ "reactionCount": 52, "topReactions": [ { - "id": 21041, - "emoji": "❤️", - "count": 3 + "emoji": "🎉", + "count": 945 }, { - "id": 81901, - "emoji": "🎉", - "count": 20 + "emoji": "❤️", + "count": 556 }, { - "id": 3660, "emoji": "🥹", - "count": 7 + "count": 28 } ] }, { "id": 75973, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "beige", "backgroundImageURL": "https://picsum.photos/seed/75973/600/400", "createdAt": "2023-04-29T23:14:33Z", @@ -5265,10 +4228,10 @@ { "id": 85401, "recipientId": 75973, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/269/200/200", "relationship": "동료", - "content": "Suwon Kim님의 메세지 내용 90", + "content": "Sowon Kim님의 메세지 내용 90", "font": "Noto Sans", "createdAt": "2023-11-12T05:17:44Z" }, @@ -5296,24 +4259,12 @@ "reactionCount": 27, "topReactions": [ { - "id": 98483, - "emoji": "🥹", - "count": 5 - }, - { - "id": 73979, - "emoji": "🥹", - "count": 7 + "emoji": "😁", + "count": 850 }, { - "id": 14149, "emoji": "🥹", - "count": 4 - }, - { - "id": 73714, - "emoji": "😁", - "count": 11 + "count": 931 } ] }, @@ -5359,19 +4310,12 @@ "reactionCount": 54, "topReactions": [ { - "id": 84273, "emoji": "🥹", - "count": 18 + "count": 74 }, { - "id": 67980, "emoji": "😀", - "count": 19 - }, - { - "id": 57293, - "emoji": "🥹", - "count": 9 + "count": 239 } ] }, @@ -5417,29 +4361,12 @@ "reactionCount": 66, "topReactions": [ { - "id": 48674, - "emoji": "😁", - "count": 16 - }, - { - "id": 8548, "emoji": "😀", - "count": 6 - }, - { - "id": 43006, - "emoji": "😁", - "count": 15 + "count": 657 }, { - "id": 6573, "emoji": "😁", - "count": 6 - }, - { - "id": 57200, - "emoji": "😀", - "count": 1 + "count": 573 } ] }, @@ -5485,24 +4412,16 @@ "reactionCount": 48, "topReactions": [ { - "id": 214, - "emoji": "👍", - "count": 3 + "emoji": "❤️", + "count": 258 }, { - "id": 16801, "emoji": "😀", - "count": 1 - }, - { - "id": 64372, - "emoji": "❤️", - "count": 18 + "count": 476 }, { - "id": 4933, - "emoji": "🎉", - "count": 4 + "emoji": "👍", + "count": 813 } ] }, @@ -5548,24 +4467,16 @@ "reactionCount": 55, "topReactions": [ { - "id": 1802, - "emoji": "😀", - "count": 10 - }, - { - "id": 94631, "emoji": "🎉", - "count": 17 + "count": 347 }, { - "id": 42577, - "emoji": "❤️", - "count": 6 + "emoji": "😀", + "count": 532 }, { - "id": 83907, - "emoji": "🎉", - "count": 6 + "emoji": "❤️", + "count": 718 } ] }, @@ -5611,24 +4522,12 @@ "reactionCount": 6, "topReactions": [ { - "id": 14584, - "emoji": "👍", - "count": 16 - }, - { - "id": 64130, "emoji": "🎉", - "count": 19 - }, - { - "id": 98800, - "emoji": "😀", - "count": 20 + "count": 169 }, { - "id": 93562, "emoji": "😁", - "count": 13 + "count": 329 } ] }, @@ -5674,29 +4573,8 @@ "reactionCount": 24, "topReactions": [ { - "id": 85440, - "emoji": "😀", - "count": 4 - }, - { - "id": 94784, "emoji": "❤️", - "count": 3 - }, - { - "id": 65361, - "emoji": "👍", - "count": 12 - }, - { - "id": 74494, - "emoji": "🥹", - "count": 2 - }, - { - "id": 20433, - "emoji": "🥹", - "count": 2 + "count": 996 } ] }, @@ -5742,20 +4620,18 @@ "reactionCount": 65, "topReactions": [ { - "id": 4983, - "emoji": "😀", - "count": 20 + "emoji": "❤️", + "count": 276 }, { - "id": 91060, - "emoji": "❤️", - "count": 2 + "emoji": "😀", + "count": 421 } ] }, { "id": 32314, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "purple", "backgroundImageURL": null, "createdAt": "2023-06-09T07:16:23Z", @@ -5774,10 +4650,10 @@ { "id": 10034, "recipientId": 32314, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/288/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 22", + "content": "Sowon Kim님의 메세지 내용 22", "font": "Pretendard", "createdAt": "2023-09-14T13:27:24Z" }, @@ -5795,9 +4671,8 @@ "reactionCount": 59, "topReactions": [ { - "id": 58698, "emoji": "😀", - "count": 13 + "count": 832 } ] }, @@ -5837,25 +4712,14 @@ "relationship": "동료", "content": "김하은님의 메세지 내용 17", "font": "Pretendard", - "createdAt": "2023-11-16T09:47:54Z" - } - ], - "reactionCount": 16, - "topReactions": [ - { - "id": 7801, - "emoji": "😁", - "count": 12 - }, - { - "id": 58961, - "emoji": "❤️", - "count": 16 - }, + "createdAt": "2023-11-16T09:47:54Z" + } + ], + "reactionCount": 16, + "topReactions": [ { - "id": 59283, - "emoji": "🥹", - "count": 5 + "emoji": "😁", + "count": 23 } ] }, @@ -5901,9 +4765,8 @@ "reactionCount": 37, "topReactions": [ { - "id": 11248, "emoji": "❤️", - "count": 3 + "count": 693 } ] }, @@ -5938,10 +4801,10 @@ { "id": 50489, "recipientId": 63219, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/11/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 77", + "content": "Sowon Kim님의 메세지 내용 77", "font": "Noto Sans", "createdAt": "2023-11-27T08:16:32Z" } @@ -5949,20 +4812,14 @@ "reactionCount": 17, "topReactions": [ { - "id": 78228, "emoji": "🥹", - "count": 4 - }, - { - "id": 93441, - "emoji": "🥹", - "count": 10 + "count": 700 } ] }, { "id": 32218, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "beige", "backgroundImageURL": null, "createdAt": "2023-07-22T22:33:51Z", @@ -6002,29 +4859,12 @@ "reactionCount": 47, "topReactions": [ { - "id": 88844, "emoji": "🎉", - "count": 16 - }, - { - "id": 58724, - "emoji": "👍", - "count": 19 - }, - { - "id": 26471, - "emoji": "👍", - "count": 5 + "count": 474 }, { - "id": 39423, - "emoji": "😁", - "count": 15 - }, - { - "id": 68714, "emoji": "👍", - "count": 6 + "count": 437 } ] }, @@ -6070,9 +4910,8 @@ "reactionCount": 2, "topReactions": [ { - "id": 42141, "emoji": "👍", - "count": 19 + "count": 425 } ] }, @@ -6107,10 +4946,10 @@ { "id": 24988, "recipientId": 1341, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/423/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 64", + "content": "Sowon Kim님의 메세지 내용 64", "font": "Roboto", "createdAt": "2023-01-06T05:53:05Z" } @@ -6118,9 +4957,8 @@ "reactionCount": 95, "topReactions": [ { - "id": 39502, "emoji": "🎉", - "count": 11 + "count": 666 } ] }, @@ -6166,25 +5004,14 @@ "reactionCount": 87, "topReactions": [ { - "id": 1723, "emoji": "🎉", - "count": 3 - }, - { - "id": 7654, - "emoji": "😀", - "count": 8 - }, - { - "id": 29263, - "emoji": "😀", - "count": 4 + "count": 381 } ] }, { "id": 93438, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "blue", "backgroundImageURL": "https://picsum.photos/seed/93438/600/400", "createdAt": "2023-04-02T11:00:53Z", @@ -6203,10 +5030,10 @@ { "id": 6156, "recipientId": 93438, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/109/200/200", "relationship": "동료", - "content": "Suwon Kim님의 메세지 내용 59", + "content": "Sowon Kim님의 메세지 내용 59", "font": "Noto Sans", "createdAt": "2023-01-24T10:30:39Z" }, @@ -6224,15 +5051,14 @@ "reactionCount": 99, "topReactions": [ { - "id": 19288, "emoji": "😁", - "count": 11 + "count": 891 } ] }, { "id": 44334, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "blue", "backgroundImageURL": "https://picsum.photos/seed/44334/600/400", "createdAt": "2023-12-30T01:42:47Z", @@ -6272,34 +5098,8 @@ "reactionCount": 87, "topReactions": [ { - "id": 37061, - "emoji": "👍", - "count": 6 - }, - { - "id": 2287, - "emoji": "👍", - "count": 11 - }, - { - "id": 45099, - "emoji": "😀", - "count": 12 - }, - { - "id": 90256, - "emoji": "😁", - "count": 7 - }, - { - "id": 99885, - "emoji": "👍", - "count": 8 - }, - { - "id": 76279, "emoji": "❤️", - "count": 12 + "count": 390 } ] }, @@ -6345,15 +5145,14 @@ "reactionCount": 70, "topReactions": [ { - "id": 17950, "emoji": "🥹", - "count": 20 + "count": 766 } ] }, { "id": 44928, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "beige", "backgroundImageURL": null, "createdAt": "2023-11-24T12:12:26Z", @@ -6373,24 +5172,12 @@ "reactionCount": 8, "topReactions": [ { - "id": 82489, - "emoji": "🥹", - "count": 7 - }, - { - "id": 41836, "emoji": "🥹", - "count": 7 - }, - { - "id": 64846, - "emoji": "❤️", - "count": 9 + "count": 470 }, { - "id": 50727, "emoji": "❤️", - "count": 14 + "count": 625 } ] }, @@ -6405,10 +5192,10 @@ { "id": 31761, "recipientId": 94539, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/62/200/200", "relationship": "가족", - "content": "Suwon Kim님의 메세지 내용 53", + "content": "Sowon Kim님의 메세지 내용 53", "font": "Pretendard", "createdAt": "2023-04-17T18:23:36Z" }, @@ -6436,14 +5223,12 @@ "reactionCount": 92, "topReactions": [ { - "id": 73214, - "emoji": "👍", - "count": 14 + "emoji": "😀", + "count": 634 }, { - "id": 314, - "emoji": "😀", - "count": 20 + "emoji": "👍", + "count": 296 } ] }, @@ -6489,24 +5274,12 @@ "reactionCount": 73, "topReactions": [ { - "id": 49624, - "emoji": "😁", - "count": 6 - }, - { - "id": 69914, "emoji": "😁", - "count": 17 - }, - { - "id": 12300, - "emoji": "👍", - "count": 16 + "count": 171 }, { - "id": 26416, "emoji": "🎉", - "count": 12 + "count": 87 } ] }, @@ -6552,9 +5325,8 @@ "reactionCount": 96, "topReactions": [ { - "id": 85370, "emoji": "😀", - "count": 9 + "count": 844 } ] }, @@ -6600,29 +5372,16 @@ "reactionCount": 76, "topReactions": [ { - "id": 20609, "emoji": "😀", - "count": 4 + "count": 470 }, { - "id": 24638, "emoji": "❤️", - "count": 8 - }, - { - "id": 38365, - "emoji": "👍", - "count": 20 - }, - { - "id": 16361, - "emoji": "😀", - "count": 2 + "count": 638 }, { - "id": 41186, "emoji": "👍", - "count": 20 + "count": 364 } ] }, @@ -6648,9 +5407,8 @@ "reactionCount": 79, "topReactions": [ { - "id": 36218, "emoji": "😀", - "count": 9 + "count": 595 } ] }, @@ -6696,34 +5454,12 @@ "reactionCount": 73, "topReactions": [ { - "id": 24875, - "emoji": "😀", - "count": 12 - }, - { - "id": 99067, - "emoji": "❤️", - "count": 20 - }, - { - "id": 24734, - "emoji": "❤️", - "count": 20 - }, - { - "id": 3733, "emoji": "👍", - "count": 10 - }, - { - "id": 54558, - "emoji": "🥹", - "count": 11 + "count": 375 }, { - "id": 21392, - "emoji": "🎉", - "count": 18 + "emoji": "😀", + "count": 358 } ] }, @@ -6759,29 +5495,12 @@ "reactionCount": 82, "topReactions": [ { - "id": 53064, - "emoji": "❤️", - "count": 4 + "emoji": "😀", + "count": 232 }, { - "id": 84662, "emoji": "🎉", - "count": 16 - }, - { - "id": 15519, - "emoji": "❤️", - "count": 19 - }, - { - "id": 75306, - "emoji": "❤️", - "count": 19 - }, - { - "id": 59498, - "emoji": "😀", - "count": 14 + "count": 564 } ] }, @@ -6827,24 +5546,16 @@ "reactionCount": 57, "topReactions": [ { - "id": 67314, - "emoji": "🎉", - "count": 6 - }, - { - "id": 20708, - "emoji": "👍", - "count": 13 + "emoji": "🥹", + "count": 243 }, { - "id": 32217, - "emoji": "🥹", - "count": 8 + "emoji": "🎉", + "count": 12 }, { - "id": 59013, "emoji": "😁", - "count": 9 + "count": 966 } ] }, @@ -6890,24 +5601,16 @@ "reactionCount": 47, "topReactions": [ { - "id": 81037, - "emoji": "🥹", - "count": 20 + "emoji": "🎉", + "count": 383 }, { - "id": 16358, "emoji": "😁", - "count": 3 - }, - { - "id": 44167, - "emoji": "😀", - "count": 15 + "count": 160 }, { - "id": 66141, - "emoji": "🎉", - "count": 19 + "emoji": "🥹", + "count": 822 } ] }, @@ -6933,19 +5636,12 @@ "reactionCount": 43, "topReactions": [ { - "id": 17924, - "emoji": "😀", - "count": 12 + "emoji": "🥹", + "count": 544 }, { - "id": 49600, "emoji": "😀", - "count": 11 - }, - { - "id": 11142, - "emoji": "🥹", - "count": 7 + "count": 617 } ] }, @@ -6970,10 +5666,10 @@ { "id": 41596, "recipientId": 43809, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/439/200/200", "relationship": "동료", - "content": "Suwon Kim님의 메세지 내용 36", + "content": "Sowon Kim님의 메세지 내용 36", "font": "Roboto", "createdAt": "2023-02-12T07:13:07Z" }, @@ -6991,14 +5687,12 @@ "reactionCount": 45, "topReactions": [ { - "id": 89452, "emoji": "🥹", - "count": 11 + "count": 3 }, { - "id": 83618, "emoji": "😀", - "count": 12 + "count": 575 } ] }, @@ -7044,14 +5738,12 @@ "reactionCount": 7, "topReactions": [ { - "id": 45551, - "emoji": "❤️", - "count": 19 + "emoji": "😁", + "count": 772 }, { - "id": 57044, - "emoji": "😁", - "count": 1 + "emoji": "❤️", + "count": 189 } ] }, @@ -7086,10 +5778,10 @@ { "id": 62162, "recipientId": 62125, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/293/200/200", "relationship": "지인", - "content": "Suwon Kim님의 메세지 내용 93", + "content": "Sowon Kim님의 메세지 내용 93", "font": "Roboto", "createdAt": "2023-04-29T23:05:56Z" } @@ -7097,9 +5789,8 @@ "reactionCount": 75, "topReactions": [ { - "id": 11123, "emoji": "🎉", - "count": 14 + "count": 421 } ] }, @@ -7145,34 +5836,8 @@ "reactionCount": 55, "topReactions": [ { - "id": 79847, - "emoji": "👍", - "count": 9 - }, - { - "id": 33325, - "emoji": "🎉", - "count": 6 - }, - { - "id": 19452, - "emoji": "😀", - "count": 4 - }, - { - "id": 70794, - "emoji": "🥹", - "count": 20 - }, - { - "id": 55957, - "emoji": "😀", - "count": 20 - }, - { - "id": 1762, "emoji": "🎉", - "count": 14 + "count": 521 } ] }, @@ -7207,10 +5872,10 @@ { "id": 91516, "recipientId": 58844, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/108/200/200", "relationship": "가족", - "content": "Suwon Kim님의 메세지 내용 82", + "content": "Sowon Kim님의 메세지 내용 82", "font": "Pretendard", "createdAt": "2023-08-27T12:05:46Z" } @@ -7218,24 +5883,8 @@ "reactionCount": 20, "topReactions": [ { - "id": 81634, - "emoji": "😀", - "count": 5 - }, - { - "id": 88135, - "emoji": "🥹", - "count": 16 - }, - { - "id": 86465, - "emoji": "😀", - "count": 13 - }, - { - "id": 92893, "emoji": "❤️", - "count": 3 + "count": 154 } ] }, @@ -7260,10 +5909,10 @@ { "id": 29903, "recipientId": 72437, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/106/200/200", "relationship": "동료", - "content": "Suwon Kim님의 메세지 내용 40", + "content": "Sowon Kim님의 메세지 내용 40", "font": "Roboto", "createdAt": "2023-04-29T16:49:48Z" } @@ -7271,24 +5920,8 @@ "reactionCount": 98, "topReactions": [ { - "id": 70510, - "emoji": "🎉", - "count": 20 - }, - { - "id": 66505, - "emoji": "👍", - "count": 3 - }, - { - "id": 66557, "emoji": "❤️", - "count": 12 - }, - { - "id": 61631, - "emoji": "😁", - "count": 20 + "count": 11 } ] }, @@ -7323,10 +5956,10 @@ { "id": 91691, "recipientId": 31124, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/461/200/200", "relationship": "지인", - "content": "Suwon Kim님의 메세지 내용 53", + "content": "Sowon Kim님의 메세지 내용 53", "font": "Roboto", "createdAt": "2023-05-21T09:55:42Z" } @@ -7334,20 +5967,18 @@ "reactionCount": 91, "topReactions": [ { - "id": 70597, "emoji": "😁", - "count": 10 + "count": 439 }, { - "id": 86461, "emoji": "👍", - "count": 11 + "count": 337 } ] }, { "id": 73111, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "blue", "backgroundImageURL": null, "createdAt": "2023-12-29T11:24:51Z", @@ -7377,24 +6008,8 @@ "reactionCount": 16, "topReactions": [ { - "id": 42626, - "emoji": "😀", - "count": 7 - }, - { - "id": 2933, - "emoji": "😁", - "count": 19 - }, - { - "id": 8592, "emoji": "👍", - "count": 20 - }, - { - "id": 33974, - "emoji": "😀", - "count": 9 + "count": 642 } ] }, @@ -7419,10 +6034,10 @@ { "id": 2974, "recipientId": 44599, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/46/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 13", + "content": "Sowon Kim님의 메세지 내용 13", "font": "Roboto", "createdAt": "2023-11-11T07:56:34Z" }, @@ -7440,34 +6055,12 @@ "reactionCount": 54, "topReactions": [ { - "id": 69943, - "emoji": "🥹", - "count": 8 - }, - { - "id": 93387, - "emoji": "😀", - "count": 10 - }, - { - "id": 55895, - "emoji": "❤️", - "count": 12 - }, - { - "id": 1552, - "emoji": "🥹", - "count": 13 - }, - { - "id": 62897, "emoji": "❤️", - "count": 8 + "count": 97 }, { - "id": 11953, - "emoji": "👍", - "count": 9 + "emoji": "😀", + "count": 591 } ] }, @@ -7513,29 +6106,16 @@ "reactionCount": 99, "topReactions": [ { - "id": 26899, - "emoji": "🥹", - "count": 19 - }, - { - "id": 64192, "emoji": "😀", - "count": 20 - }, - { - "id": 38049, - "emoji": "🥹", - "count": 12 + "count": 360 }, { - "id": 3255, - "emoji": "❤️", - "count": 3 + "emoji": "👍", + "count": 360 }, { - "id": 35106, - "emoji": "👍", - "count": 17 + "emoji": "🥹", + "count": 667 } ] }, @@ -7581,34 +6161,8 @@ "reactionCount": 81, "topReactions": [ { - "id": 40481, - "emoji": "😁", - "count": 6 - }, - { - "id": 89819, "emoji": "👍", - "count": 5 - }, - { - "id": 56551, - "emoji": "🎉", - "count": 8 - }, - { - "id": 90383, - "emoji": "🎉", - "count": 8 - }, - { - "id": 48052, - "emoji": "😁", - "count": 4 - }, - { - "id": 53141, - "emoji": "🎉", - "count": 10 + "count": 825 } ] }, @@ -7654,14 +6208,12 @@ "reactionCount": 91, "topReactions": [ { - "id": 22984, - "emoji": "😁", - "count": 2 + "emoji": "😀", + "count": 979 }, { - "id": 38976, - "emoji": "😀", - "count": 1 + "emoji": "😁", + "count": 230 } ] }, @@ -7695,22 +6247,16 @@ } ], "reactionCount": 48, - "topReactions": [ - { - "id": 64931, - "emoji": "❤️", - "count": 5 - }, + "topReactions": [ { - "id": 32976, "emoji": "🎉", - "count": 19 + "count": 36 } ] }, { "id": 72332, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "purple", "backgroundImageURL": "https://picsum.photos/seed/72332/600/400", "createdAt": "2023-10-08T20:12:12Z", @@ -7750,9 +6296,8 @@ "reactionCount": 84, "topReactions": [ { - "id": 34056, "emoji": "🎉", - "count": 9 + "count": 320 } ] }, @@ -7798,9 +6343,8 @@ "reactionCount": 86, "topReactions": [ { - "id": 11941, "emoji": "😀", - "count": 10 + "count": 371 } ] }, @@ -7815,10 +6359,10 @@ { "id": 47612, "recipientId": 6048, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/97/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 72", + "content": "Sowon Kim님의 메세지 내용 72", "font": "Pretendard", "createdAt": "2023-12-11T12:42:57Z" }, @@ -7846,24 +6390,8 @@ "reactionCount": 93, "topReactions": [ { - "id": 85562, - "emoji": "👍", - "count": 14 - }, - { - "id": 19775, - "emoji": "❤️", - "count": 4 - }, - { - "id": 97219, - "emoji": "❤️", - "count": 18 - }, - { - "id": 77812, "emoji": "🎉", - "count": 3 + "count": 177 } ] }, @@ -7888,10 +6416,10 @@ { "id": 54283, "recipientId": 7768, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/368/200/200", "relationship": "가족", - "content": "Suwon Kim님의 메세지 내용 8", + "content": "Sowon Kim님의 메세지 내용 8", "font": "Nanum Gothic", "createdAt": "2023-02-19T15:25:55Z" }, @@ -7909,9 +6437,8 @@ "reactionCount": 17, "topReactions": [ { - "id": 56016, "emoji": "😁", - "count": 7 + "count": 948 } ] }, @@ -7946,10 +6473,10 @@ { "id": 66344, "recipientId": 60032, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/444/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 47", + "content": "Sowon Kim님의 메세지 내용 47", "font": "Pretendard", "createdAt": "2023-07-26T07:54:55Z" } @@ -7957,9 +6484,8 @@ "reactionCount": 61, "topReactions": [ { - "id": 79749, "emoji": "😀", - "count": 11 + "count": 77 } ] }, @@ -7985,14 +6511,8 @@ "reactionCount": 58, "topReactions": [ { - "id": 15557, - "emoji": "❤️", - "count": 1 - }, - { - "id": 87847, "emoji": "❤️", - "count": 5 + "count": 740 } ] }, @@ -8018,29 +6538,8 @@ "reactionCount": 83, "topReactions": [ { - "id": 19026, "emoji": "🎉", - "count": 9 - }, - { - "id": 66458, - "emoji": "🥹", - "count": 18 - }, - { - "id": 39586, - "emoji": "❤️", - "count": 7 - }, - { - "id": 19251, - "emoji": "🥹", - "count": 17 - }, - { - "id": 4095, - "emoji": "🥹", - "count": 13 + "count": 116 } ] }, @@ -8086,29 +6585,12 @@ "reactionCount": 47, "topReactions": [ { - "id": 55806, "emoji": "😀", - "count": 9 + "count": 983 }, { - "id": 81344, - "emoji": "🎉", - "count": 20 - }, - { - "id": 23760, "emoji": "😁", - "count": 7 - }, - { - "id": 95115, - "emoji": "❤️", - "count": 10 - }, - { - "id": 62637, - "emoji": "😀", - "count": 2 + "count": 421 } ] }, @@ -8154,34 +6636,16 @@ "reactionCount": 15, "topReactions": [ { - "id": 12348, - "emoji": "🎉", - "count": 8 - }, - { - "id": 54843, - "emoji": "👍", - "count": 15 - }, - { - "id": 79979, - "emoji": "👍", - "count": 1 - }, - { - "id": 20768, - "emoji": "👍", - "count": 20 + "emoji": "❤️", + "count": 506 }, { - "id": 16109, - "emoji": "❤️", - "count": 1 + "emoji": "🎉", + "count": 735 }, { - "id": 10264, "emoji": "😁", - "count": 9 + "count": 370 } ] }, @@ -8207,24 +6671,12 @@ "reactionCount": 55, "topReactions": [ { - "id": 65130, - "emoji": "👍", - "count": 7 - }, - { - "id": 3875, - "emoji": "😁", - "count": 15 - }, - { - "id": 93476, "emoji": "❤️", - "count": 16 + "count": 368 }, { - "id": 22262, "emoji": "🥹", - "count": 2 + "count": 996 } ] }, @@ -8260,29 +6712,8 @@ "reactionCount": 80, "topReactions": [ { - "id": 90187, "emoji": "😀", - "count": 6 - }, - { - "id": 26989, - "emoji": "🥹", - "count": 8 - }, - { - "id": 80780, - "emoji": "🥹", - "count": 15 - }, - { - "id": 4359, - "emoji": "🎉", - "count": 15 - }, - { - "id": 25620, - "emoji": "👍", - "count": 10 + "count": 807 } ] }, @@ -8308,34 +6739,12 @@ "reactionCount": 4, "topReactions": [ { - "id": 71201, "emoji": "😀", - "count": 5 - }, - { - "id": 4897, - "emoji": "🥹", - "count": 4 + "count": 81 }, { - "id": 64978, "emoji": "😁", - "count": 12 - }, - { - "id": 69162, - "emoji": "🥹", - "count": 1 - }, - { - "id": 99414, - "emoji": "😀", - "count": 5 - }, - { - "id": 2807, - "emoji": "🥹", - "count": 7 + "count": 425 } ] }, @@ -8381,29 +6790,8 @@ "reactionCount": 23, "topReactions": [ { - "id": 7041, - "emoji": "😁", - "count": 6 - }, - { - "id": 19313, "emoji": "😀", - "count": 1 - }, - { - "id": 22714, - "emoji": "👍", - "count": 12 - }, - { - "id": 12076, - "emoji": "👍", - "count": 18 - }, - { - "id": 8583, - "emoji": "🎉", - "count": 5 + "count": 865 } ] }, @@ -8418,10 +6806,10 @@ { "id": 48175, "recipientId": 96506, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/145/200/200", "relationship": "동료", - "content": "Suwon Kim님의 메세지 내용 86", + "content": "Sowon Kim님의 메세지 내용 86", "font": "Pretendard", "createdAt": "2023-03-13T10:17:35Z" }, @@ -8449,29 +6837,8 @@ "reactionCount": 29, "topReactions": [ { - "id": 52114, - "emoji": "🥹", - "count": 8 - }, - { - "id": 93670, - "emoji": "🥹", - "count": 18 - }, - { - "id": 34535, "emoji": "🎉", - "count": 1 - }, - { - "id": 34032, - "emoji": "🥹", - "count": 3 - }, - { - "id": 24268, - "emoji": "😁", - "count": 2 + "count": 167 } ] }, @@ -8517,9 +6884,8 @@ "reactionCount": 10, "topReactions": [ { - "id": 34005, "emoji": "🎉", - "count": 7 + "count": 388 } ] }, @@ -8565,14 +6931,12 @@ "reactionCount": 45, "topReactions": [ { - "id": 30409, - "emoji": "🎉", - "count": 9 + "emoji": "👍", + "count": 253 }, { - "id": 96020, - "emoji": "👍", - "count": 19 + "emoji": "🎉", + "count": 611 } ] }, @@ -8607,10 +6971,10 @@ { "id": 11805, "recipientId": 10732, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/76/200/200", "relationship": "지인", - "content": "Suwon Kim님의 메세지 내용 48", + "content": "Sowon Kim님의 메세지 내용 48", "font": "Nanum Gothic", "createdAt": "2023-12-29T05:06:21Z" } @@ -8618,24 +6982,16 @@ "reactionCount": 45, "topReactions": [ { - "id": 75995, - "emoji": "🎉", - "count": 14 - }, - { - "id": 83468, "emoji": "👍", - "count": 6 + "count": 956 }, { - "id": 3826, "emoji": "🎉", - "count": 6 + "count": 702 }, { - "id": 53081, "emoji": "❤️", - "count": 14 + "count": 858 } ] }, @@ -8681,9 +7037,8 @@ "reactionCount": 99, "topReactions": [ { - "id": 22251, "emoji": "👍", - "count": 13 + "count": 359 } ] }, @@ -8708,10 +7063,10 @@ { "id": 94450, "recipientId": 64061, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/353/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 61", + "content": "Sowon Kim님의 메세지 내용 61", "font": "Pretendard", "createdAt": "2023-12-02T06:48:01Z" }, @@ -8729,15 +7084,14 @@ "reactionCount": 9, "topReactions": [ { - "id": 16899, "emoji": "🥹", - "count": 5 + "count": 658 } ] }, { "id": 15549, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "blue", "backgroundImageURL": null, "createdAt": "2023-12-13T10:07:11Z", @@ -8777,24 +7131,12 @@ "reactionCount": 72, "topReactions": [ { - "id": 71384, - "emoji": "👍", - "count": 8 - }, - { - "id": 23202, - "emoji": "👍", - "count": 19 + "emoji": "🥹", + "count": 585 }, { - "id": 98227, "emoji": "👍", - "count": 15 - }, - { - "id": 17552, - "emoji": "🥹", - "count": 14 + "count": 331 } ] }, @@ -8819,10 +7161,10 @@ { "id": 67124, "recipientId": 84213, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/482/200/200", "relationship": "가족", - "content": "Suwon Kim님의 메세지 내용 81", + "content": "Sowon Kim님의 메세지 내용 81", "font": "Pretendard", "createdAt": "2023-04-16T14:42:59Z" }, @@ -8840,34 +7182,8 @@ "reactionCount": 5, "topReactions": [ { - "id": 84810, - "emoji": "😀", - "count": 13 - }, - { - "id": 42243, - "emoji": "🥹", - "count": 6 - }, - { - "id": 63560, - "emoji": "👍", - "count": 10 - }, - { - "id": 6972, - "emoji": "🥹", - "count": 4 - }, - { - "id": 32485, "emoji": "😁", - "count": 1 - }, - { - "id": 29060, - "emoji": "😁", - "count": 10 + "count": 335 } ] }, @@ -8913,9 +7229,8 @@ "reactionCount": 0, "topReactions": [ { - "id": 99864, "emoji": "🥹", - "count": 11 + "count": 650 } ] }, @@ -8930,10 +7245,10 @@ { "id": 91701, "recipientId": 83558, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/169/200/200", "relationship": "지인", - "content": "Suwon Kim님의 메세지 내용 97", + "content": "Sowon Kim님의 메세지 내용 97", "font": "Noto Sans", "createdAt": "2023-11-22T09:50:03Z" }, @@ -8961,29 +7276,8 @@ "reactionCount": 95, "topReactions": [ { - "id": 4780, - "emoji": "😀", - "count": 11 - }, - { - "id": 36370, - "emoji": "👍", - "count": 15 - }, - { - "id": 857, - "emoji": "😁", - "count": 11 - }, - { - "id": 68373, "emoji": "😁", - "count": 17 - }, - { - "id": 86784, - "emoji": "❤️", - "count": 20 + "count": 794 } ] }, @@ -9029,24 +7323,16 @@ "reactionCount": 63, "topReactions": [ { - "id": 48182, "emoji": "😀", - "count": 16 + "count": 235 }, { - "id": 5086, - "emoji": "😀", - "count": 9 + "emoji": "🥹", + "count": 186 }, { - "id": 3495, "emoji": "❤️", - "count": 5 - }, - { - "id": 84837, - "emoji": "🥹", - "count": 6 + "count": 701 } ] }, @@ -9061,10 +7347,10 @@ { "id": 86215, "recipientId": 1220, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/419/200/200", "relationship": "가족", - "content": "Suwon Kim님의 메세지 내용 25", + "content": "Sowon Kim님의 메세지 내용 25", "font": "Pretendard", "createdAt": "2023-05-10T21:59:12Z" } @@ -9072,20 +7358,18 @@ "reactionCount": 14, "topReactions": [ { - "id": 11863, "emoji": "👍", - "count": 16 + "count": 865 }, { - "id": 36179, "emoji": "🎉", - "count": 18 + "count": 581 } ] }, { "id": 53959, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "blue", "backgroundImageURL": "https://picsum.photos/seed/53959/600/400", "createdAt": "2023-08-24T05:22:48Z", @@ -9114,10 +7398,10 @@ { "id": 59151, "recipientId": 53959, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/10/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 4", + "content": "Sowon Kim님의 메세지 내용 4", "font": "Nanum Gothic", "createdAt": "2023-03-11T07:04:18Z" } @@ -9125,34 +7409,8 @@ "reactionCount": 24, "topReactions": [ { - "id": 23239, - "emoji": "🥹", - "count": 6 - }, - { - "id": 8346, - "emoji": "😀", - "count": 3 - }, - { - "id": 10520, "emoji": "❤️", - "count": 9 - }, - { - "id": 92010, - "emoji": "😀", - "count": 9 - }, - { - "id": 33511, - "emoji": "🥹", - "count": 11 - }, - { - "id": 29961, - "emoji": "😀", - "count": 17 + "count": 91 } ] }, @@ -9198,25 +7456,22 @@ "reactionCount": 8, "topReactions": [ { - "id": 78078, - "emoji": "👍", - "count": 2 + "emoji": "❤️", + "count": 902 }, { - "id": 36649, "emoji": "🎉", - "count": 6 + "count": 548 }, { - "id": 92725, - "emoji": "❤️", - "count": 2 + "emoji": "👍", + "count": 583 } ] }, { "id": 51432, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "beige", "backgroundImageURL": "https://picsum.photos/seed/51432/600/400", "createdAt": "2023-11-07T07:07:37Z", @@ -9235,10 +7490,10 @@ { "id": 33808, "recipientId": 51432, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/478/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 8", + "content": "Sowon Kim님의 메세지 내용 8", "font": "Pretendard", "createdAt": "2023-04-04T10:06:15Z" }, @@ -9256,29 +7511,8 @@ "reactionCount": 12, "topReactions": [ { - "id": 45279, "emoji": "🥹", - "count": 4 - }, - { - "id": 59474, - "emoji": "👍", - "count": 11 - }, - { - "id": 61205, - "emoji": "👍", - "count": 20 - }, - { - "id": 69208, - "emoji": "😀", - "count": 11 - }, - { - "id": 47277, - "emoji": "🎉", - "count": 13 + "count": 545 } ] }, @@ -9324,9 +7558,8 @@ "reactionCount": 96, "topReactions": [ { - "id": 49415, "emoji": "😀", - "count": 16 + "count": 316 } ] }, @@ -9352,24 +7585,12 @@ "reactionCount": 61, "topReactions": [ { - "id": 78077, "emoji": "❤️", - "count": 15 + "count": 575 }, { - "id": 81214, "emoji": "🥹", - "count": 6 - }, - { - "id": 17360, - "emoji": "❤️", - "count": 19 - }, - { - "id": 21652, - "emoji": "🥹", - "count": 4 + "count": 192 } ] }, @@ -9415,9 +7636,8 @@ "reactionCount": 77, "topReactions": [ { - "id": 52469, "emoji": "❤️", - "count": 16 + "count": 653 } ] }, @@ -9463,9 +7683,8 @@ "reactionCount": 33, "topReactions": [ { - "id": 41010, "emoji": "🥹", - "count": 14 + "count": 740 } ] }, @@ -9511,29 +7730,8 @@ "reactionCount": 86, "topReactions": [ { - "id": 42848, "emoji": "🥹", - "count": 4 - }, - { - "id": 30829, - "emoji": "🎉", - "count": 5 - }, - { - "id": 89207, - "emoji": "😁", - "count": 11 - }, - { - "id": 82766, - "emoji": "😀", - "count": 7 - }, - { - "id": 95876, - "emoji": "🎉", - "count": 6 + "count": 229 } ] }, @@ -9577,36 +7775,10 @@ } ], "reactionCount": 43, - "topReactions": [ - { - "id": 70355, - "emoji": "🎉", - "count": 8 - }, - { - "id": 23001, - "emoji": "😁", - "count": 16 - }, - { - "id": 16865, - "emoji": "🎉", - "count": 20 - }, - { - "id": 85383, - "emoji": "👍", - "count": 1 - }, - { - "id": 62476, - "emoji": "👍", - "count": 2 - }, + "topReactions": [ { - "id": 25834, "emoji": "👍", - "count": 1 + "count": 632 } ] }, @@ -9642,19 +7814,12 @@ "reactionCount": 51, "topReactions": [ { - "id": 79191, - "emoji": "😀", - "count": 17 - }, - { - "id": 99981, "emoji": "😀", - "count": 7 + "count": 782 }, { - "id": 77927, "emoji": "🎉", - "count": 4 + "count": 968 } ] }, @@ -9700,24 +7865,8 @@ "reactionCount": 13, "topReactions": [ { - "id": 22643, "emoji": "👍", - "count": 19 - }, - { - "id": 77117, - "emoji": "😁", - "count": 8 - }, - { - "id": 35930, - "emoji": "❤️", - "count": 8 - }, - { - "id": 86858, - "emoji": "🎉", - "count": 16 + "count": 652 } ] }, @@ -9742,10 +7891,10 @@ { "id": 93059, "recipientId": 73798, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/252/200/200", "relationship": "지인", - "content": "Suwon Kim님의 메세지 내용 99", + "content": "Sowon Kim님의 메세지 내용 99", "font": "Roboto", "createdAt": "2023-11-21T09:01:45Z" }, @@ -9763,29 +7912,16 @@ "reactionCount": 71, "topReactions": [ { - "id": 31784, - "emoji": "😁", - "count": 6 + "emoji": "👍", + "count": 773 }, { - "id": 52139, - "emoji": "🥹", - "count": 7 + "emoji": "❤️", + "count": 613 }, { - "id": 20530, "emoji": "😁", - "count": 9 - }, - { - "id": 12585, - "emoji": "👍", - "count": 11 - }, - { - "id": 6677, - "emoji": "❤️", - "count": 6 + "count": 445 } ] }, @@ -9831,19 +7967,8 @@ "reactionCount": 53, "topReactions": [ { - "id": 16359, "emoji": "😁", - "count": 4 - }, - { - "id": 63702, - "emoji": "😁", - "count": 11 - }, - { - "id": 74672, - "emoji": "😁", - "count": 18 + "count": 353 } ] }, @@ -9868,10 +7993,10 @@ { "id": 33941, "recipientId": 3992, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/364/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 93", + "content": "Sowon Kim님의 메세지 내용 93", "font": "Pretendard", "createdAt": "2023-02-13T23:03:26Z" }, @@ -9889,9 +8014,8 @@ "reactionCount": 28, "topReactions": [ { - "id": 59388, "emoji": "🎉", - "count": 4 + "count": 814 } ] }, @@ -9937,9 +8061,8 @@ "reactionCount": 43, "topReactions": [ { - "id": 3962, "emoji": "🥹", - "count": 17 + "count": 963 } ] }, @@ -9964,10 +8087,10 @@ { "id": 89359, "recipientId": 63758, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/401/200/200", "relationship": "지인", - "content": "Suwon Kim님의 메세지 내용 53", + "content": "Sowon Kim님의 메세지 내용 53", "font": "Roboto", "createdAt": "2023-05-10T19:04:15Z" }, @@ -9985,9 +8108,8 @@ "reactionCount": 56, "topReactions": [ { - "id": 52289, "emoji": "😁", - "count": 7 + "count": 365 } ] }, @@ -10013,14 +8135,8 @@ "reactionCount": 69, "topReactions": [ { - "id": 75660, "emoji": "🥹", - "count": 13 - }, - { - "id": 30629, - "emoji": "❤️", - "count": 6 + "count": 764 } ] }, @@ -10066,25 +8182,18 @@ "reactionCount": 26, "topReactions": [ { - "id": 68634, "emoji": "👍", - "count": 16 - }, - { - "id": 74041, - "emoji": "🥹", - "count": 12 + "count": 606 }, { - "id": 834, "emoji": "🥹", - "count": 5 + "count": 965 } ] }, { "id": 63096, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "blue", "backgroundImageURL": "https://picsum.photos/seed/63096/600/400", "createdAt": "2023-08-25T09:30:08Z", @@ -10093,10 +8202,10 @@ { "id": 72995, "recipientId": 63096, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/368/200/200", "relationship": "동료", - "content": "Suwon Kim님의 메세지 내용 44", + "content": "Sowon Kim님의 메세지 내용 44", "font": "Pretendard", "createdAt": "2023-10-07T18:41:59Z" }, @@ -10124,19 +8233,12 @@ "reactionCount": 90, "topReactions": [ { - "id": 30117, "emoji": "🎉", - "count": 14 + "count": 568 }, { - "id": 52187, "emoji": "👍", - "count": 6 - }, - { - "id": 18011, - "emoji": "🎉", - "count": 17 + "count": 213 } ] }, @@ -10151,10 +8253,10 @@ { "id": 44494, "recipientId": 13289, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/118/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 64", + "content": "Sowon Kim님의 메세지 내용 64", "font": "Nanum Gothic", "createdAt": "2024-01-29T16:37:33Z" }, @@ -10182,34 +8284,8 @@ "reactionCount": 20, "topReactions": [ { - "id": 27582, - "emoji": "🥹", - "count": 5 - }, - { - "id": 7453, - "emoji": "😁", - "count": 15 - }, - { - "id": 32011, - "emoji": "🥹", - "count": 14 - }, - { - "id": 18525, - "emoji": "🎉", - "count": 8 - }, - { - "id": 15768, - "emoji": "😀", - "count": 19 - }, - { - "id": 14938, "emoji": "👍", - "count": 6 + "count": 94 } ] }, @@ -10255,34 +8331,8 @@ "reactionCount": 63, "topReactions": [ { - "id": 75593, - "emoji": "🎉", - "count": 17 - }, - { - "id": 86152, - "emoji": "👍", - "count": 18 - }, - { - "id": 94679, "emoji": "❤️", - "count": 19 - }, - { - "id": 93225, - "emoji": "😁", - "count": 3 - }, - { - "id": 50484, - "emoji": "🎉", - "count": 9 - }, - { - "id": 97858, - "emoji": "👍", - "count": 2 + "count": 448 } ] }, @@ -10328,14 +8378,12 @@ "reactionCount": 98, "topReactions": [ { - "id": 11291, - "emoji": "🥹", - "count": 9 + "emoji": "😀", + "count": 985 }, { - "id": 71787, - "emoji": "😀", - "count": 19 + "emoji": "🥹", + "count": 609 } ] }, @@ -10381,24 +8429,12 @@ "reactionCount": 69, "topReactions": [ { - "id": 29485, - "emoji": "😁", - "count": 16 - }, - { - "id": 51258, - "emoji": "😁", - "count": 14 + "emoji": "😀", + "count": 737 }, { - "id": 24027, "emoji": "😁", - "count": 18 - }, - { - "id": 86629, - "emoji": "😀", - "count": 4 + "count": 298 } ] }, @@ -10424,29 +8460,12 @@ "reactionCount": 52, "topReactions": [ { - "id": 78028, - "emoji": "👍", - "count": 7 - }, - { - "id": 81658, - "emoji": "👍", - "count": 8 - }, - { - "id": 99396, - "emoji": "❤️", - "count": 1 - }, - { - "id": 91845, "emoji": "🎉", - "count": 4 + "count": 679 }, { - "id": 95208, "emoji": "👍", - "count": 5 + "count": 166 } ] }, @@ -10482,24 +8501,12 @@ "reactionCount": 55, "topReactions": [ { - "id": 63963, - "emoji": "😀", - "count": 11 - }, - { - "id": 26888, - "emoji": "😀", - "count": 14 + "emoji": "❤️", + "count": 828 }, { - "id": 5147, "emoji": "😁", - "count": 15 - }, - { - "id": 47112, - "emoji": "❤️", - "count": 7 + "count": 960 } ] }, @@ -10534,10 +8541,10 @@ { "id": 33150, "recipientId": 66190, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/26/200/200", "relationship": "지인", - "content": "Suwon Kim님의 메세지 내용 47", + "content": "Sowon Kim님의 메세지 내용 47", "font": "Roboto", "createdAt": "2024-01-22T00:03:15Z" } @@ -10545,20 +8552,18 @@ "reactionCount": 29, "topReactions": [ { - "id": 30808, - "emoji": "🥹", - "count": 20 + "emoji": "😀", + "count": 142 }, { - "id": 18642, - "emoji": "😀", - "count": 9 + "emoji": "🥹", + "count": 226 } ] }, { "id": 68635, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "beige", "backgroundImageURL": null, "createdAt": "2023-10-22T10:14:45Z", @@ -10598,19 +8603,8 @@ "reactionCount": 18, "topReactions": [ { - "id": 98726, - "emoji": "😀", - "count": 15 - }, - { - "id": 65169, - "emoji": "🥹", - "count": 3 - }, - { - "id": 8481, "emoji": "🥹", - "count": 12 + "count": 536 } ] }, @@ -10625,10 +8619,10 @@ { "id": 8378, "recipientId": 52236, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/383/200/200", "relationship": "동료", - "content": "Suwon Kim님의 메세지 내용 53", + "content": "Sowon Kim님의 메세지 내용 53", "font": "Pretendard", "createdAt": "2023-12-03T19:03:51Z" } @@ -10636,9 +8630,8 @@ "reactionCount": 48, "topReactions": [ { - "id": 89637, "emoji": "😀", - "count": 8 + "count": 914 } ] }, @@ -10663,10 +8656,10 @@ { "id": 14027, "recipientId": 81115, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/400/200/200", "relationship": "가족", - "content": "Suwon Kim님의 메세지 내용 48", + "content": "Sowon Kim님의 메세지 내용 48", "font": "Noto Sans", "createdAt": "2023-09-18T14:09:01Z" }, @@ -10684,9 +8677,8 @@ "reactionCount": 93, "topReactions": [ { - "id": 89132, "emoji": "🎉", - "count": 18 + "count": 633 } ] }, @@ -10732,9 +8724,8 @@ "reactionCount": 93, "topReactions": [ { - "id": 21925, "emoji": "😀", - "count": 4 + "count": 623 } ] }, @@ -10780,9 +8771,8 @@ "reactionCount": 10, "topReactions": [ { - "id": 71407, "emoji": "😁", - "count": 11 + "count": 349 } ] }, @@ -10828,29 +8818,16 @@ "reactionCount": 30, "topReactions": [ { - "id": 45061, - "emoji": "❤️", - "count": 20 - }, - { - "id": 40818, "emoji": "❤️", - "count": 20 - }, - { - "id": 86400, - "emoji": "🥹", - "count": 3 + "count": 425 }, { - "id": 90349, "emoji": "🥹", - "count": 1 + "count": 131 }, { - "id": 307, "emoji": "😁", - "count": 9 + "count": 242 } ] }, @@ -10885,10 +8862,10 @@ { "id": 16314, "recipientId": 60, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/345/200/200", "relationship": "동료", - "content": "Suwon Kim님의 메세지 내용 52", + "content": "Sowon Kim님의 메세지 내용 52", "font": "Roboto", "createdAt": "2023-03-07T04:55:33Z" } @@ -10896,14 +8873,12 @@ "reactionCount": 50, "topReactions": [ { - "id": 58906, - "emoji": "😀", - "count": 1 + "emoji": "🎉", + "count": 814 }, { - "id": 50471, - "emoji": "🎉", - "count": 7 + "emoji": "😀", + "count": 481 } ] }, @@ -10928,10 +8903,10 @@ { "id": 81467, "recipientId": 66554, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/487/200/200", "relationship": "가족", - "content": "Suwon Kim님의 메세지 내용 17", + "content": "Sowon Kim님의 메세지 내용 17", "font": "Nanum Gothic", "createdAt": "2023-03-16T05:19:39Z" }, @@ -10949,24 +8924,16 @@ "reactionCount": 78, "topReactions": [ { - "id": 11998, - "emoji": "😀", - "count": 1 - }, - { - "id": 43630, - "emoji": "❤️", - "count": 5 + "emoji": "😁", + "count": 632 }, { - "id": 4909, "emoji": "🥹", - "count": 10 + "count": 377 }, { - "id": 15023, - "emoji": "😁", - "count": 4 + "emoji": "😀", + "count": 581 } ] }, @@ -10992,7 +8959,7 @@ "id": 19330, "recipientId": 50312, "sender": "전지현", - "profileImageURL": "https://picsum.photos/id/435/200/200", + "profileImageURL": "https://picsum.photos/id/51/200/200", "relationship": "가족", "content": "전지현님의 메세지 내용 14", "font": "Pretendard", @@ -11012,14 +8979,12 @@ "reactionCount": 97, "topReactions": [ { - "id": 73411, - "emoji": "❤️", - "count": 14 + "emoji": "🥹", + "count": 281 }, { - "id": 26879, - "emoji": "🥹", - "count": 9 + "emoji": "❤️", + "count": 265 } ] }, @@ -11045,34 +9010,8 @@ "reactionCount": 41, "topReactions": [ { - "id": 69423, - "emoji": "🥹", - "count": 19 - }, - { - "id": 37533, - "emoji": "🎉", - "count": 10 - }, - { - "id": 73552, - "emoji": "😁", - "count": 5 - }, - { - "id": 58186, "emoji": "🥹", - "count": 8 - }, - { - "id": 26741, - "emoji": "😁", - "count": 18 - }, - { - "id": 8330, - "emoji": "❤️", - "count": 6 + "count": 974 } ] }, @@ -11108,19 +9047,8 @@ "reactionCount": 35, "topReactions": [ { - "id": 44310, - "emoji": "🥹", - "count": 4 - }, - { - "id": 10011, "emoji": "❤️", - "count": 6 - }, - { - "id": 8641, - "emoji": "🥹", - "count": 4 + "count": 900 } ] }, @@ -11155,10 +9083,10 @@ { "id": 19962, "recipientId": 31459, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/80/200/200", "relationship": "동료", - "content": "Suwon Kim님의 메세지 내용 11", + "content": "Sowon Kim님의 메세지 내용 11", "font": "Nanum Gothic", "createdAt": "2023-11-26T04:31:20Z" } @@ -11166,9 +9094,8 @@ "reactionCount": 21, "topReactions": [ { - "id": 4005, "emoji": "😀", - "count": 7 + "count": 783 } ] }, @@ -11214,34 +9141,12 @@ "reactionCount": 5, "topReactions": [ { - "id": 5588, - "emoji": "❤️", - "count": 5 - }, - { - "id": 98400, - "emoji": "🥹", - "count": 13 - }, - { - "id": 5484, - "emoji": "❤️", - "count": 16 - }, - { - "id": 40058, "emoji": "🎉", - "count": 2 + "count": 275 }, { - "id": 51056, "emoji": "👍", - "count": 14 - }, - { - "id": 31995, - "emoji": "🎉", - "count": 12 + "count": 76 } ] }, @@ -11287,34 +9192,8 @@ "reactionCount": 6, "topReactions": [ { - "id": 51742, - "emoji": "🥹", - "count": 6 - }, - { - "id": 48690, - "emoji": "🎉", - "count": 2 - }, - { - "id": 50705, - "emoji": "😀", - "count": 14 - }, - { - "id": 8991, - "emoji": "😀", - "count": 10 - }, - { - "id": 12174, - "emoji": "🥹", - "count": 9 - }, - { - "id": 10137, "emoji": "😀", - "count": 10 + "count": 604 } ] }, @@ -11360,24 +9239,12 @@ "reactionCount": 90, "topReactions": [ { - "id": 16362, - "emoji": "😁", - "count": 14 - }, - { - "id": 6576, - "emoji": "🥹", - "count": 14 - }, - { - "id": 78222, "emoji": "🎉", - "count": 1 + "count": 657 }, { - "id": 62128, - "emoji": "😁", - "count": 18 + "emoji": "🥹", + "count": 298 } ] }, @@ -11402,10 +9269,10 @@ { "id": 24156, "recipientId": 41885, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/360/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 14", + "content": "Sowon Kim님의 메세지 내용 14", "font": "Noto Sans", "createdAt": "2023-07-13T21:35:18Z" }, @@ -11423,24 +9290,16 @@ "reactionCount": 9, "topReactions": [ { - "id": 31604, "emoji": "😀", - "count": 15 + "count": 646 }, { - "id": 7967, "emoji": "😁", - "count": 2 + "count": 786 }, { - "id": 52857, "emoji": "🥹", - "count": 14 - }, - { - "id": 52766, - "emoji": "😀", - "count": 13 + "count": 677 } ] }, @@ -11486,24 +9345,12 @@ "reactionCount": 21, "topReactions": [ { - "id": 13179, - "emoji": "🎉", - "count": 3 - }, - { - "id": 5003, - "emoji": "🥹", - "count": 1 - }, - { - "id": 37584, "emoji": "🥹", - "count": 4 + "count": 11 }, { - "id": 63440, "emoji": "🎉", - "count": 4 + "count": 646 } ] }, @@ -11522,36 +9369,15 @@ "profileImageURL": "https://picsum.photos/id/3/200/200", "relationship": "지인", "content": "이영준님의 메세지 내용 13", - "font": "Noto Sans", - "createdAt": "2023-01-18T07:30:08Z" - } - ], - "reactionCount": 37, - "topReactions": [ - { - "id": 1985, - "emoji": "👍", - "count": 9 - }, - { - "id": 65556, - "emoji": "❤️", - "count": 7 - }, - { - "id": 96682, - "emoji": "😁", - "count": 9 - }, - { - "id": 49044, - "emoji": "🎉", - "count": 13 - }, + "font": "Noto Sans", + "createdAt": "2023-01-18T07:30:08Z" + } + ], + "reactionCount": 37, + "topReactions": [ { - "id": 76158, "emoji": "❤️", - "count": 7 + "count": 725 } ] }, @@ -11577,34 +9403,12 @@ "reactionCount": 33, "topReactions": [ { - "id": 38198, "emoji": "😁", - "count": 5 - }, - { - "id": 75156, - "emoji": "🥹", - "count": 11 - }, - { - "id": 85523, - "emoji": "🥹", - "count": 4 + "count": 236 }, { - "id": 68198, "emoji": "🎉", - "count": 5 - }, - { - "id": 91, - "emoji": "😁", - "count": 9 - }, - { - "id": 249, - "emoji": "😀", - "count": 4 + "count": 36 } ] }, @@ -11640,29 +9444,16 @@ "reactionCount": 28, "topReactions": [ { - "id": 13204, "emoji": "😀", - "count": 13 + "count": 842 }, { - "id": 16155, "emoji": "🎉", - "count": 19 - }, - { - "id": 68608, - "emoji": "😀", - "count": 18 + "count": 398 }, { - "id": 78848, - "emoji": "😀", - "count": 18 - }, - { - "id": 4799, "emoji": "👍", - "count": 12 + "count": 585 } ] }, @@ -11708,9 +9499,8 @@ "reactionCount": 100, "topReactions": [ { - "id": 72646, "emoji": "❤️", - "count": 5 + "count": 622 } ] }, @@ -11756,14 +9546,8 @@ "reactionCount": 72, "topReactions": [ { - "id": 37949, - "emoji": "❤️", - "count": 10 - }, - { - "id": 46408, "emoji": "😀", - "count": 1 + "count": 809 } ] }, @@ -11799,9 +9583,8 @@ "reactionCount": 100, "topReactions": [ { - "id": 51363, "emoji": "😀", - "count": 9 + "count": 98 } ] }, @@ -11816,20 +9599,20 @@ { "id": 86564, "recipientId": 46642, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/36/200/200", "relationship": "지인", - "content": "Suwon Kim님의 메세지 내용 78", + "content": "Sowon Kim님의 메세지 내용 78", "font": "Noto Sans", "createdAt": "2023-09-23T23:48:17Z" }, { "id": 46880, "recipientId": 46642, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/453/200/200", "relationship": "가족", - "content": "Suwon Kim님의 메세지 내용 92", + "content": "Sowon Kim님의 메세지 내용 92", "font": "Noto Sans", "createdAt": "2023-06-07T09:44:08Z" }, @@ -11847,34 +9630,12 @@ "reactionCount": 24, "topReactions": [ { - "id": 50493, - "emoji": "🥹", - "count": 10 - }, - { - "id": 14174, "emoji": "❤️", - "count": 7 - }, - { - "id": 8164, - "emoji": "😀", - "count": 14 + "count": 839 }, { - "id": 59391, "emoji": "😁", - "count": 12 - }, - { - "id": 503, - "emoji": "❤️", - "count": 14 - }, - { - "id": 96571, - "emoji": "❤️", - "count": 7 + "count": 258 } ] }, @@ -11920,15 +9681,14 @@ "reactionCount": 93, "topReactions": [ { - "id": 90352, "emoji": "😁", - "count": 1 + "count": 90 } ] }, { "id": 93469, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "beige", "backgroundImageURL": "https://picsum.photos/seed/93469/600/400", "createdAt": "2023-08-05T08:37:01Z", @@ -11968,30 +9728,22 @@ "reactionCount": 84, "topReactions": [ { - "id": 89622, - "emoji": "🎉", - "count": 13 + "emoji": "😀", + "count": 442 }, { - "id": 63069, "emoji": "🎉", - "count": 4 - }, - { - "id": 24110, - "emoji": "😀", - "count": 4 + "count": 682 }, { - "id": 67263, "emoji": "👍", - "count": 12 + "count": 278 } ] }, { "id": 45950, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "green", "backgroundImageURL": "https://picsum.photos/seed/45950/600/400", "createdAt": "2023-04-24T21:39:46Z", @@ -12031,9 +9783,8 @@ "reactionCount": 45, "topReactions": [ { - "id": 39540, "emoji": "🎉", - "count": 13 + "count": 775 } ] }, @@ -12079,19 +9830,8 @@ "reactionCount": 84, "topReactions": [ { - "id": 12098, - "emoji": "👍", - "count": 9 - }, - { - "id": 54057, "emoji": "😀", - "count": 9 - }, - { - "id": 45620, - "emoji": "👍", - "count": 3 + "count": 792 } ] }, @@ -12137,34 +9877,16 @@ "reactionCount": 72, "topReactions": [ { - "id": 76463, - "emoji": "😁", - "count": 15 + "emoji": "👍", + "count": 829 }, { - "id": 25167, "emoji": "🎉", - "count": 19 + "count": 814 }, { - "id": 5479, - "emoji": "🥹", - "count": 2 - }, - { - "id": 92981, - "emoji": "😀", - "count": 17 - }, - { - "id": 85208, "emoji": "😁", - "count": 10 - }, - { - "id": 61758, - "emoji": "👍", - "count": 8 + "count": 369 } ] }, @@ -12210,24 +9932,16 @@ "reactionCount": 70, "topReactions": [ { - "id": 11095, - "emoji": "😁", - "count": 1 + "emoji": "🥹", + "count": 765 }, { - "id": 76832, "emoji": "👍", - "count": 1 - }, - { - "id": 65012, - "emoji": "🥹", - "count": 7 + "count": 288 }, { - "id": 65074, - "emoji": "🎉", - "count": 2 + "emoji": "😁", + "count": 492 } ] }, @@ -12273,14 +9987,8 @@ "reactionCount": 34, "topReactions": [ { - "id": 17825, - "emoji": "🎉", - "count": 10 - }, - { - "id": 85431, "emoji": "❤️", - "count": 1 + "count": 561 } ] }, @@ -12326,14 +10034,12 @@ "reactionCount": 4, "topReactions": [ { - "id": 50561, - "emoji": "❤️", - "count": 15 + "emoji": "🎉", + "count": 678 }, { - "id": 80082, - "emoji": "🎉", - "count": 18 + "emoji": "❤️", + "count": 792 } ] }, @@ -12379,34 +10085,16 @@ "reactionCount": 41, "topReactions": [ { - "id": 26308, - "emoji": "🥹", - "count": 6 - }, - { - "id": 63793, "emoji": "👍", - "count": 11 + "count": 843 }, { - "id": 52541, - "emoji": "🎉", - "count": 4 - }, - { - "id": 83299, "emoji": "😀", - "count": 9 - }, - { - "id": 85136, - "emoji": "🥹", - "count": 7 + "count": 155 }, { - "id": 889, - "emoji": "👍", - "count": 7 + "emoji": "🎉", + "count": 16 } ] }, @@ -12452,29 +10140,8 @@ "reactionCount": 70, "topReactions": [ { - "id": 40083, "emoji": "👍", - "count": 5 - }, - { - "id": 46868, - "emoji": "😀", - "count": 4 - }, - { - "id": 9028, - "emoji": "😀", - "count": 12 - }, - { - "id": 33264, - "emoji": "😁", - "count": 2 - }, - { - "id": 5936, - "emoji": "❤️", - "count": 13 + "count": 89 } ] }, @@ -12489,10 +10156,10 @@ { "id": 46241, "recipientId": 30047, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/397/200/200", "relationship": "동료", - "content": "Suwon Kim님의 메세지 내용 64", + "content": "Sowon Kim님의 메세지 내용 64", "font": "Roboto", "createdAt": "2023-04-12T04:50:45Z" }, @@ -12520,34 +10187,16 @@ "reactionCount": 55, "topReactions": [ { - "id": 35861, "emoji": "👍", - "count": 20 + "count": 865 }, { - "id": 3537, "emoji": "🎉", - "count": 19 - }, - { - "id": 95822, - "emoji": "😀", - "count": 11 - }, - { - "id": 70453, - "emoji": "❤️", - "count": 10 - }, - { - "id": 12985, - "emoji": "🥹", - "count": 18 + "count": 993 }, { - "id": 22095, "emoji": "😀", - "count": 1 + "count": 755 } ] }, @@ -12593,14 +10242,8 @@ "reactionCount": 96, "topReactions": [ { - "id": 55075, "emoji": "❤️", - "count": 3 - }, - { - "id": 35577, - "emoji": "🎉", - "count": 19 + "count": 196 } ] }, @@ -12646,24 +10289,12 @@ "reactionCount": 43, "topReactions": [ { - "id": 5861, - "emoji": "🎉", - "count": 13 - }, - { - "id": 44343, "emoji": "🥹", - "count": 12 - }, - { - "id": 43982, - "emoji": "🎉", - "count": 14 + "count": 112 }, { - "id": 4963, "emoji": "🎉", - "count": 6 + "count": 135 } ] }, @@ -12689,19 +10320,8 @@ "reactionCount": 71, "topReactions": [ { - "id": 99348, "emoji": "😁", - "count": 10 - }, - { - "id": 52447, - "emoji": "🎉", - "count": 19 - }, - { - "id": 16678, - "emoji": "😁", - "count": 1 + "count": 72 } ] }, @@ -12747,29 +10367,16 @@ "reactionCount": 32, "topReactions": [ { - "id": 20504, "emoji": "🥹", - "count": 16 - }, - { - "id": 54171, - "emoji": "😁", - "count": 12 - }, - { - "id": 73446, - "emoji": "😁", - "count": 6 + "count": 111 }, { - "id": 11616, "emoji": "🎉", - "count": 7 + "count": 859 }, { - "id": 95136, - "emoji": "🥹", - "count": 5 + "emoji": "😁", + "count": 919 } ] }, @@ -12815,25 +10422,18 @@ "reactionCount": 31, "topReactions": [ { - "id": 57710, - "emoji": "😀", - "count": 2 - }, - { - "id": 8909, "emoji": "🥹", - "count": 2 + "count": 814 }, { - "id": 28098, - "emoji": "🥹", - "count": 9 + "emoji": "😀", + "count": 701 } ] }, { "id": 44091, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "blue", "backgroundImageURL": "https://picsum.photos/seed/44091/600/400", "createdAt": "2023-06-17T19:51:45Z", @@ -12873,9 +10473,8 @@ "reactionCount": 73, "topReactions": [ { - "id": 53118, "emoji": "😁", - "count": 1 + "count": 832 } ] }, @@ -12921,24 +10520,8 @@ "reactionCount": 70, "topReactions": [ { - "id": 60136, - "emoji": "😀", - "count": 7 - }, - { - "id": 45903, - "emoji": "🥹", - "count": 17 - }, - { - "id": 38212, - "emoji": "😀", - "count": 18 - }, - { - "id": 59414, "emoji": "🥹", - "count": 5 + "count": 962 } ] }, @@ -12984,29 +10567,8 @@ "reactionCount": 9, "topReactions": [ { - "id": 19392, - "emoji": "😁", - "count": 18 - }, - { - "id": 13700, - "emoji": "❤️", - "count": 12 - }, - { - "id": 50701, "emoji": "😁", - "count": 6 - }, - { - "id": 28314, - "emoji": "❤️", - "count": 15 - }, - { - "id": 65318, - "emoji": "🥹", - "count": 19 + "count": 212 } ] }, @@ -13052,9 +10614,8 @@ "reactionCount": 43, "topReactions": [ { - "id": 38169, "emoji": "🥹", - "count": 6 + "count": 948 } ] }, @@ -13080,24 +10641,16 @@ "reactionCount": 36, "topReactions": [ { - "id": 51242, - "emoji": "👍", - "count": 3 - }, - { - "id": 23565, "emoji": "❤️", - "count": 8 + "count": 705 }, { - "id": 37031, "emoji": "🥹", - "count": 17 + "count": 173 }, { - "id": 78779, - "emoji": "❤️", - "count": 9 + "emoji": "👍", + "count": 137 } ] }, @@ -13143,29 +10696,12 @@ "reactionCount": 31, "topReactions": [ { - "id": 50319, - "emoji": "😁", - "count": 20 - }, - { - "id": 44923, "emoji": "🥹", - "count": 16 - }, - { - "id": 54729, - "emoji": "👍", - "count": 1 - }, - { - "id": 82072, - "emoji": "🎉", - "count": 11 + "count": 10 }, { - "id": 10911, "emoji": "😁", - "count": 2 + "count": 714 } ] }, @@ -13211,19 +10747,8 @@ "reactionCount": 48, "topReactions": [ { - "id": 55639, "emoji": "😁", - "count": 2 - }, - { - "id": 98809, - "emoji": "❤️", - "count": 2 - }, - { - "id": 69046, - "emoji": "👍", - "count": 2 + "count": 901 } ] }, @@ -13269,9 +10794,8 @@ "reactionCount": 100, "topReactions": [ { - "id": 4687, "emoji": "❤️", - "count": 9 + "count": 726 } ] }, @@ -13317,14 +10841,12 @@ "reactionCount": 54, "topReactions": [ { - "id": 5609, - "emoji": "🎉", - "count": 3 + "emoji": "😁", + "count": 818 }, { - "id": 93922, - "emoji": "😁", - "count": 19 + "emoji": "🎉", + "count": 315 } ] }, @@ -13349,10 +10871,10 @@ { "id": 58525, "recipientId": 62965, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/103/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 1", + "content": "Sowon Kim님의 메세지 내용 1", "font": "Noto Sans", "createdAt": "2023-04-24T14:22:46Z" }, @@ -13370,9 +10892,8 @@ "reactionCount": 74, "topReactions": [ { - "id": 29181, "emoji": "😁", - "count": 2 + "count": 95 } ] }, @@ -13387,10 +10908,10 @@ { "id": 86114, "recipientId": 61614, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/1/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 48", + "content": "Sowon Kim님의 메세지 내용 48", "font": "Noto Sans", "createdAt": "2023-11-16T04:24:55Z" }, @@ -13418,19 +10939,8 @@ "reactionCount": 43, "topReactions": [ { - "id": 96270, - "emoji": "😁", - "count": 8 - }, - { - "id": 86470, "emoji": "👍", - "count": 20 - }, - { - "id": 73582, - "emoji": "😁", - "count": 18 + "count": 658 } ] }, @@ -13476,25 +10986,18 @@ "reactionCount": 59, "topReactions": [ { - "id": 10874, "emoji": "❤️", - "count": 20 - }, - { - "id": 9648, - "emoji": "🥹", - "count": 8 + "count": 950 }, { - "id": 90543, "emoji": "👍", - "count": 3 + "count": 704 } ] }, { "id": 31146, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "green", "backgroundImageURL": null, "createdAt": "2023-09-27T13:42:38Z", @@ -13509,34 +11012,13 @@ "content": "한지민님의 메세지 내용 1", "font": "Pretendard", "createdAt": "2024-01-20T10:25:39Z" - } - ], - "reactionCount": 88, - "topReactions": [ - { - "id": 90630, - "emoji": "🥹", - "count": 8 - }, - { - "id": 31427, - "emoji": "🎉", - "count": 13 - }, - { - "id": 40617, - "emoji": "🎉", - "count": 19 - }, - { - "id": 21215, - "emoji": "🎉", - "count": 1 - }, + } + ], + "reactionCount": 88, + "topReactions": [ { - "id": 10418, - "emoji": "😀", - "count": 10 + "emoji": "🥹", + "count": 136 } ] }, @@ -13551,10 +11033,10 @@ { "id": 80875, "recipientId": 99123, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/42/200/200", "relationship": "동료", - "content": "Suwon Kim님의 메세지 내용 14", + "content": "Sowon Kim님의 메세지 내용 14", "font": "Roboto", "createdAt": "2023-11-30T19:44:40Z" }, @@ -13582,14 +11064,12 @@ "reactionCount": 80, "topReactions": [ { - "id": 24281, "emoji": "😁", - "count": 12 + "count": 347 }, { - "id": 56612, "emoji": "❤️", - "count": 8 + "count": 766 } ] }, @@ -13635,19 +11115,16 @@ "reactionCount": 83, "topReactions": [ { - "id": 41395, "emoji": "❤️", - "count": 3 + "count": 886 }, { - "id": 71463, "emoji": "😁", - "count": 14 + "count": 199 }, { - "id": 43684, "emoji": "🎉", - "count": 20 + "count": 734 } ] }, @@ -13682,10 +11159,10 @@ { "id": 9237, "recipientId": 16143, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/437/200/200", "relationship": "지인", - "content": "Suwon Kim님의 메세지 내용 14", + "content": "Sowon Kim님의 메세지 내용 14", "font": "Pretendard", "createdAt": "2023-03-17T21:44:08Z" } @@ -13693,24 +11170,8 @@ "reactionCount": 77, "topReactions": [ { - "id": 18467, "emoji": "👍", - "count": 17 - }, - { - "id": 28382, - "emoji": "😀", - "count": 1 - }, - { - "id": 94572, - "emoji": "❤️", - "count": 1 - }, - { - "id": 63127, - "emoji": "🥹", - "count": 16 + "count": 219 } ] }, @@ -13756,9 +11217,8 @@ "reactionCount": 61, "topReactions": [ { - "id": 99369, "emoji": "👍", - "count": 6 + "count": 974 } ] }, @@ -13793,10 +11253,10 @@ { "id": 31892, "recipientId": 98422, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/8/200/200", "relationship": "지인", - "content": "Suwon Kim님의 메세지 내용 43", + "content": "Sowon Kim님의 메세지 내용 43", "font": "Pretendard", "createdAt": "2023-09-02T03:23:20Z" } @@ -13804,19 +11264,12 @@ "reactionCount": 6, "topReactions": [ { - "id": 99679, - "emoji": "👍", - "count": 1 + "emoji": "😀", + "count": 838 }, { - "id": 42127, "emoji": "👍", - "count": 20 - }, - { - "id": 49549, - "emoji": "😀", - "count": 5 + "count": 490 } ] }, @@ -13841,10 +11294,10 @@ { "id": 85445, "recipientId": 53532, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/363/200/200", "relationship": "지인", - "content": "Suwon Kim님의 메세지 내용 51", + "content": "Sowon Kim님의 메세지 내용 51", "font": "Noto Sans", "createdAt": "2023-09-23T11:29:56Z" }, @@ -13862,34 +11315,8 @@ "reactionCount": 59, "topReactions": [ { - "id": 23496, - "emoji": "❤️", - "count": 18 - }, - { - "id": 81866, - "emoji": "👍", - "count": 10 - }, - { - "id": 17757, - "emoji": "🥹", - "count": 10 - }, - { - "id": 39750, - "emoji": "🥹", - "count": 16 - }, - { - "id": 24933, "emoji": "😁", - "count": 12 - }, - { - "id": 26409, - "emoji": "❤️", - "count": 19 + "count": 349 } ] }, @@ -13904,10 +11331,10 @@ { "id": 86518, "recipientId": 93792, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/204/200/200", "relationship": "지인", - "content": "Suwon Kim님의 메세지 내용 9", + "content": "Sowon Kim님의 메세지 내용 9", "font": "Roboto", "createdAt": "2023-01-22T13:44:09Z" }, @@ -13924,10 +11351,10 @@ { "id": 9752, "recipientId": 93792, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/171/200/200", "relationship": "동료", - "content": "Suwon Kim님의 메세지 내용 68", + "content": "Sowon Kim님의 메세지 내용 68", "font": "Roboto", "createdAt": "2023-02-15T23:39:35Z" } @@ -13935,29 +11362,16 @@ "reactionCount": 52, "topReactions": [ { - "id": 4867, - "emoji": "❤️", - "count": 19 - }, - { - "id": 39233, "emoji": "🥹", - "count": 20 - }, - { - "id": 20026, - "emoji": "❤️", - "count": 19 + "count": 325 }, { - "id": 72595, "emoji": "👍", - "count": 13 + "count": 579 }, { - "id": 13775, - "emoji": "🥹", - "count": 17 + "emoji": "❤️", + "count": 675 } ] }, @@ -13992,10 +11406,10 @@ { "id": 84648, "recipientId": 12242, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/112/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 4", + "content": "Sowon Kim님의 메세지 내용 4", "font": "Pretendard", "createdAt": "2024-01-06T11:37:10Z" } @@ -14003,34 +11417,16 @@ "reactionCount": 61, "topReactions": [ { - "id": 84557, - "emoji": "😀", - "count": 20 + "emoji": "❤️", + "count": 47 }, { - "id": 77673, "emoji": "😀", - "count": 12 + "count": 589 }, { - "id": 99493, - "emoji": "❤️", - "count": 13 - }, - { - "id": 67646, "emoji": "🥹", - "count": 4 - }, - { - "id": 54419, - "emoji": "❤️", - "count": 12 - }, - { - "id": 2038, - "emoji": "🎉", - "count": 1 + "count": 840 } ] }, @@ -14066,14 +11462,12 @@ "reactionCount": 31, "topReactions": [ { - "id": 72384, "emoji": "🎉", - "count": 10 + "count": 687 }, { - "id": 24751, "emoji": "👍", - "count": 2 + "count": 355 } ] }, @@ -14098,10 +11492,10 @@ { "id": 35816, "recipientId": 76148, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/488/200/200", "relationship": "가족", - "content": "Suwon Kim님의 메세지 내용 96", + "content": "Sowon Kim님의 메세지 내용 96", "font": "Nanum Gothic", "createdAt": "2023-04-09T14:21:56Z" } @@ -14109,24 +11503,8 @@ "reactionCount": 3, "topReactions": [ { - "id": 24742, "emoji": "🥹", - "count": 11 - }, - { - "id": 31827, - "emoji": "👍", - "count": 6 - }, - { - "id": 12947, - "emoji": "🎉", - "count": 5 - }, - { - "id": 40799, - "emoji": "🎉", - "count": 3 + "count": 231 } ] }, @@ -14162,9 +11540,8 @@ "reactionCount": 50, "topReactions": [ { - "id": 99751, "emoji": "❤️", - "count": 16 + "count": 267 } ] }, @@ -14179,10 +11556,10 @@ { "id": 76780, "recipientId": 38642, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/253/200/200", "relationship": "가족", - "content": "Suwon Kim님의 메세지 내용 24", + "content": "Sowon Kim님의 메세지 내용 24", "font": "Nanum Gothic", "createdAt": "2023-07-12T11:54:03Z" }, @@ -14210,24 +11587,8 @@ "reactionCount": 29, "topReactions": [ { - "id": 96587, - "emoji": "😁", - "count": 16 - }, - { - "id": 33006, "emoji": "🎉", - "count": 8 - }, - { - "id": 4665, - "emoji": "🎉", - "count": 3 - }, - { - "id": 6761, - "emoji": "😀", - "count": 7 + "count": 48 } ] }, @@ -14263,9 +11624,8 @@ "reactionCount": 29, "topReactions": [ { - "id": 85255, "emoji": "😀", - "count": 10 + "count": 269 } ] }, @@ -14311,24 +11671,8 @@ "reactionCount": 15, "topReactions": [ { - "id": 93584, - "emoji": "🥹", - "count": 17 - }, - { - "id": 64509, - "emoji": "🥹", - "count": 7 - }, - { - "id": 26383, "emoji": "❤️", - "count": 11 - }, - { - "id": 18223, - "emoji": "🥹", - "count": 6 + "count": 607 } ] }, @@ -14364,19 +11708,12 @@ "reactionCount": 91, "topReactions": [ { - "id": 12819, - "emoji": "🎉", - "count": 16 - }, - { - "id": 51793, "emoji": "❤️", - "count": 8 + "count": 419 }, { - "id": 47344, - "emoji": "❤️", - "count": 9 + "emoji": "🎉", + "count": 932 } ] }, @@ -14391,10 +11728,10 @@ { "id": 78207, "recipientId": 55884, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/155/200/200", "relationship": "지인", - "content": "Suwon Kim님의 메세지 내용 87", + "content": "Sowon Kim님의 메세지 내용 87", "font": "Pretendard", "createdAt": "2023-06-01T07:21:37Z" }, @@ -14422,24 +11759,16 @@ "reactionCount": 53, "topReactions": [ { - "id": 48355, - "emoji": "👍", - "count": 6 - }, - { - "id": 38418, "emoji": "👍", - "count": 13 + "count": 737 }, { - "id": 7995, "emoji": "😀", - "count": 20 + "count": 7 }, { - "id": 55879, "emoji": "🥹", - "count": 5 + "count": 149 } ] }, @@ -14454,10 +11783,10 @@ { "id": 2300, "recipientId": 65809, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/358/200/200", "relationship": "지인", - "content": "Suwon Kim님의 메세지 내용 60", + "content": "Sowon Kim님의 메세지 내용 60", "font": "Roboto", "createdAt": "2023-05-12T09:25:19Z" }, @@ -14485,34 +11814,8 @@ "reactionCount": 93, "topReactions": [ { - "id": 51783, "emoji": "🎉", - "count": 10 - }, - { - "id": 37523, - "emoji": "❤️", - "count": 19 - }, - { - "id": 58371, - "emoji": "😁", - "count": 16 - }, - { - "id": 83933, - "emoji": "😀", - "count": 10 - }, - { - "id": 67432, - "emoji": "❤️", - "count": 17 - }, - { - "id": 37226, - "emoji": "😀", - "count": 15 + "count": 758 } ] }, @@ -14527,10 +11830,10 @@ { "id": 12155, "recipientId": 47549, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/247/200/200", "relationship": "지인", - "content": "Suwon Kim님의 메세지 내용 80", + "content": "Sowon Kim님의 메세지 내용 80", "font": "Pretendard", "createdAt": "2023-03-09T22:19:14Z" }, @@ -14558,34 +11861,8 @@ "reactionCount": 73, "topReactions": [ { - "id": 6824, - "emoji": "🎉", - "count": 1 - }, - { - "id": 77828, "emoji": "😀", - "count": 14 - }, - { - "id": 10712, - "emoji": "🥹", - "count": 8 - }, - { - "id": 14431, - "emoji": "❤️", - "count": 5 - }, - { - "id": 41886, - "emoji": "🎉", - "count": 15 - }, - { - "id": 38043, - "emoji": "❤️", - "count": 7 + "count": 662 } ] }, @@ -14620,10 +11897,10 @@ { "id": 64811, "recipientId": 7135, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/184/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 9", + "content": "Sowon Kim님의 메세지 내용 9", "font": "Roboto", "createdAt": "2023-10-17T00:36:13Z" } @@ -14631,9 +11908,8 @@ "reactionCount": 80, "topReactions": [ { - "id": 73068, "emoji": "😁", - "count": 14 + "count": 292 } ] }, @@ -14679,29 +11955,16 @@ "reactionCount": 0, "topReactions": [ { - "id": 64631, - "emoji": "❤️", - "count": 7 - }, - { - "id": 15818, - "emoji": "❤️", - "count": 6 + "emoji": "🎉", + "count": 176 }, { - "id": 96523, "emoji": "❤️", - "count": 3 - }, - { - "id": 87388, - "emoji": "🎉", - "count": 19 + "count": 889 }, { - "id": 64648, "emoji": "👍", - "count": 4 + "count": 759 } ] }, @@ -14747,19 +12010,16 @@ "reactionCount": 54, "topReactions": [ { - "id": 38019, "emoji": "😀", - "count": 5 + "count": 420 }, { - "id": 97709, - "emoji": "😁", - "count": 17 + "emoji": "👍", + "count": 760 }, { - "id": 46872, - "emoji": "👍", - "count": 1 + "emoji": "😁", + "count": 167 } ] }, @@ -14805,14 +12065,12 @@ "reactionCount": 2, "topReactions": [ { - "id": 10319, - "emoji": "🥹", - "count": 19 + "emoji": "🎉", + "count": 440 }, { - "id": 88672, - "emoji": "🎉", - "count": 18 + "emoji": "🥹", + "count": 460 } ] }, @@ -14858,24 +12116,16 @@ "reactionCount": 56, "topReactions": [ { - "id": 82148, - "emoji": "😀", - "count": 5 + "emoji": "🎉", + "count": 241 }, { - "id": 99162, "emoji": "😀", - "count": 20 - }, - { - "id": 60338, - "emoji": "🎉", - "count": 20 + "count": 812 }, { - "id": 99668, "emoji": "👍", - "count": 10 + "count": 621 } ] }, @@ -14921,19 +12171,8 @@ "reactionCount": 4, "topReactions": [ { - "id": 2410, - "emoji": "👍", - "count": 7 - }, - { - "id": 46152, - "emoji": "😀", - "count": 4 - }, - { - "id": 98175, "emoji": "🎉", - "count": 1 + "count": 452 } ] }, @@ -14979,14 +12218,12 @@ "reactionCount": 24, "topReactions": [ { - "id": 8056, - "emoji": "🥹", - "count": 17 + "emoji": "❤️", + "count": 576 }, { - "id": 73087, - "emoji": "❤️", - "count": 2 + "emoji": "🥹", + "count": 888 } ] }, @@ -15022,9 +12259,8 @@ "reactionCount": 31, "topReactions": [ { - "id": 58447, "emoji": "😁", - "count": 18 + "count": 130 } ] }, @@ -15070,29 +12306,8 @@ "reactionCount": 28, "topReactions": [ { - "id": 18524, - "emoji": "🎉", - "count": 5 - }, - { - "id": 46949, "emoji": "😁", - "count": 16 - }, - { - "id": 76510, - "emoji": "😁", - "count": 12 - }, - { - "id": 81605, - "emoji": "😀", - "count": 19 - }, - { - "id": 66745, - "emoji": "🎉", - "count": 13 + "count": 339 } ] }, @@ -15117,10 +12332,10 @@ { "id": 65322, "recipientId": 21977, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/156/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 79", + "content": "Sowon Kim님의 메세지 내용 79", "font": "Nanum Gothic", "createdAt": "2023-09-13T04:30:55Z" } @@ -15128,19 +12343,16 @@ "reactionCount": 76, "topReactions": [ { - "id": 11821, "emoji": "😀", - "count": 15 + "count": 90 }, { - "id": 35147, "emoji": "😁", - "count": 1 + "count": 875 }, { - "id": 34644, "emoji": "🎉", - "count": 5 + "count": 422 } ] }, @@ -15155,10 +12367,10 @@ { "id": 37649, "recipientId": 67245, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/160/200/200", "relationship": "지인", - "content": "Suwon Kim님의 메세지 내용 84", + "content": "Sowon Kim님의 메세지 내용 84", "font": "Roboto", "createdAt": "2023-05-09T12:36:18Z" }, @@ -15186,34 +12398,12 @@ "reactionCount": 35, "topReactions": [ { - "id": 59116, - "emoji": "🥹", - "count": 1 - }, - { - "id": 49749, - "emoji": "😀", - "count": 6 - }, - { - "id": 9760, - "emoji": "❤️", - "count": 20 - }, - { - "id": 29620, "emoji": "😀", - "count": 17 + "count": 254 }, { - "id": 93360, "emoji": "🥹", - "count": 5 - }, - { - "id": 55285, - "emoji": "🎉", - "count": 6 + "count": 515 } ] }, @@ -15259,24 +12449,8 @@ "reactionCount": 66, "topReactions": [ { - "id": 93016, - "emoji": "❤️", - "count": 5 - }, - { - "id": 41560, - "emoji": "👍", - "count": 8 - }, - { - "id": 62205, - "emoji": "👍", - "count": 17 - }, - { - "id": 98001, "emoji": "🥹", - "count": 4 + "count": 414 } ] }, @@ -15312,34 +12486,16 @@ "reactionCount": 100, "topReactions": [ { - "id": 18600, "emoji": "😁", - "count": 20 - }, - { - "id": 69649, - "emoji": "🥹", - "count": 14 + "count": 782 }, { - "id": 61872, "emoji": "🎉", - "count": 12 - }, - { - "id": 53627, - "emoji": "👍", - "count": 3 + "count": 204 }, { - "id": 97051, "emoji": "❤️", - "count": 17 - }, - { - "id": 91070, - "emoji": "🥹", - "count": 19 + "count": 348 } ] }, @@ -15382,22 +12538,11 @@ "createdAt": "2024-01-25T22:34:40Z" } ], - "reactionCount": 6, - "topReactions": [ - { - "id": 61471, - "emoji": "❤️", - "count": 17 - }, + "reactionCount": 6, + "topReactions": [ { - "id": 3871, "emoji": "👍", - "count": 2 - }, - { - "id": 72869, - "emoji": "😀", - "count": 8 + "count": 324 } ] }, @@ -15443,34 +12588,12 @@ "reactionCount": 65, "topReactions": [ { - "id": 92606, - "emoji": "😁", - "count": 4 - }, - { - "id": 38991, "emoji": "👍", - "count": 8 - }, - { - "id": 59355, - "emoji": "🥹", - "count": 3 - }, - { - "id": 54969, - "emoji": "🥹", - "count": 6 - }, - { - "id": 33347, - "emoji": "🥹", - "count": 8 + "count": 399 }, { - "id": 92921, "emoji": "🎉", - "count": 13 + "count": 851 } ] }, @@ -15496,24 +12619,16 @@ "reactionCount": 83, "topReactions": [ { - "id": 30441, - "emoji": "❤️", - "count": 1 - }, - { - "id": 39751, - "emoji": "😁", - "count": 20 + "emoji": "👍", + "count": 682 }, { - "id": 53520, - "emoji": "😀", - "count": 20 + "emoji": "❤️", + "count": 842 }, { - "id": 10975, - "emoji": "👍", - "count": 7 + "emoji": "😁", + "count": 379 } ] }, @@ -15559,19 +12674,8 @@ "reactionCount": 46, "topReactions": [ { - "id": 62030, - "emoji": "🎉", - "count": 15 - }, - { - "id": 97843, - "emoji": "🎉", - "count": 10 - }, - { - "id": 93058, "emoji": "😁", - "count": 4 + "count": 277 } ] }, @@ -15617,29 +12721,12 @@ "reactionCount": 74, "topReactions": [ { - "id": 48788, - "emoji": "🎉", - "count": 3 - }, - { - "id": 40394, - "emoji": "🥹", - "count": 18 - }, - { - "id": 22994, "emoji": "😁", - "count": 16 + "count": 619 }, { - "id": 46587, "emoji": "🎉", - "count": 17 - }, - { - "id": 83614, - "emoji": "🥹", - "count": 13 + "count": 601 } ] }, @@ -15654,10 +12741,10 @@ { "id": 7778, "recipientId": 37498, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/202/200/200", "relationship": "가족", - "content": "Suwon Kim님의 메세지 내용 24", + "content": "Sowon Kim님의 메세지 내용 24", "font": "Pretendard", "createdAt": "2023-12-27T07:03:22Z" }, @@ -15685,24 +12772,8 @@ "reactionCount": 86, "topReactions": [ { - "id": 3081, - "emoji": "❤️", - "count": 15 - }, - { - "id": 5953, - "emoji": "😁", - "count": 9 - }, - { - "id": 28198, "emoji": "😀", - "count": 2 - }, - { - "id": 89135, - "emoji": "👍", - "count": 5 + "count": 23 } ] }, @@ -15738,9 +12809,8 @@ "reactionCount": 44, "topReactions": [ { - "id": 5603, "emoji": "👍", - "count": 5 + "count": 712 } ] }, @@ -15786,34 +12856,8 @@ "reactionCount": 19, "topReactions": [ { - "id": 56372, - "emoji": "😁", - "count": 2 - }, - { - "id": 27688, - "emoji": "😀", - "count": 12 - }, - { - "id": 41479, "emoji": "😁", - "count": 9 - }, - { - "id": 84278, - "emoji": "👍", - "count": 1 - }, - { - "id": 10391, - "emoji": "❤️", - "count": 15 - }, - { - "id": 47486, - "emoji": "👍", - "count": 14 + "count": 714 } ] }, @@ -15859,35 +12903,14 @@ "reactionCount": 51, "topReactions": [ { - "id": 91006, "emoji": "😁", - "count": 7 - }, - { - "id": 33237, - "emoji": "😀", - "count": 9 - }, - { - "id": 53636, - "emoji": "🎉", - "count": 12 - }, - { - "id": 15454, - "emoji": "😀", - "count": 18 - }, - { - "id": 14384, - "emoji": "❤️", - "count": 14 + "count": 165 } ] }, { "id": 12700, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "purple", "backgroundImageURL": null, "createdAt": "2023-08-18T22:43:12Z", @@ -15916,10 +12939,10 @@ { "id": 4746, "recipientId": 12700, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/260/200/200", "relationship": "친구", - "content": "Suwon Kim님의 메세지 내용 44", + "content": "Sowon Kim님의 메세지 내용 44", "font": "Noto Sans", "createdAt": "2023-02-17T03:59:23Z" } @@ -15927,34 +12950,12 @@ "reactionCount": 74, "topReactions": [ { - "id": 88984, - "emoji": "❤️", - "count": 18 - }, - { - "id": 57596, - "emoji": "❤️", - "count": 1 - }, - { - "id": 12377, - "emoji": "🥹", - "count": 17 - }, - { - "id": 45146, - "emoji": "❤️", - "count": 9 - }, - { - "id": 53052, "emoji": "🥹", - "count": 7 + "count": 597 }, { - "id": 60303, "emoji": "❤️", - "count": 10 + "count": 681 } ] }, @@ -15990,24 +12991,12 @@ "reactionCount": 9, "topReactions": [ { - "id": 5270, - "emoji": "🎉", - "count": 4 - }, - { - "id": 42056, - "emoji": "🎉", - "count": 9 - }, - { - "id": 79595, "emoji": "❤️", - "count": 20 + "count": 756 }, { - "id": 49566, "emoji": "😁", - "count": 10 + "count": 922 } ] }, @@ -16053,19 +13042,16 @@ "reactionCount": 53, "topReactions": [ { - "id": 89292, - "emoji": "❤️", - "count": 4 + "emoji": "🎉", + "count": 596 }, { - "id": 50557, "emoji": "🥹", - "count": 14 + "count": 907 }, { - "id": 50390, - "emoji": "🎉", - "count": 1 + "emoji": "❤️", + "count": 594 } ] }, @@ -16111,9 +13097,8 @@ "reactionCount": 65, "topReactions": [ { - "id": 79656, "emoji": "🎉", - "count": 14 + "count": 94 } ] }, @@ -16159,14 +13144,8 @@ "reactionCount": 41, "topReactions": [ { - "id": 90464, - "emoji": "😀", - "count": 14 - }, - { - "id": 30005, "emoji": "😀", - "count": 10 + "count": 176 } ] }, @@ -16181,10 +13160,10 @@ { "id": 47661, "recipientId": 56031, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/395/200/200", "relationship": "동료", - "content": "Suwon Kim님의 메세지 내용 62", + "content": "Sowon Kim님의 메세지 내용 62", "font": "Nanum Gothic", "createdAt": "2023-08-20T17:27:35Z" }, @@ -16212,14 +13191,12 @@ "reactionCount": 83, "topReactions": [ { - "id": 33533, "emoji": "❤️", - "count": 11 + "count": 375 }, { - "id": 51483, "emoji": "🥹", - "count": 16 + "count": 408 } ] }, @@ -16265,9 +13242,8 @@ "reactionCount": 61, "topReactions": [ { - "id": 76710, "emoji": "👍", - "count": 5 + "count": 665 } ] }, @@ -16303,29 +13279,12 @@ "reactionCount": 97, "topReactions": [ { - "id": 82751, - "emoji": "🥹", - "count": 7 - }, - { - "id": 27780, - "emoji": "🥹", - "count": 11 - }, - { - "id": 11937, - "emoji": "❤️", - "count": 15 + "emoji": "😀", + "count": 951 }, { - "id": 35875, "emoji": "❤️", - "count": 9 - }, - { - "id": 93134, - "emoji": "😀", - "count": 6 + "count": 215 } ] }, @@ -16371,24 +13330,8 @@ "reactionCount": 48, "topReactions": [ { - "id": 33044, - "emoji": "🥹", - "count": 18 - }, - { - "id": 77894, - "emoji": "😁", - "count": 4 - }, - { - "id": 97021, "emoji": "🎉", - "count": 17 - }, - { - "id": 94868, - "emoji": "🥹", - "count": 3 + "count": 995 } ] }, @@ -16434,14 +13377,8 @@ "reactionCount": 13, "topReactions": [ { - "id": 81498, - "emoji": "❤️", - "count": 10 - }, - { - "id": 39236, "emoji": "❤️", - "count": 17 + "count": 62 } ] }, @@ -16487,34 +13424,8 @@ "reactionCount": 57, "topReactions": [ { - "id": 5184, - "emoji": "👍", - "count": 18 - }, - { - "id": 31068, - "emoji": "😁", - "count": 8 - }, - { - "id": 87339, - "emoji": "👍", - "count": 2 - }, - { - "id": 79179, - "emoji": "❤️", - "count": 15 - }, - { - "id": 2076, - "emoji": "😁", - "count": 9 - }, - { - "id": 9962, "emoji": "👍", - "count": 15 + "count": 412 } ] }, @@ -16560,24 +13471,12 @@ "reactionCount": 87, "topReactions": [ { - "id": 87641, - "emoji": "😁", - "count": 12 - }, - { - "id": 89470, "emoji": "😀", - "count": 4 - }, - { - "id": 40031, - "emoji": "❤️", - "count": 1 + "count": 356 }, { - "id": 42953, "emoji": "😁", - "count": 18 + "count": 255 } ] }, @@ -16623,9 +13522,8 @@ "reactionCount": 55, "topReactions": [ { - "id": 71312, "emoji": "❤️", - "count": 1 + "count": 839 } ] }, @@ -16671,14 +13569,12 @@ "reactionCount": 34, "topReactions": [ { - "id": 4256, "emoji": "👍", - "count": 4 + "count": 367 }, { - "id": 89759, "emoji": "❤️", - "count": 3 + "count": 86 } ] }, @@ -16704,19 +13600,12 @@ "reactionCount": 40, "topReactions": [ { - "id": 93310, - "emoji": "😁", - "count": 4 + "emoji": "🥹", + "count": 607 }, { - "id": 37249, "emoji": "😁", - "count": 5 - }, - { - "id": 73269, - "emoji": "🥹", - "count": 7 + "count": 324 } ] }, @@ -16762,29 +13651,12 @@ "reactionCount": 12, "topReactions": [ { - "id": 66681, "emoji": "🥹", - "count": 8 - }, - { - "id": 67854, - "emoji": "😁", - "count": 15 + "count": 603 }, { - "id": 94387, - "emoji": "❤️", - "count": 16 - }, - { - "id": 94338, "emoji": "🎉", - "count": 20 - }, - { - "id": 59665, - "emoji": "🎉", - "count": 8 + "count": 741 } ] }, @@ -16830,29 +13702,12 @@ "reactionCount": 26, "topReactions": [ { - "id": 63913, - "emoji": "😀", - "count": 8 - }, - { - "id": 82488, - "emoji": "🎉", - "count": 6 - }, - { - "id": 38729, - "emoji": "👍", - "count": 3 - }, - { - "id": 79770, "emoji": "❤️", - "count": 16 + "count": 356 }, { - "id": 75631, "emoji": "🎉", - "count": 5 + "count": 780 } ] }, @@ -16898,34 +13753,16 @@ "reactionCount": 45, "topReactions": [ { - "id": 86657, - "emoji": "🥹", - "count": 10 - }, - { - "id": 6702, - "emoji": "🎉", - "count": 11 - }, - { - "id": 64387, "emoji": "🥹", - "count": 7 + "count": 664 }, { - "id": 16189, "emoji": "😀", - "count": 11 + "count": 205 }, { - "id": 58652, "emoji": "🎉", - "count": 2 - }, - { - "id": 67118, - "emoji": "🥹", - "count": 5 + "count": 667 } ] }, @@ -16971,34 +13808,16 @@ "reactionCount": 15, "topReactions": [ { - "id": 40353, - "emoji": "🥹", - "count": 19 - }, - { - "id": 25637, - "emoji": "👍", - "count": 17 - }, - { - "id": 34226, - "emoji": "🥹", - "count": 4 - }, - { - "id": 14495, - "emoji": "👍", - "count": 14 + "emoji": "🎉", + "count": 963 }, { - "id": 96566, "emoji": "❤️", - "count": 3 + "count": 879 }, { - "id": 2409, - "emoji": "🎉", - "count": 10 + "emoji": "🥹", + "count": 713 } ] }, @@ -17044,14 +13863,12 @@ "reactionCount": 73, "topReactions": [ { - "id": 83819, "emoji": "😁", - "count": 15 + "count": 12 }, { - "id": 91850, "emoji": "🥹", - "count": 2 + "count": 176 } ] }, @@ -17097,25 +13914,18 @@ "reactionCount": 12, "topReactions": [ { - "id": 14335, "emoji": "❤️", - "count": 10 + "count": 766 }, { - "id": 37620, "emoji": "😁", - "count": 18 - }, - { - "id": 35030, - "emoji": "😁", - "count": 18 + "count": 636 } ] }, { "id": 31249, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "blue", "backgroundImageURL": null, "createdAt": "2023-05-16T17:41:45Z", @@ -17134,10 +13944,10 @@ { "id": 54855, "recipientId": 31249, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/188/200/200", "relationship": "지인", - "content": "Suwon Kim님의 메세지 내용 84", + "content": "Sowon Kim님의 메세지 내용 84", "font": "Pretendard", "createdAt": "2023-07-01T14:34:04Z" } @@ -17145,25 +13955,18 @@ "reactionCount": 87, "topReactions": [ { - "id": 64819, - "emoji": "😀", - "count": 16 + "emoji": "🎉", + "count": 697 }, { - "id": 14849, "emoji": "😀", - "count": 4 - }, - { - "id": 30100, - "emoji": "🎉", - "count": 15 + "count": 765 } ] }, { "id": 87008, - "name": "Suwon Kim", + "name": "Sowon Kim", "backgroundColor": "purple", "backgroundImageURL": null, "createdAt": "2023-05-31T18:24:49Z", @@ -17182,10 +13985,10 @@ { "id": 29069, "recipientId": 87008, - "sender": "Suwon Kim", + "sender": "Sowon Kim", "profileImageURL": "https://picsum.photos/id/25/200/200", "relationship": "지인", - "content": "Suwon Kim님의 메세지 내용 19", + "content": "Sowon Kim님의 메세지 내용 19", "font": "Roboto", "createdAt": "2024-01-14T03:59:30Z" }, @@ -17203,24 +14006,8 @@ "reactionCount": 42, "topReactions": [ { - "id": 86769, - "emoji": "❤️", - "count": 10 - }, - { - "id": 17942, - "emoji": "👍", - "count": 8 - }, - { - "id": 88772, "emoji": "😀", - "count": 5 - }, - { - "id": 69231, - "emoji": "👍", - "count": 15 + "count": 832 } ] } From e74d98fdbe3959ff13d29418ee3ca112b1ea629b Mon Sep 17 00:00:00 2001 From: luli Date: Mon, 18 Aug 2025 02:42:39 +0900 Subject: [PATCH 131/253] =?UTF-8?q?[#53]=20=EC=9D=B4=EB=AF=B8=EC=A7=80?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=EC=A0=9C=EC=99=B8=20desktop=EB=B2=84?= =?UTF-8?q?=EC=A0=84=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 이모지등ㄷ 추가사항 적용 --- .../components/rolling-paper-list.jsx | 76 +++++++++++++++++-- src/pages/test_recipients_data.json | 12 +-- 2 files changed, 77 insertions(+), 11 deletions(-) diff --git a/src/features/rolling-paper/components/rolling-paper-list.jsx b/src/features/rolling-paper/components/rolling-paper-list.jsx index 8bb4608..d01ec30 100644 --- a/src/features/rolling-paper/components/rolling-paper-list.jsx +++ b/src/features/rolling-paper/components/rolling-paper-list.jsx @@ -32,15 +32,16 @@ const CardContainer = styled.div` const CardItem = styled.div` width: 275px; - height: 260px; + min-height: 260px; border-radius: 16px; text-align: left; padding: 30px 24px 20px 24px; border: 1px solid rgba(0, 0, 0, 0.1); box-shadow: 0px 2px 12px 0px rgba(0, 0, 0, 0.08); - display: grid; - grid-template-rows: 1fr 1fr auto; + display: flex; + gap: 12px; + flex-direction: column; background: ${(props) => props.$backgroundImageURL @@ -153,8 +154,54 @@ const MessageCountText = styled.span` } `; -const CardEmoji = styled.div` +const CardEmojiBox = styled.div` border-top: 1px solid rgba(0, 0, 0, 0.1); + padding-top: 17px; + margin-top: auto; + + display: flex; + flex-wrap: wrap; + row-gap: 5px; +`; + +const CardEmoji = styled.span` + background-color: rgba(0, 0, 0, 0.54); + border-radius: 32px; + color: #ffffff; + padding: 8px 12px; + margin-right: 8px; + + position: relative; + white-space: nowrap; + overflow: hidden; + + min-width: ${(props) => (props.$isLong ? "60px" : "auto")}; + max-width: ${(props) => (props.$isLong ? "44px" : "none")}; + + transition: max-width 0.3s ease, z-index 0s; + + &:hover { + max-width: 200px; + z-index: 100; + position: relative; + } +`; + +const HiddenCount = styled.span` + display: inline; + + .show-on-hover { + display: none; + } + + ${CardEmoji}:hover & { + .show-on-hover { + display: inline; + } + .hide-on-hover { + display: none; + } + } `; const NextButtonWrapper = styled.div` @@ -206,7 +253,26 @@ function RollingPaperList({ cardData, totalPages, currentPage, onTurnCards }) { > {item.messageCount}명이 작성했어요! - {item.topReactions.map((emoji) => emoji.emoji)} + + {item.topReactions.map((emoji, index) => { + const countLength = emoji.count.toString().length; + const isLongCount = countLength > 2; + + return ( + + {emoji.emoji} + {isLongCount ? ( + + + + {emoji.count} + + ) : ( + ` ${emoji.count}` + )} + + ); + })} + ))} {currentPage > 0 && ( diff --git a/src/pages/test_recipients_data.json b/src/pages/test_recipients_data.json index 056ede3..8d2dbf0 100644 --- a/src/pages/test_recipients_data.json +++ b/src/pages/test_recipients_data.json @@ -22,7 +22,7 @@ "topReactions": [ { "emoji": "🥹", - "count": 159 + "count": 2 }, { "emoji": "😁", @@ -120,11 +120,11 @@ "topReactions": [ { "emoji": "😀", - "count": 46 + "count": 333 }, { "emoji": "🎉", - "count": 585 + "count": 333 }, { "emoji": "😁", @@ -212,15 +212,15 @@ "topReactions": [ { "emoji": "❤️", - "count": 847 + "count": 8 }, { "emoji": "😀", - "count": 141 + "count": 12 }, { "emoji": "👍", - "count": 396 + "count": 33 } ] }, From 5f056074af54d7701035bcf2ddc587c3e0999fdf Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 16 Aug 2025 10:53:49 +0900 Subject: [PATCH 132/253] =?UTF-8?q?feat=20[#46]=20`Portal`,=20`PortalProvi?= =?UTF-8?q?dr`=20component=EC=99=80=20`usePortal`=20hook=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/modal/modal-context.js | 5 ----- src/components/portal/portal-context.js | 5 +++++ src/components/portal/portal-provider.jsx | 10 ++++++++++ src/components/portal/portal.jsx | 7 +++++++ src/hooks/use-portal.jsx | 15 +++++++++++++++ 5 files changed, 37 insertions(+), 5 deletions(-) delete mode 100644 src/components/modal/modal-context.js create mode 100644 src/components/portal/portal-context.js create mode 100644 src/components/portal/portal-provider.jsx create mode 100644 src/components/portal/portal.jsx create mode 100644 src/hooks/use-portal.jsx diff --git a/src/components/modal/modal-context.js b/src/components/modal/modal-context.js deleted file mode 100644 index 2cee28d..0000000 --- a/src/components/modal/modal-context.js +++ /dev/null @@ -1,5 +0,0 @@ -import { createContext } from "react"; - -const ModalContext = createContext(); - -export default ModalContext; diff --git a/src/components/portal/portal-context.js b/src/components/portal/portal-context.js new file mode 100644 index 0000000..23b1a3b --- /dev/null +++ b/src/components/portal/portal-context.js @@ -0,0 +1,5 @@ +import { createContext } from "react"; + +const PortalContext = createContext({}); + +export default PortalContext; diff --git a/src/components/portal/portal-provider.jsx b/src/components/portal/portal-provider.jsx new file mode 100644 index 0000000..7d1a5df --- /dev/null +++ b/src/components/portal/portal-provider.jsx @@ -0,0 +1,10 @@ +import { useState } from "react"; +import PortalContext from "./portal-context"; + +function PortalProvider({ children }) { + const [portalState, setPortalState] = useState({}); + const value = { portalState, setPortalState }; + return {children}; +} + +export default PortalProvider; diff --git a/src/components/portal/portal.jsx b/src/components/portal/portal.jsx new file mode 100644 index 0000000..06a182b --- /dev/null +++ b/src/components/portal/portal.jsx @@ -0,0 +1,7 @@ +import { createPortal } from "react-dom"; + +function Portal({ children, id }) { + return createPortal(children, document.getElementById(id)); +} + +export default Portal; diff --git a/src/hooks/use-portal.jsx b/src/hooks/use-portal.jsx new file mode 100644 index 0000000..767fe0c --- /dev/null +++ b/src/hooks/use-portal.jsx @@ -0,0 +1,15 @@ +import { useContext } from "react"; +import PortalContext from "../components/portal/portal-context"; + +function usePortal({ key }) { + const { portalState, setPortalState } = useContext(PortalContext); + const isOpen = portalState[key] ?? false; + + const setIsOpen = (value) => { + setPortalState((prev) => ({ ...prev, [key]: value })); + }; + + return { isOpen, setIsOpen }; +} + +export { usePortal }; From 03bfc75d4b8a744d9bf5613377ed476d15a7b5b4 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 16 Aug 2025 10:57:48 +0900 Subject: [PATCH 133/253] =?UTF-8?q?feat=20[#46]=20=EA=B8=B0=EC=A1=B4=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=EB=A5=BC=20`Portal`=20component=20=EB=B0=8F?= =?UTF-8?q?=20`usePortal`=20hook=EC=9D=84=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.jsx | 12 +-- src/components/modal/modal-provider.jsx | 10 --- src/components/modal/modal.jsx | 57 +++++++------ src/components/popover/popover-context.js | 5 -- src/components/popover/popover-provider.jsx | 10 --- src/components/popover/popover.jsx | 43 +++++++--- .../dropdown-input/dropdown-context.js | 5 -- .../dropdown-input/dropdown-provider.jsx | 10 --- .../text-field/dropdown-input/dropdown.jsx | 10 +-- .../components/rolling-paper-reactions.jsx | 25 ++---- src/hooks/use-dropdown.jsx | 24 ++---- src/hooks/use-modal.jsx | 10 +-- src/hooks/use-popover.jsx | 45 +++++----- src/pages/test-page.jsx | 82 +++++++------------ 14 files changed, 138 insertions(+), 210 deletions(-) delete mode 100644 src/components/modal/modal-provider.jsx delete mode 100644 src/components/popover/popover-context.js delete mode 100644 src/components/popover/popover-provider.jsx delete mode 100644 src/components/text-field/dropdown-input/dropdown-context.js delete mode 100644 src/components/text-field/dropdown-input/dropdown-provider.jsx diff --git a/src/app.jsx b/src/app.jsx index 7b4902c..9689899 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -1,7 +1,5 @@ import { BrowserRouter, Route, Routes } from "react-router-dom"; -import ModalProvider from "./components/modal/modal-provider"; -import PopoverProvider from "./components/popover/popover-provider"; -import DropdownProvider from "./components/text-field/dropdown-input/dropdown-provider"; +import PortalProvider from "./components/portal/portal-provider"; import ContentLayout from "./layouts/content-layout"; import OnboardingLayout from "./layouts/onboarding-layout"; import CreatePostPage from "./pages/create-post-page"; @@ -13,13 +11,7 @@ import SendPage from "./pages/send-page"; import TestPage from "./pages/test-page"; function Provider({ children }) { - return ( - - - {children} - - - ); + return {children}; } function App() { diff --git a/src/components/modal/modal-provider.jsx b/src/components/modal/modal-provider.jsx deleted file mode 100644 index f7b6d44..0000000 --- a/src/components/modal/modal-provider.jsx +++ /dev/null @@ -1,10 +0,0 @@ -import { useState } from "react"; -import ModalContext from "./modal-context"; - -function ModalProvider({ children }) { - const [showsModal, setShowsModal] = useState(false); - const value = { showsModal, setShowsModal }; - return {children}; -} - -export default ModalProvider; diff --git a/src/components/modal/modal.jsx b/src/components/modal/modal.jsx index e0cb504..6e7e059 100644 --- a/src/components/modal/modal.jsx +++ b/src/components/modal/modal.jsx @@ -1,4 +1,3 @@ -import { createPortal } from "react-dom"; import styled from "styled-components"; import { useModal } from "../../hooks/use-modal"; import { formatDate } from "../../utils/formatter"; @@ -8,6 +7,7 @@ import BADGE_TYPE from "../badge/badge-type"; import { PrimaryButton } from "../button/button"; import BUTTON_SIZE from "../button/button-size"; import Colors from "../color/colors"; +import Portal from "../portal/portal"; /* UserInfo */ @@ -47,10 +47,10 @@ const StyledUserProfile = styled.div` gap: 16px; `; -function UserProfile({ profileImg, name }) { +function UserProfile({ profileImage, name }) { return ( - + ); @@ -77,11 +77,11 @@ const StyledHeader = styled.div` } `; -function Header({ profileImg, name, date }) { +function Header({ profileImage, name, date }) { return (
- + {formatDate(date, ".")}
@@ -140,29 +140,38 @@ const ModalContainer = styled.div` align-items: center; `; -function Modal({ user, date, content }) { - const { setShowsModal } = useModal(); - - const ModalPortal = ({ children }) => { - return createPortal(children, document.getElementById("modal")); - }; +function Modal({ id, user, date, content, children }) { + const { showsModal, setShowsModal } = useModal({ + id: id, + type: "modal", + }); + const handleClick = () => setShowsModal(true); const handleConfirmClick = () => setShowsModal(false); return ( - - - -
- {content} - - - - + <> +
{children}
+ {showsModal && ( + + + +
+ {content} + + + + + )} + ); } diff --git a/src/components/popover/popover-context.js b/src/components/popover/popover-context.js deleted file mode 100644 index 06b8815..0000000 --- a/src/components/popover/popover-context.js +++ /dev/null @@ -1,5 +0,0 @@ -import { createContext } from "react"; - -const PopoverContext = createContext(); - -export default PopoverContext; diff --git a/src/components/popover/popover-provider.jsx b/src/components/popover/popover-provider.jsx deleted file mode 100644 index 4529615..0000000 --- a/src/components/popover/popover-provider.jsx +++ /dev/null @@ -1,10 +0,0 @@ -import { useState } from "react"; -import PopoverContext from "./popover-context"; - -function PopoverProvider({ children }) { - const [showsPopover, setShowsPopover] = useState(false); - const value = { showsPopover, setShowsPopover }; - return {children}; -} - -export default PopoverProvider; diff --git a/src/components/popover/popover.jsx b/src/components/popover/popover.jsx index 2258612..08fec9e 100644 --- a/src/components/popover/popover.jsx +++ b/src/components/popover/popover.jsx @@ -1,5 +1,6 @@ -import { createPortal } from "react-dom"; import styled from "styled-components"; +import { usePopover } from "../../hooks/use-popover"; +import Portal from "../portal/portal"; const Container = styled.div` position: fixed; @@ -9,10 +10,6 @@ const Container = styled.div` left: 0; `; -function PopoverPortal({ children }) { - return createPortal(children, document.getElementById("popover")); -} - const StyledPopover = styled.div` position: absolute; top: ${({ $position }) => $position.top}px; @@ -24,15 +21,35 @@ const StyledPopover = styled.div` box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08); `; -function Popover({ isOpen, onClose, position, children }) { +function Popover({ id, alignment, action, children }) { + const { + targetRef, + position, + showsPopover, + setShowsPopover, + handleTargetClick, + } = usePopover({ + id, + type: "popover", + alignment, + }); + + const handleClick = () => handleTargetClick(true); + const handleBackdropClick = () => setShowsPopover(false); + return ( - isOpen && ( - - - {children} - - - ) + <> +
+ {action} +
+ {showsPopover && ( + + + {children} + + + )} + ); } diff --git a/src/components/text-field/dropdown-input/dropdown-context.js b/src/components/text-field/dropdown-input/dropdown-context.js deleted file mode 100644 index 34a3d95..0000000 --- a/src/components/text-field/dropdown-input/dropdown-context.js +++ /dev/null @@ -1,5 +0,0 @@ -import { createContext } from "react"; - -const DropdownContext = createContext(null); - -export default DropdownContext; diff --git a/src/components/text-field/dropdown-input/dropdown-provider.jsx b/src/components/text-field/dropdown-input/dropdown-provider.jsx deleted file mode 100644 index f74b577..0000000 --- a/src/components/text-field/dropdown-input/dropdown-provider.jsx +++ /dev/null @@ -1,10 +0,0 @@ -import { useState } from "react"; -import DropdownContext from "./dropdown-context"; - -function DropdownProvider({ children }) { - const [dropdownState, setDropdownState] = useState({}); - const value = { dropdownState, setDropdownState }; - return {children}; -} - -export default DropdownProvider; diff --git a/src/components/text-field/dropdown-input/dropdown.jsx b/src/components/text-field/dropdown-input/dropdown.jsx index 188df8a..a2c5774 100644 --- a/src/components/text-field/dropdown-input/dropdown.jsx +++ b/src/components/text-field/dropdown-input/dropdown.jsx @@ -1,6 +1,6 @@ -import { createPortal } from "react-dom"; import styled from "styled-components"; import Colors from "../../color/colors"; +import Portal from "../../portal/portal"; const BACKDROP_CLASS_NAME = "dropdown-backdrop"; @@ -44,12 +44,8 @@ const StyledDropdown = styled.div` `; function Dropdown({ children, origin, size, onClose }) { - const DropdownPortal = ({ children }) => { - return createPortal(children, document.getElementById("dropdown")); - }; - return ( - + @@ -59,7 +55,7 @@ function Dropdown({ children, origin, size, onClose }) { - + ); } diff --git a/src/features/rolling-paper/components/rolling-paper-reactions.jsx b/src/features/rolling-paper/components/rolling-paper-reactions.jsx index 8c4dc4b..689a4c0 100644 --- a/src/features/rolling-paper/components/rolling-paper-reactions.jsx +++ b/src/features/rolling-paper/components/rolling-paper-reactions.jsx @@ -1,11 +1,9 @@ -import { useRef } from "react"; import styled from "styled-components"; import arrowDownImage from "../../../assets/ic-chevron-down.svg"; import EmojiBadge from "../../../components/badge/emoji-badge"; import Popover from "../../../components/popover/popover"; import POPOVER_ALIGNMENT from "../../../components/popover/popover-alignment"; import { useMedia } from "../../../hooks/use-media"; -import { usePopover } from "../../../hooks/use-popover"; import { media } from "../../../utils/media"; const MoreButton = styled.button` @@ -41,16 +39,6 @@ const StyledRollingPaperReactions = styled.div` function RollingPaperReactions({ reactions }) { const { isMobile } = useMedia(); - const { popoverPosition, showsPopover, openPopopver, closePopover } = - usePopover(); - const targetRef = useRef(); - - const handleMoreClick = () => { - openPopopver({ - target: targetRef.current, - alignment: POPOVER_ALIGNMENT.right, - }); - }; return ( @@ -59,13 +47,14 @@ function RollingPaperReactions({ reactions }) { ))} - - 열기 버튼 - + 열기 버튼 + + } > {reactions.slice(0, isMobile ? 6 : 8).map(({ id, emoji, count }) => ( diff --git a/src/hooks/use-dropdown.jsx b/src/hooks/use-dropdown.jsx index 5a25cb6..a539cef 100644 --- a/src/hooks/use-dropdown.jsx +++ b/src/hooks/use-dropdown.jsx @@ -1,5 +1,5 @@ -import { useContext, useEffect, useRef, useState } from "react"; -import DropdownContext from "../components/text-field/dropdown-input/dropdown-context"; +import { useEffect, useRef, useState } from "react"; +import { usePortal } from "./use-portal"; function makeRect({ x, y, width } = { x: 0, y: 0, width: 0 }) { return { @@ -24,18 +24,12 @@ function calculateDropdownRect(target) { } function useDropdown({ id, type }) { - const { dropdownState, setDropdownState } = useContext(DropdownContext); + const key = `${type}_${id}`; + const { isOpen, setIsOpen } = usePortal({ key }); const [dropdownRect, setDropdownRect] = useState(); const targetRef = useRef(); - const key = `${type}_${id}`; - const showsDropdown = dropdownState[key] ?? false; - - const setShowsDropdown = (shows) => { - setDropdownState((prev) => ({ ...prev, [key]: shows })); - }; - const updateDropdownLayout = (target) => { const rect = calculateDropdownRect(target); setDropdownRect(rect); @@ -43,11 +37,11 @@ function useDropdown({ id, type }) { const handleTargetClick = (shows) => { updateDropdownLayout(targetRef.current); - setShowsDropdown(shows); + setIsOpen(shows); }; useEffect(() => { - if (!showsDropdown) return; + if (!isOpen) return; function handleWindowResize() { updateDropdownLayout(targetRef.current); @@ -55,13 +49,13 @@ function useDropdown({ id, type }) { window.addEventListener("resize", handleWindowResize); return () => window.removeEventListener("resize", handleWindowResize); - }, [showsDropdown, targetRef]); + }, [isOpen, targetRef]); return { targetRef, dropdownRect, - showsDropdown, - setShowsDropdown, + showsDropdown: isOpen, + setShowsDropdown: setIsOpen, handleTargetClick, }; } diff --git a/src/hooks/use-modal.jsx b/src/hooks/use-modal.jsx index d215967..9a3a1ad 100644 --- a/src/hooks/use-modal.jsx +++ b/src/hooks/use-modal.jsx @@ -1,9 +1,9 @@ -import { useContext } from "react"; -import ModalContext from "../components/modal/modal-context"; +import { usePortal } from "./use-portal"; -function useModal() { - const { showsModal, setShowsModal } = useContext(ModalContext); - return { showsModal, setShowsModal }; +function useModal({ id, type }) { + const key = `${type}_${id}`; + const { isOpen, setIsOpen } = usePortal({ key }); + return { showsModal: isOpen, setShowsModal: setIsOpen }; } export { useModal }; diff --git a/src/hooks/use-popover.jsx b/src/hooks/use-popover.jsx index 70cea0d..1e230fc 100644 --- a/src/hooks/use-popover.jsx +++ b/src/hooks/use-popover.jsx @@ -1,6 +1,6 @@ -import { useContext, useState, useEffect } from "react"; +import { useEffect, useRef, useState } from "react"; import POPOVER_ALIGNMENT from "../components/popover/popover-alignment"; -import PopoverContext from "../components/popover/popover-context"; +import { usePortal } from "./use-portal"; function calculatePopoverPosition(target, alignment) { if (!target) { @@ -24,44 +24,39 @@ function calculatePopoverPosition(target, alignment) { return position; } -function usePopover() { - const { showsPopover, setShowsPopover } = useContext(PopoverContext); - const [popoverPosition, setPopoverPosition] = useState(); - const [target, setTarget] = useState(); - const [alignment, setAlignment] = useState(POPOVER_ALIGNMENT.left); - - const openPopopver = ({ target, alignment }) => { - updatePopoverPosition(target, alignment); - setTarget(target); - setAlignment(alignment); - setShowsPopover(true); - }; - - const closePopover = () => { - setShowsPopover(false); - }; +function usePopover({ id, type, alignment }) { + const key = `${type}_${id}`; + const { isOpen, setIsOpen } = usePortal({ key }); + const [position, setPopoverPosition] = useState(); + const targetRef = useRef(); const updatePopoverPosition = (target, alignment) => { const position = calculatePopoverPosition(target, alignment); setPopoverPosition(position); }; + const handleTargetClick = (shows) => { + updatePopoverPosition(targetRef.current, alignment); + setIsOpen(shows); + }; + useEffect(() => { - if (!showsPopover) return; + if (!isOpen) return; function handleWindowResize() { - updatePopoverPosition(target, alignment); + updatePopoverPosition(targetRef.current, alignment); } window.addEventListener("resize", handleWindowResize); return () => window.removeEventListener("resize", handleWindowResize); - }, [showsPopover, target, alignment]); + }, [isOpen, targetRef, alignment]); return { - popoverPosition, - showsPopover, - openPopopver, - closePopover, + targetRef, + position, + showsPopover: isOpen, + setShowsPopover: setIsOpen, + handleTargetClick, }; } diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index f691c69..76b07dd 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -1,4 +1,4 @@ -import { useRef, useState } from "react"; +import { useState } from "react"; import styled from "styled-components"; import smileAddImage from "../assets/ic-face-smile-add.svg"; import Avatar from "../components/avatar/avatar"; @@ -22,8 +22,6 @@ import POPOVER_ALIGNMENT from "../components/popover/popover-alignment"; import TextField from "../components/text-field/text-field"; import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; import Toast from "../components/toast/toast"; -import { useModal } from "../hooks/use-modal"; -import { usePopover } from "../hooks/use-popover"; import { useToast } from "../hooks/use-toast"; const OutlinedHeader = styled(Header)` @@ -50,29 +48,6 @@ function TestPage() { const handleToastClick = () => setShowsToast(true); const handleToastDismiss = () => setShowsToast(false); - /* Modal */ - const { showsModal, setShowsModal } = useModal(); - const handleModalClick = () => setShowsModal(true); - - /* Popover */ - const { popoverPosition, showsPopover, openPopopver, closePopover } = - usePopover(); - const popoverLeftRef = useRef(); - const popoverRightRef = useRef(); - - const handlePopoverLeftClick = () => { - openPopopver({ - target: popoverLeftRef.current, - alignment: POPOVER_ALIGNMENT.left, - }); - }; - const handlePopoverRightClick = () => { - openPopopver({ - target: popoverRightRef.current, - alignment: POPOVER_ALIGNMENT.right, - }); - }; - return (
- - {showsModal && ( - - )} + + +
- - + } + > +

This is Popover.

+
+ + } >

This is Popover.

From 9e1e65d96c5056b17d08725e3b28b9cc96ed4ed2 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 16 Aug 2025 11:01:17 +0900 Subject: [PATCH 134/253] =?UTF-8?q?refactor=20[#46]=20Modal=20action=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EB=B0=A9=EC=8B=9D=EC=9D=84=20Popover?= =?UTF-8?q?=EC=99=80=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `children`이 아닌 `action` prop으로 직접 받음 --- src/components/modal/modal.jsx | 4 ++-- src/pages/test-page.jsx | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/components/modal/modal.jsx b/src/components/modal/modal.jsx index 6e7e059..a098817 100644 --- a/src/components/modal/modal.jsx +++ b/src/components/modal/modal.jsx @@ -140,7 +140,7 @@ const ModalContainer = styled.div` align-items: center; `; -function Modal({ id, user, date, content, children }) { +function Modal({ id, user, date, content, action }) { const { showsModal, setShowsModal } = useModal({ id: id, type: "modal", @@ -151,7 +151,7 @@ function Modal({ id, user, date, content, children }) { return ( <> -
{children}
+
{action}
{showsModal && ( diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index 76b07dd..0f4f8b3 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -199,9 +199,8 @@ function TestPage() { user={{ name: "김동훈", profileImage: null }} date={new Date("2023-07-08")} content="코로나가 또다시 기승을 부리는 요즘이네요. 건강, 체력 모두 조심 또 하세요! 코로나가 또다시 기승을 부리는 요즘이네요. 건강, 체력 모두 조심 또 하세요!코로나가 또다시 기승을 부리는 요즘이네요. 건강, 체력 모두 조심 또 하세요!코로나가 또다시 기승을 부리는 요즘이네요. 건강, 체력 모두 조심 또 하세요!코로나가 또다시 기승을 부리는 요즘이네요. 건강, 체력 모두 조심 또 하세요!코로나가 또다시 기승을 부리는 요즘이네요. 건강, 체력 모두 조심 또 하세요! 코로나가 또다시 기승을 부리는 요즘이네요. 건강, 체력 모두 조심 또 하세요!코로나가 또다시 기승을 부리는 요즘이네요. 건강, 체력 모두 조심 또 하세요!코로나가 또다시 기승을 부리는 요즘이네요. 건강, 체력 모두 조심 또 하세요!코로나가 또다시 기승을 부리는 요즘이네요. 건강, 체력 모두 조심 또 하세요!코로나가 또다시 기승을 부리는 요즘이네요. 건강, 체력 모두 조심 또 하세요!" - > - - + action={} + />
Date: Sat, 16 Aug 2025 11:40:13 +0900 Subject: [PATCH 135/253] =?UTF-8?q?fix=20[#46]=20=ED=99=94=EB=A9=B4?= =?UTF-8?q?=EC=9D=84=20scroll=20=ED=95=A0=20=EB=95=8C=20dropdown=20?= =?UTF-8?q?=EB=B0=8F=20popover=EA=B0=80=20scroll=ED=95=9C=20=EB=A7=8C?= =?UTF-8?q?=ED=81=BC=20=EC=9D=B4=EB=8F=99=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/use-dropdown.jsx | 11 ++++++++++- src/hooks/use-popover.jsx | 11 ++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/hooks/use-dropdown.jsx b/src/hooks/use-dropdown.jsx index a539cef..7e932a4 100644 --- a/src/hooks/use-dropdown.jsx +++ b/src/hooks/use-dropdown.jsx @@ -47,8 +47,17 @@ function useDropdown({ id, type }) { updateDropdownLayout(targetRef.current); } + function handleWindowScroll() { + updateDropdownLayout(targetRef.current); + } + window.addEventListener("resize", handleWindowResize); - return () => window.removeEventListener("resize", handleWindowResize); + window.addEventListener("scroll", handleWindowScroll); + + return () => { + window.removeEventListener("resize", handleWindowResize); + window.removeEventListener("scroll", handleWindowScroll); + }; }, [isOpen, targetRef]); return { diff --git a/src/hooks/use-popover.jsx b/src/hooks/use-popover.jsx index 1e230fc..d4ec738 100644 --- a/src/hooks/use-popover.jsx +++ b/src/hooks/use-popover.jsx @@ -47,8 +47,17 @@ function usePopover({ id, type, alignment }) { updatePopoverPosition(targetRef.current, alignment); } + function handleWindowScroll() { + updatePopoverPosition(targetRef.current, alignment); + } + window.addEventListener("resize", handleWindowResize); - return () => window.removeEventListener("resize", handleWindowResize); + window.addEventListener("scroll", handleWindowScroll); + + return () => { + window.removeEventListener("resize", handleWindowResize); + window.removeEventListener("scroll", handleWindowScroll); + }; }, [isOpen, targetRef, alignment]); return { From c293e1801087618252e9d4acc84cc22c084992ca Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 16 Aug 2025 13:01:49 +0900 Subject: [PATCH 136/253] =?UTF-8?q?fix=20[]=20Popover=EB=A5=BC=20=EB=B2=97?= =?UTF-8?q?=EC=96=B4=EB=82=98=EB=8A=94=20content=EB=8A=94=20=EC=88=A8?= =?UTF-8?q?=EA=B9=80=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/popover/popover.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/popover/popover.jsx b/src/components/popover/popover.jsx index 08fec9e..e6d31e8 100644 --- a/src/components/popover/popover.jsx +++ b/src/components/popover/popover.jsx @@ -19,6 +19,7 @@ const StyledPopover = styled.div` border: 1px solid #b6b6b6; background-color: white; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08); + overflow: hidden; `; function Popover({ id, alignment, action, children }) { From 67cf3bc9d441918bcabc026b23c12389fa3f3b15 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 16 Aug 2025 13:48:45 +0900 Subject: [PATCH 137/253] =?UTF-8?q?refactor=20[#46]=20Dropdown=20rect=20?= =?UTF-8?q?=EB=B0=8F=20popover=20position=EC=97=90=20=EA=B8=B0=EB=B3=B8?= =?UTF-8?q?=EA=B0=92=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Media query match가 변경되면서 component가 다시 생성될 때, rect 또는 position이 `undefined`가 되어 발생할 수 있는 잠재적인 error를 방지합니다. --- src/hooks/use-dropdown.jsx | 8 +++++--- src/hooks/use-popover.jsx | 6 ++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/hooks/use-dropdown.jsx b/src/hooks/use-dropdown.jsx index 7e932a4..051dfe6 100644 --- a/src/hooks/use-dropdown.jsx +++ b/src/hooks/use-dropdown.jsx @@ -1,7 +1,9 @@ import { useEffect, useRef, useState } from "react"; import { usePortal } from "./use-portal"; -function makeRect({ x, y, width } = { x: 0, y: 0, width: 0 }) { +const DEFAULT_RECT = { x: 0, y: 0, width: 0 }; + +function makeRect({ x, y, width }) { return { origin: { x, y }, size: { width }, @@ -10,7 +12,7 @@ function makeRect({ x, y, width } = { x: 0, y: 0, width: 0 }) { function calculateDropdownRect(target) { if (!target) { - return makeRect(); + return DEFAULT_RECT; } const targetRect = target.getBoundingClientRect(); @@ -26,7 +28,7 @@ function calculateDropdownRect(target) { function useDropdown({ id, type }) { const key = `${type}_${id}`; const { isOpen, setIsOpen } = usePortal({ key }); - const [dropdownRect, setDropdownRect] = useState(); + const [dropdownRect, setDropdownRect] = useState(DEFAULT_RECT); const targetRef = useRef(); diff --git a/src/hooks/use-popover.jsx b/src/hooks/use-popover.jsx index d4ec738..1d775fb 100644 --- a/src/hooks/use-popover.jsx +++ b/src/hooks/use-popover.jsx @@ -2,9 +2,11 @@ import { useEffect, useRef, useState } from "react"; import POPOVER_ALIGNMENT from "../components/popover/popover-alignment"; import { usePortal } from "./use-portal"; +const DEFAULT_POSITION = { top: 0, left: 0, right: 0 }; + function calculatePopoverPosition(target, alignment) { if (!target) { - return { top: 0, left: 0, right: 0 }; + return DEFAULT_POSITION; } const targetRect = target.getBoundingClientRect(); @@ -27,7 +29,7 @@ function calculatePopoverPosition(target, alignment) { function usePopover({ id, type, alignment }) { const key = `${type}_${id}`; const { isOpen, setIsOpen } = usePortal({ key }); - const [position, setPopoverPosition] = useState(); + const [position, setPopoverPosition] = useState(DEFAULT_POSITION); const targetRef = useRef(); const updatePopoverPosition = (target, alignment) => { From 174847949ec0af6a3380fe537fc456b1e8b9f1c6 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Mon, 18 Aug 2025 16:16:59 +0900 Subject: [PATCH 138/253] =?UTF-8?q?feat=20[#55]=20Dropdown=20option?= =?UTF-8?q?=EC=97=90=20font=EB=A5=BC=20=EB=8B=A4=EB=A5=B4=EA=B2=8C=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=ED=95=A0=20=EC=88=98=20=EC=9E=88=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 이 component는 rolling 에서만 사용할 목적으로 개발되었으므로, 모든 style을 변경할 수 있게 허용하지는 않습니다. - 나중에 다른 custom style 요구사항이 생기면 대응하기 위해 비슷한 방법으로 수정될 수 있습니다. --- .../text-field/dropdown-input/dropdown-input.jsx | 3 ++- .../text-field/dropdown-input/dropdown-option.jsx | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/components/text-field/dropdown-input/dropdown-input.jsx b/src/components/text-field/dropdown-input/dropdown-input.jsx index 880b506..775710c 100644 --- a/src/components/text-field/dropdown-input/dropdown-input.jsx +++ b/src/components/text-field/dropdown-input/dropdown-input.jsx @@ -131,8 +131,9 @@ function DropdownInput({ - {option} + {option.title ?? option} ))} diff --git a/src/components/text-field/dropdown-input/dropdown-option.jsx b/src/components/text-field/dropdown-input/dropdown-option.jsx index 6619019..2f976cd 100644 --- a/src/components/text-field/dropdown-input/dropdown-option.jsx +++ b/src/components/text-field/dropdown-input/dropdown-option.jsx @@ -1,11 +1,12 @@ import styled from "styled-components"; import Colors from "../../color/colors"; -const DropdownOption = styled.div` +const StyledDropdownOption = styled.div` width: calc(100% - 2px); border: none; background: none; padding: 12px 16px; + ${({ style }) => style?.fontFamily ?? ""} font-size: 16px; font-weight: 400; line-height: 26px; @@ -17,4 +18,8 @@ const DropdownOption = styled.div` } `; +function DropdownOption({ children, ...props }) { + return {children}; +} + export default DropdownOption; From bb77b09b3324215b875ecb7387fce5fead39f405 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Mon, 18 Aug 2025 16:18:52 +0900 Subject: [PATCH 139/253] =?UTF-8?q?feat=20[#55]=20Dropdown=20option?= =?UTF-8?q?=EC=97=90=20fontFamily=EB=A5=BC=20=EC=84=A4=EC=A0=95=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EC=98=88=EC=8B=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/test-page.jsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index f691c69..1707abe 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -201,7 +201,12 @@ function TestPage() { placeholder="Placeholder" value={option2} error={dropdown2Error} - options={["Option 1", "Option 2", "Option 3", "Option 4"]} + options={[ + { title: "Option 1", fontFamily: "system-ui" }, + { title: "Option 2", fontFamily: "Roboto" }, + { title: "Option 3", fontFamily: "Helvetica Neue" }, + { title: "Option 4", fontFamily: "Segoe UI" }, + ]} onSelect={handleDropdownSelect2} />
From 4570077640985e5eaceb736ccfec27648b65fc97 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Mon, 18 Aug 2025 17:19:08 +0900 Subject: [PATCH 140/253] =?UTF-8?q?config=20[#50]=20Vercel=20redirection?= =?UTF-8?q?=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vercel.json | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 vercel.json diff --git a/vercel.json b/vercel.json new file mode 100644 index 0000000..3a48e56 --- /dev/null +++ b/vercel.json @@ -0,0 +1,3 @@ +{ + "rewrites": [{ "source": "/(.*)", "destination": "/" }] +} From 4bd5ec8056fe925df6cfa6f4c624394413807d1a Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Tue, 19 Aug 2025 09:02:09 +0900 Subject: [PATCH 141/253] =?UTF-8?q?config=20[#50]=20=ED=8C=80=20repo?= =?UTF-8?q?=EC=9D=98=20`develop`=20branch=EB=A5=BC=20=EA=B0=9C=EC=9D=B8=20?= =?UTF-8?q?repo=EB=A1=9C=20=EB=8F=99=EA=B8=B0=ED=99=94=ED=95=98=EB=8A=94?= =?UTF-8?q?=20workflow=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Vercel의 조직 repository 유료 plan을 우회하기 위해 forked repo를 통해 배포되도록 설정 --- .github/workflows/sync.yaml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .github/workflows/sync.yaml diff --git a/.github/workflows/sync.yaml b/.github/workflows/sync.yaml new file mode 100644 index 0000000..737c68d --- /dev/null +++ b/.github/workflows/sync.yaml @@ -0,0 +1,31 @@ +name: Synchronize to forked repo +on: + push: + branches: + - develop +jobs: + sync: + name: Sync forked repo + runs-on: ubuntu-latest + + steps: + - name: Checkout develop + uses: actions/checkout@v4 + with: + token: ${{ secrets.AUTO_ACTIONS }} + fetch-depth: 0 + ref: develop + + - name: Add remote-url + run: | + git remote add forked-repo https://cskime:${{ secrets.AUTO_ACTIONS }}@github.com/cskime/rolling + git config user.name cskime + git config user.email ${{ secrets.EMAIL }} + + - name: Push changes to forked-repo + run: | + git push -f forked-repo develop + + - name: Clean up + run: | + git remote remove forked-repo From e32efd93d9913069db7a59be5602484032b2dabe Mon Sep 17 00:00:00 2001 From: luli Date: Mon, 18 Aug 2025 02:42:39 +0900 Subject: [PATCH 142/253] =?UTF-8?q?[#53]=20=EC=9D=B4=EB=AF=B8=EC=A7=80?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=20=EC=A0=9C=EC=99=B8=20desktop=EB=B2=84?= =?UTF-8?q?=EC=A0=84=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 이모지등ㄷ 추가사항 적용 --- .../components/rolling-paper-list.jsx | 76 +++++++++++++++++-- src/pages/test_recipients_data.json | 12 +-- 2 files changed, 77 insertions(+), 11 deletions(-) diff --git a/src/features/rolling-paper/components/rolling-paper-list.jsx b/src/features/rolling-paper/components/rolling-paper-list.jsx index 8bb4608..d01ec30 100644 --- a/src/features/rolling-paper/components/rolling-paper-list.jsx +++ b/src/features/rolling-paper/components/rolling-paper-list.jsx @@ -32,15 +32,16 @@ const CardContainer = styled.div` const CardItem = styled.div` width: 275px; - height: 260px; + min-height: 260px; border-radius: 16px; text-align: left; padding: 30px 24px 20px 24px; border: 1px solid rgba(0, 0, 0, 0.1); box-shadow: 0px 2px 12px 0px rgba(0, 0, 0, 0.08); - display: grid; - grid-template-rows: 1fr 1fr auto; + display: flex; + gap: 12px; + flex-direction: column; background: ${(props) => props.$backgroundImageURL @@ -153,8 +154,54 @@ const MessageCountText = styled.span` } `; -const CardEmoji = styled.div` +const CardEmojiBox = styled.div` border-top: 1px solid rgba(0, 0, 0, 0.1); + padding-top: 17px; + margin-top: auto; + + display: flex; + flex-wrap: wrap; + row-gap: 5px; +`; + +const CardEmoji = styled.span` + background-color: rgba(0, 0, 0, 0.54); + border-radius: 32px; + color: #ffffff; + padding: 8px 12px; + margin-right: 8px; + + position: relative; + white-space: nowrap; + overflow: hidden; + + min-width: ${(props) => (props.$isLong ? "60px" : "auto")}; + max-width: ${(props) => (props.$isLong ? "44px" : "none")}; + + transition: max-width 0.3s ease, z-index 0s; + + &:hover { + max-width: 200px; + z-index: 100; + position: relative; + } +`; + +const HiddenCount = styled.span` + display: inline; + + .show-on-hover { + display: none; + } + + ${CardEmoji}:hover & { + .show-on-hover { + display: inline; + } + .hide-on-hover { + display: none; + } + } `; const NextButtonWrapper = styled.div` @@ -206,7 +253,26 @@ function RollingPaperList({ cardData, totalPages, currentPage, onTurnCards }) { > {item.messageCount}명이 작성했어요! - {item.topReactions.map((emoji) => emoji.emoji)} + + {item.topReactions.map((emoji, index) => { + const countLength = emoji.count.toString().length; + const isLongCount = countLength > 2; + + return ( + + {emoji.emoji} + {isLongCount ? ( + + + + {emoji.count} + + ) : ( + ` ${emoji.count}` + )} + + ); + })} + ))} {currentPage > 0 && ( diff --git a/src/pages/test_recipients_data.json b/src/pages/test_recipients_data.json index 056ede3..8d2dbf0 100644 --- a/src/pages/test_recipients_data.json +++ b/src/pages/test_recipients_data.json @@ -22,7 +22,7 @@ "topReactions": [ { "emoji": "🥹", - "count": 159 + "count": 2 }, { "emoji": "😁", @@ -120,11 +120,11 @@ "topReactions": [ { "emoji": "😀", - "count": 46 + "count": 333 }, { "emoji": "🎉", - "count": 585 + "count": 333 }, { "emoji": "😁", @@ -212,15 +212,15 @@ "topReactions": [ { "emoji": "❤️", - "count": 847 + "count": 8 }, { "emoji": "😀", - "count": 141 + "count": 12 }, { "emoji": "👍", - "count": 396 + "count": 33 } ] }, From ddb50bab49ecdc3476309157070358bbde25e654 Mon Sep 17 00:00:00 2001 From: luli Date: Tue, 19 Aug 2025 15:02:35 +0900 Subject: [PATCH 143/253] =?UTF-8?q?[#53]=20pr=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Emoji 공통컴포넌트는 일단 주석처리 --- .../components/rolling-paper-list.jsx | 105 ++++++++++-------- 1 file changed, 57 insertions(+), 48 deletions(-) diff --git a/src/features/rolling-paper/components/rolling-paper-list.jsx b/src/features/rolling-paper/components/rolling-paper-list.jsx index d01ec30..848db1a 100644 --- a/src/features/rolling-paper/components/rolling-paper-list.jsx +++ b/src/features/rolling-paper/components/rolling-paper-list.jsx @@ -7,10 +7,11 @@ import { } from "../../../components/button/button"; import BUTTON_SIZE from "../../../components/button/button-size"; import ToggleButton from "../../../components/button/toggle-button"; +import EmojiBadge from "../../../components/badge/emoji-badge"; // import React, { useEffect, useState } from "react"; -import styled from "styled-components"; +import styled, { css } from "styled-components"; const backgroundColors = { beige: "#FFE2AD", @@ -21,13 +22,12 @@ const backgroundColors = { const CardContainer = styled.div` display: grid; - grid-template-columns: 275px 275px 275px 275px; + grid-template-columns: repeat(4, 275px); gap: 20px; width: fit-content; font-family: Pretendard; position: relative; - overflow: visible; `; const CardItem = styled.div` @@ -56,52 +56,9 @@ const CardItem = styled.div` content: ""; position: absolute; z-index: 0; - ${(props) => { - if (!props.$backgroundImageURL) { - if ( - props.$backgroundColor === "purple" || - props.$backgroundColor === "green" - ) { - return ` - width: 336px; - height: 169px; - background-color: ${ - props.$backgroundColor === "purple" - ? "rgba(220,185,255,0.4)" - : "rgba(155, 226, 130, 0.3)" - }; - border-radius: 90.5px; - top: 124px; - left: 133px; - `; - } else if (props.$backgroundColor === "beige") { - return ` - width: 332px; - height: 318px; - border-radius: 51px; - background-color: #ffd382; - top: 124px; - left: 154px; - `; - } else if (props.$backgroundColor === "blue") { - const svgString = ``; - const encodedSvg = encodeURIComponent(svgString); - - return ` - width: 170px; - height: 200px; - background-image: url("data:image/svg+xml,${encodedSvg}"); - background-repeat: no-repeat; - background-position: center; - background-size: contain; - top: 108px; - left: 113px; - `; - } - } - return ""; + ${({ $backgroundImageURL, $backgroundColor }) => { + return $backgroundImageURL ? "" : polygonStyle[$backgroundColor]; }} - } & > * { position: relative; @@ -109,6 +66,51 @@ const CardItem = styled.div` } `; +const ellipseStyle = css` + width: 336px; + height: 169px; + background-color: ${({ $backgroundColor }) => + $backgroundColor === "purple" + ? "rgba(220,185,255,0.4)" + : "rgba(155, 226, 130, 0.3)"}; + border-radius: 90.5px; + top: 124px; + left: 133px; +`; + +const roundedRectangleStyle = css` + width: 332px; + height: 318px; + border-radius: 51px; + background-color: #ffd382; + top: 124px; + left: 154px; +`; + +function getTriangleBackgroundImage() { + const svgString = ``; + const encodedSvg = encodeURIComponent(svgString); + return `url("data:image/svg+xml,${encodedSvg}")`; +} + +const roundedTriangleStyle = css` + width: 170px; + height: 200px; + background-image: ${getTriangleBackgroundImage}; + background-repeat: no-repeat; + background-position: center; + background-size: contain; + top: 108px; + left: 113px; +`; + +const polygonStyle = { + beige: roundedRectangleStyle, + purple: ellipseStyle, + green: ellipseStyle, + blue: roundedTriangleStyle, +}; + const CardTitle = styled.h2` margin: 0; font-size: 24px; @@ -162,6 +164,7 @@ const CardEmojiBox = styled.div` display: flex; flex-wrap: wrap; row-gap: 5px; + z-index: 2; `; const CardEmoji = styled.span` @@ -259,6 +262,12 @@ function RollingPaperList({ cardData, totalPages, currentPage, onTurnCards }) { const isLongCount = countLength > 2; return ( + // + {emoji.emoji} {isLongCount ? ( From f8e846ee46091750e96a65c89f65597a8fdc623b Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Mon, 18 Aug 2025 13:59:21 +0900 Subject: [PATCH 144/253] =?UTF-8?q?refactor=20#29=20trimmed=20=EC=A7=80?= =?UTF-8?q?=EC=97=AD=EB=B3=80=EC=88=98=20->=20=EC=A0=84=EC=97=AD=EB=B3=80?= =?UTF-8?q?=EC=88=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/create-post-page.jsx | 9 +++++++-- src/pages/send-message-page.jsx | 8 +++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/pages/create-post-page.jsx b/src/pages/create-post-page.jsx index 67202af..cac37ed 100644 --- a/src/pages/create-post-page.jsx +++ b/src/pages/create-post-page.jsx @@ -60,8 +60,9 @@ function CreatePostPage() { setNameError(""); // 값 입력 중 에러 없애기 }; + const trimmed = name.trim(); + const handleBlur = () => { - const trimmed = name.trim(); if (trimmed === "") { setNameError("값을 입력해 주세요"); } else if (trimmed !== name) { @@ -79,11 +80,15 @@ function CreatePostPage() { }; const handleCreate = () => { + const finalName = trimmed; const randomID = Math.floor(Math.random() * 10000); + if (finalName !== name) { + return; + } navigate(`/post/${randomID}`); }; - const canCreate = name.trim() !== ""; + const canCreate = trimmed !== ""; return ( diff --git a/src/pages/send-message-page.jsx b/src/pages/send-message-page.jsx index 1c5f84e..4d07b18 100644 --- a/src/pages/send-message-page.jsx +++ b/src/pages/send-message-page.jsx @@ -88,10 +88,12 @@ function SendMessagePage() { } }; + const trimmed = name.trim(); + const handleBlur = () => { - if (name.trim() === "") { + if (trimmed === "") { setNameError("값을 입력해 주세요"); - } else if (name !== name.trim()) { + } else if (trimmed !== name.trim()) { setNameError("공백 없이 입력해 주세요"); // 텍스트 앞 뒤 공백 에러 처리(임시) } }; @@ -114,7 +116,7 @@ function SendMessagePage() { navigate(`/post/${randomID}`); }; - const canCreate = name.trim() !== ""; + const canCreate = trimmed !== ""; return ( From 13c1e5a9fe3d4c704bb1dd7ff102c5307d68ef05 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Tue, 19 Aug 2025 23:46:27 +0900 Subject: [PATCH 145/253] =?UTF-8?q?refactor=20#62=20name=20input=20field?= =?UTF-8?q?=20=EA=B0=92=EC=9D=84=20~=20->=20=EC=9D=B4=EB=A6=84=EC=9D=84=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=ED=95=B4=20=EC=A3=BC=EC=84=B8=EC=9A=94=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/send-message-page.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/send-message-page.jsx b/src/pages/send-message-page.jsx index 4d07b18..b8f2532 100644 --- a/src/pages/send-message-page.jsx +++ b/src/pages/send-message-page.jsx @@ -92,8 +92,8 @@ function SendMessagePage() { const handleBlur = () => { if (trimmed === "") { - setNameError("값을 입력해 주세요"); - } else if (trimmed !== name.trim()) { + setNameError("이름을 입력해 주세요"); + } else if (trimmed !== name) { setNameError("공백 없이 입력해 주세요"); // 텍스트 앞 뒤 공백 에러 처리(임시) } }; From 38d8114a40a2d040b8caeb3e01e619009dc86997 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Wed, 20 Aug 2025 00:22:05 +0900 Subject: [PATCH 146/253] =?UTF-8?q?refactor=20#62=20=EC=9D=B4=EB=A6=84?= =?UTF-8?q?=EC=97=90=20=EC=95=9E=20=EB=92=A4=20=EA=B3=B5=EB=B0=B1=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=20=ED=9B=84=20blur=20=EC=8B=9C=20=EA=B3=B5?= =?UTF-8?q?=EB=B0=B1=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/create-post-page.jsx | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/pages/create-post-page.jsx b/src/pages/create-post-page.jsx index cac37ed..0bd1f21 100644 --- a/src/pages/create-post-page.jsx +++ b/src/pages/create-post-page.jsx @@ -60,13 +60,11 @@ function CreatePostPage() { setNameError(""); // 값 입력 중 에러 없애기 }; - const trimmed = name.trim(); - const handleBlur = () => { + const trimmed = name.trim(); + setName(trimmed); if (trimmed === "") { - setNameError("값을 입력해 주세요"); - } else if (trimmed !== name) { - setNameError("앞 뒤 공백 없이 입력해 주세요"); // 텍스트 앞 뒤 공백 에러 처리(임시) + setNameError("이름을 입력해 주세요"); } }; @@ -80,15 +78,11 @@ function CreatePostPage() { }; const handleCreate = () => { - const finalName = trimmed; const randomID = Math.floor(Math.random() * 10000); - if (finalName !== name) { - return; - } navigate(`/post/${randomID}`); }; - const canCreate = trimmed !== ""; + const canCreate = name.trim() !== ""; return ( From f1f684d0e5f76534d4f3e86da607a2920235dc85 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Wed, 20 Aug 2025 00:30:38 +0900 Subject: [PATCH 147/253] =?UTF-8?q?refactro=20#62=20send=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EC=9D=B4=EB=A6=84=20=EA=B3=B5=EB=B0=B1=20?= =?UTF-8?q?=EC=9E=90=EB=8F=99=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/send-message-page.jsx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/pages/send-message-page.jsx b/src/pages/send-message-page.jsx index b8f2532..9731c89 100644 --- a/src/pages/send-message-page.jsx +++ b/src/pages/send-message-page.jsx @@ -88,13 +88,11 @@ function SendMessagePage() { } }; - const trimmed = name.trim(); - const handleBlur = () => { + const trimmed = name.trim(); + setName(trimmed); if (trimmed === "") { setNameError("이름을 입력해 주세요"); - } else if (trimmed !== name) { - setNameError("공백 없이 입력해 주세요"); // 텍스트 앞 뒤 공백 에러 처리(임시) } }; @@ -116,7 +114,7 @@ function SendMessagePage() { navigate(`/post/${randomID}`); }; - const canCreate = trimmed !== ""; + const canCreate = name.trim() !== ""; return ( From dddaf38b102eaadf027762b6260680c3a1d8c8c3 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Wed, 20 Aug 2025 01:42:45 +0900 Subject: [PATCH 148/253] =?UTF-8?q?=EC=B2=B4=ED=81=AC=20=EC=95=84=EC=9D=B4?= =?UTF-8?q?=EC=BD=98=20=EC=A0=9C=EC=99=B8=ED=95=9C=20=EB=B0=B0=EA=B2=BD?= =?UTF-8?q?=EB=A7=8C=20=ED=88=AC=EB=AA=85=EB=8F=84=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/option/background-select.jsx | 55 ++++++++++----------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/src/components/option/background-select.jsx b/src/components/option/background-select.jsx index cc6cb27..f844408 100644 --- a/src/components/option/background-select.jsx +++ b/src/components/option/background-select.jsx @@ -17,9 +17,25 @@ const BackgroundWrapper = styled.div` const OptionItem = styled.div` width: 168px; height: 168px; - border-radius: 8px; cursor: pointer; - background-color: ${({ type, color }) => (type === "color" ? color : "none")}; + position: relative; +`; + +const CheckedIcon = styled(OutlinedButton)` + background-color: ${Colors.gray(500)}; + box-shadow: none; + border-radius: 50%; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); +`; + +const BackgroundOverlay = styled.div` + height: 100%; + border-radius: 8px; + background-color: ${({ type, color }) => + type === "color" ? color : "transparent"}; background-image: ${({ type, url }) => type === "image" ? `url(${url})` : "none"}; background-position: center; @@ -28,18 +44,6 @@ const OptionItem = styled.div` opacity: ${({ selected }) => (selected ? 0.3 : 1)}; `; -const CircleButtonWrapper = styled.div` - height: 100%; - overflow: hidden; - display: flex; - justify-content: center; - align-items: center; - - & > button { - border-radius: 50%; - } -`; - function BackgroundSelect({ type, selected, onSelect }) { const [imageUrls, setImageUrls] = useState([]); @@ -89,22 +93,15 @@ function BackgroundSelect({ type, selected, onSelect }) { return ( {options.map((option, index) => ( - onSelect(index)} - selected={selected === index} - > + onSelect(index)}> + {selected === index && ( - - - + )} ))} From 4cfd81d62bc198f0af166e136eea2fc9e759ecbb Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Wed, 20 Aug 2025 02:31:16 +0900 Subject: [PATCH 149/253] =?UTF-8?q?refactor=20#62=20=EB=93=9C=EB=A1=AD?= =?UTF-8?q?=EB=8B=A4=EC=9A=B4=20=EC=98=B5=EC=85=98=20=EC=BB=A4=EC=8A=A4?= =?UTF-8?q?=ED=85=80=20=20=ED=8F=B0=ED=8A=B8=20=EC=8A=A4=ED=83=80=EC=9D=BC?= =?UTF-8?q?=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/send-message-page.jsx | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/pages/send-message-page.jsx b/src/pages/send-message-page.jsx index 9731c89..94db95a 100644 --- a/src/pages/send-message-page.jsx +++ b/src/pages/send-message-page.jsx @@ -75,7 +75,10 @@ function SendMessagePage() { const [relationOption, setRelationOption] = useState("지인"); const [selectedAvatar, setSelectedAvatar] = useState(null); const [content, setContent] = useState("I am your reach text editor."); - const [fontOption, setFontOption] = useState("Noto Sans"); + const [selectedFont, setSelectedFont] = useState({ + title: "Noto Sans", + fontFamily: "Noto Sans", + }); const navigate = useNavigate(); const handleChange = (e) => { @@ -116,6 +119,13 @@ function SendMessagePage() { const canCreate = name.trim() !== ""; + const fontOptions = [ + { title: "Noto Sans", fontFamily: "Noto Sans" }, + { title: "Pretendard", fontFamily: "Pretendard" }, + { title: "나눔고딕", fontFamily: "Nanum Ghthic" }, + { title: "나눔손글씨 펜체", fontFamily: "Nanum Pen Script" }, + ]; + return ( @@ -176,7 +186,7 @@ function SendMessagePage() { }} value={content} onChange={(value) => setContent(value)} - font={fontOption} + font={selectedFont.fontFamily} />
@@ -185,15 +195,16 @@ function SendMessagePage() { { + const selected = fontOptions.find( + (fontOption) => fontOption.title === selectedFontOption + ); + setSelectedFont(selected); + }} + style={{ fontFamily: selectedFont.fontFamily }} /> From 09cf69aabbf59f23cf39ba05418352568ddead78 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Wed, 20 Aug 2025 02:55:12 +0900 Subject: [PATCH 150/253] =?UTF-8?q?fix=20#62=20=ED=85=8D=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20=EC=97=90=EB=94=94=ED=84=B0=20=EB=82=B4=EC=9A=A9=20=EC=97=86?= =?UTF-8?q?=EC=9D=84=20=EC=8B=9C=20=EB=B2=84=ED=8A=BC=20=EB=B9=84=ED=99=9C?= =?UTF-8?q?=EC=84=B1=ED=99=94=20=EC=A1=B0=EA=B1=B4=20=ED=8F=AC=ED=95=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/send-message-page.jsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pages/send-message-page.jsx b/src/pages/send-message-page.jsx index 94db95a..b368f0d 100644 --- a/src/pages/send-message-page.jsx +++ b/src/pages/send-message-page.jsx @@ -117,7 +117,9 @@ function SendMessagePage() { navigate(`/post/${randomID}`); }; - const canCreate = name.trim() !== ""; + const canCreate = + name.trim() !== "" && content.replace(/<[^>]+>/g, "").trim() !== ""; + // 정규식 유효성 검사로 html 태그 찾기("<"로 시작해서 ">"로 끝나는 문자 중 > 를 제외한(^ not) 모든 문자 제외) const fontOptions = [ { title: "Noto Sans", fontFamily: "Noto Sans" }, From 6fbbf266569fd5bde8d3edd3c17a3ea9bd8505c5 Mon Sep 17 00:00:00 2001 From: luli Date: Tue, 19 Aug 2025 15:07:57 +0900 Subject: [PATCH 151/253] =?UTF-8?q?[#53]=20message-list.jsx=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 왜 삭제해도 자꾸 살아나는지 알수없음 --- src/pages/message-list.jsx | 183 ------------------------------------- 1 file changed, 183 deletions(-) delete mode 100644 src/pages/message-list.jsx diff --git a/src/pages/message-list.jsx b/src/pages/message-list.jsx deleted file mode 100644 index 1635722..0000000 --- a/src/pages/message-list.jsx +++ /dev/null @@ -1,183 +0,0 @@ -import ArrowButton from "../components/button/arrow-button"; -import ARROW_BUTTON_DIRECTION from "../components/button/arrow-button-direction"; -import { - OutlinedButton, - PrimaryButton, - SecondaryButton, -} from "../components/button/button"; -import BUTTON_SIZE from "../components/button/button-size"; -import ToggleButton from "../components/button/toggle-button"; - -import React, { useEffect, useState } from "react"; -import axiosInstance from "../api/axios-instance"; -import styled from "styled-components"; - -/* styled components */ -const TopContainer = styled.div` - text-align: center; -`; - -const CardSection = styled.section` - justify-self: center; -`; - -const CardTitle = styled.h2` - text-align: left; -`; - -const CardContainer = styled.div` - border: 1px solid red; - display: grid; - grid-template-columns: 275px 275px 275px 275px; - gap: 20px; - width: fit-content; - - position: relative; - overflow: visible; -`; - -const CardItem = styled.div` - width: 275px; - height: 260px; - border: 1px solid red; -`; - -const NextBtnWpr = styled.div` - position: absolute; - right: -20px; - top: 50%; - transform: translateY(-50%); - z-index: 10; -`; - -const PrevBtnWpr = styled.div` - position: absolute; - left: -20px; - top: 50%; - transform: translateY(-50%); - z-index: 10; -`; - -const MakingBtn = styled(PrimaryButton)` - margin-top: 64px; - font-weight: 400; - padding: 14px 60px; -`; - -/* 그냥 출력 테스트용 */ -const testData = [ - { id: 1, to: "test1", messageCount: 1 }, - { id: 2, to: "test2", messageCount: 5 }, - { id: 3, to: "test3", messageCount: 10 }, - { id: 4, to: "test4", messageCount: 2 }, - { id: 5, to: "test5", messageCount: 3 }, - { id: 6, to: "test6", messageCount: 1 }, -]; - -function ShowMessageList() { - const [pprCurrentPage, setPprCurrentPage] = useState(0); // 인기카드 - const [currentPage, setCurrentPage] = useState(0); // 일반카드 - const [pprShowCards, setPprShowCards] = useState([]); - const [showCards, setShowCards] = useState([]); - const cardCount = 4; - - /* axios로 데이터 가져온다고 가정 */ - // axiosInstance - // .get("/18-3/recipients/?limit=5&offset=20") - // .then((res) => { - // console.log(res.data); - // }) - // .catch(console.error); - - const totalPages = Math.ceil(testData.length / cardCount); - - useEffect(() => { - const strtPageNum = currentPage * cardCount; - const endPageNum = strtPageNum + cardCount; - - const pprStrtPageNum = pprCurrentPage * cardCount; - const pprEndPageNum = pprStrtPageNum + cardCount; - - /* createdAt(생성된 시점)에 따라서 정렬 */ - setShowCards(testData.slice(strtPageNum, endPageNum)); - - /* 여기서 messageCount(메시지수)에 따라서 정렬 */ - setPprShowCards(testData.slice(pprStrtPageNum, pprEndPageNum)); - }, [pprCurrentPage, currentPage]); - - const nextPage = (mode = null) => { - if (mode) { - console.log("pprnext"); - if (pprCurrentPage < totalPages - 1) { - setPprCurrentPage((pprCurrentNum) => pprCurrentNum + 1); - } - } else { - console.log("justnext"); - if (currentPage < totalPages - 1) { - setCurrentPage((currentNum) => currentNum + 1); - } - } - }; - - const prevPage = (mode = null) => { - if (mode) { - console.log("pprprev"); - if (pprCurrentPage > 0) { - setPprCurrentPage((pprCurrentNum) => pprCurrentNum - 1); - } - } else { - console.log("justprev"); - if (currentPage > 0) { - setCurrentPage((currentNum) => currentNum - 1); - } - } - }; - - return ( - - /* navi 들어갈 자리 */ -
- - 인기 롤링 페이퍼 🔥 - - {pprShowCards.map((item) => ( - {item.to} // 테스트용 - ))} - {pprCurrentPage > 0 ? ( - prevPage("ppr")}> - - - ) : null} - {pprCurrentPage < totalPages - 1 ? ( - nextPage("ppr")}> - - - ) : null} - - - - - 최근에 만든 롤링 페이퍼 ⭐ - - {showCards.map((item) => ( - {item.to} // 테스트용 - ))} - {currentPage > 0 ? ( - prevPage()}> - - - ) : null} - {currentPage < totalPages - 1 ? ( - nextPage()}> - - - ) : null} - - -
- -
- ); -} - -export default ShowMessageList; From 9436b5f6ff87bdbd0af2a600f8399f02a18b9c52 Mon Sep 17 00:00:00 2001 From: luli Date: Tue, 19 Aug 2025 15:16:25 +0900 Subject: [PATCH 152/253] =?UTF-8?q?[#53]=20app.jsx=EC=AA=BD=20rolling-pape?= =?UTF-8?q?r-list-page=20impor=20url=EB=8F=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit app.jsx쪽 rolling-paper-list-page impor url도 수정 --- src/app.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app.jsx b/src/app.jsx index 2ee741b..3f5d4c7 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -4,7 +4,7 @@ import ContentLayout from "./layouts/content-layout"; import OnboardingLayout from "./layouts/onboarding-layout"; import CreatePostPage from "./pages/create-post-page"; import MainPage from "./pages/main-page"; -import MessagePage from "./pages/message-list"; +import MessagePage from "./pages/rolling-paper-list-page"; import MessagesPage from "./pages/messages-page"; import SendMessagePage from "./pages/send-message-page"; import TestPage from "./pages/test-page"; From a0a5ab02ecc9a2913b57fc01efc319778c006b77 Mon Sep 17 00:00:00 2001 From: luli Date: Tue, 19 Aug 2025 15:24:03 +0900 Subject: [PATCH 153/253] =?UTF-8?q?[#53]=20=EB=82=98=EB=8F=84=20=EB=A7=8C?= =?UTF-8?q?=EB=93=A4=EC=96=B4=EB=B3=B4=EA=B8=B0=EB=B2=84=ED=8A=BC=20url?= =?UTF-8?q?=EC=97=B0=EA=B2=B0,=20top-=20margin=EC=A1=B0=EA=B8=88=20?= =?UTF-8?q?=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 나도 만들어보기버튼 url연결, top- margin조금 조정 --- src/pages/rolling-paper-list-page.jsx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/pages/rolling-paper-list-page.jsx b/src/pages/rolling-paper-list-page.jsx index 5fe8958..e85306e 100644 --- a/src/pages/rolling-paper-list-page.jsx +++ b/src/pages/rolling-paper-list-page.jsx @@ -7,6 +7,7 @@ import { } from "../components/button/button"; import BUTTON_SIZE from "../components/button/button-size"; import ToggleButton from "../components/button/toggle-button"; +import { useNavigate } from "react-router"; import React, { useEffect, useState } from "react"; // import axiosInstance from "../api/axios-instance"; @@ -17,6 +18,7 @@ import RollingPaperList from "../features/rolling-paper/components/rolling-paper const TopContainer = styled.div` text-align: center; + margin-top: 50px; `; const CardSection = styled.section` @@ -43,6 +45,8 @@ function getCachedImage(url) { } function ShowMessageList() { + const navigate = useNavigate(); + const [testData, setTestData] = useState([]); const [popularDataList, setPopularDataList] = useState([]); const [recentDataList, setRecentDataList] = useState([]); @@ -52,6 +56,10 @@ function ShowMessageList() { const [recentShowCards, setRecentShowCards] = useState([]); const cardCount = 4; + const handleMakingButton = () => { + navigate("/post"); + }; + useEffect(() => { setTestData(testDataFile); // axiosInstance @@ -141,7 +149,11 @@ function ShowMessageList() { /> - + ); } From 091c722f7734536643e4b3cfdd052aa4239f7127 Mon Sep 17 00:00:00 2001 From: luli Date: Wed, 20 Aug 2025 05:09:06 +0900 Subject: [PATCH 154/253] =?UTF-8?q?[#61]=20list=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EB=B0=98=EC=9D=91=ED=98=95=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 타블렛, 모바일 반응형 화면 구현 --- .../components/rolling-paper-list.jsx | 44 ++++++++++- src/pages/rolling-paper-list-page.jsx | 78 +++++++++++++------ 2 files changed, 96 insertions(+), 26 deletions(-) diff --git a/src/features/rolling-paper/components/rolling-paper-list.jsx b/src/features/rolling-paper/components/rolling-paper-list.jsx index 848db1a..72d33e2 100644 --- a/src/features/rolling-paper/components/rolling-paper-list.jsx +++ b/src/features/rolling-paper/components/rolling-paper-list.jsx @@ -8,6 +8,7 @@ import { import BUTTON_SIZE from "../../../components/button/button-size"; import ToggleButton from "../../../components/button/toggle-button"; import EmojiBadge from "../../../components/badge/emoji-badge"; +import { media } from "../../../utils/media"; // import React, { useEffect, useState } from "react"; @@ -28,6 +29,31 @@ const CardContainer = styled.div` font-family: Pretendard; position: relative; + + ${media.tablet} { + display: flex; + gap: 16px; + overflow-x: auto; + scroll-snap-type: x mandatory; + + scrollbar-width: none; // Firefox + -ms-overflow-style: none; // IE && Edge + + max-width: 1199px; + width: 100%; + padding: 0 24px; + } + + ${media.tablet} > div { + flex: 0 0 275px; + scroll-snap-align: start; + } + + ${media.mobile} { + max-width: 767px; + width: 100%; + padding: 0 20px; + } `; const CardItem = styled.div` @@ -51,6 +77,15 @@ const CardItem = styled.div` position: relative; overflow: hidden; + ${media.tablet} { + flex-shrink: 0; + } + + ${media.mobile} { + width: 208px; + height: 232px; + } + /* 배경 도형 */ &::before { content: ""; @@ -172,12 +207,15 @@ const CardEmoji = styled.span` border-radius: 32px; color: #ffffff; padding: 8px 12px; - margin-right: 8px; + margin-right: 5px; position: relative; white-space: nowrap; overflow: hidden; + font-size: 16px; + font-weight: 400; + min-width: ${(props) => (props.$isLong ? "60px" : "auto")}; max-width: ${(props) => (props.$isLong ? "44px" : "none")}; @@ -188,6 +226,10 @@ const CardEmoji = styled.span` z-index: 100; position: relative; } + + ${media.mobile} { + font-size: 14px; + } `; const HiddenCount = styled.span` diff --git a/src/pages/rolling-paper-list-page.jsx b/src/pages/rolling-paper-list-page.jsx index e85306e..457e039 100644 --- a/src/pages/rolling-paper-list-page.jsx +++ b/src/pages/rolling-paper-list-page.jsx @@ -9,12 +9,13 @@ import BUTTON_SIZE from "../components/button/button-size"; import ToggleButton from "../components/button/toggle-button"; import { useNavigate } from "react-router"; -import React, { useEffect, useState } from "react"; +import React, { useEffect, useState, useMemo } from "react"; // import axiosInstance from "../api/axios-instance"; import testDataFile from "./test_recipients_data.json"; import styled from "styled-components"; import RollingPaperList from "../features/rolling-paper/components/rolling-paper-list"; +import { media } from "../utils/media"; const TopContainer = styled.div` text-align: center; @@ -23,16 +24,37 @@ const TopContainer = styled.div` const CardSection = styled.section` justify-self: center; + + ${media.tablet} { + width: 100%; + } `; const CardTitle = styled.h2` text-align: left; + + ${media.tablet} { + margin-left: 24px; + } + + ${media.mobile} { + margin-left: 20px; + } `; const MakingButton = styled(PrimaryButton)` margin-top: 64px; font-weight: 400; padding: 14px 60px; + + ${media.tablet} { + position: absolute; + bottom: 24px; + justify-self: anchor-center; + margin-left: 24px; + margin-right: 24px; + width: calc(100% - 48px); + } `; const cache = {}; @@ -52,9 +74,22 @@ function ShowMessageList() { const [recentDataList, setRecentDataList] = useState([]); const [popularCurrentPage, setPopularCurrentPage] = useState(0); const [recentCurrentPage, setRecentCurrentPage] = useState(0); - const [popularrecentShowCards, setPopularrecentShowCards] = useState([]); - const [recentShowCards, setRecentShowCards] = useState([]); - const cardCount = 4; + const [cardCount, setCardCount] = useState(4); + + useEffect(() => { + const mql = window.matchMedia("(max-width: 1199px)"); + const updateCardCount = (e) => { + if (e.matches) { + setCardCount(null); + } else { + setCardCount(4); + } + }; + + updateCardCount(mql); + mql.addEventListener("change", updateCardCount); + return () => mql.removeEventListener("change", updateCardCount); + }, []); const handleMakingButton = () => { navigate("/post"); @@ -87,30 +122,23 @@ function ShowMessageList() { const sortedRecent = testData .slice() - .sort((a, b) => b.createdAt - a.createdAt); + .sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt)); setRecentDataList(sortedRecent); }, [testData]); - const totalPages = Math.ceil(testData.length / cardCount); + const totalPages = cardCount ? Math.ceil(testData.length / cardCount) : 1; - useEffect(() => { - const startPageNum = recentCurrentPage * cardCount; - const endPageNum = startPageNum + cardCount; - - const popularStartPageNum = popularCurrentPage * cardCount; - const popularEndPageNum = popularStartPageNum + cardCount; - - setPopularrecentShowCards( - popularDataList.slice(popularStartPageNum, popularEndPageNum) - ); - setRecentShowCards(recentDataList.slice(startPageNum, endPageNum)); - }, [ - popularCurrentPage, - recentCurrentPage, - testData, - popularDataList, - recentDataList, - ]); + const popularShowCards = useMemo(() => { + if (!cardCount) return popularDataList; + const start = popularCurrentPage * cardCount; + return popularDataList.slice(start, start + cardCount); + }, [popularDataList, popularCurrentPage, cardCount]); + + const recentShowCards = useMemo(() => { + if (!cardCount) return recentDataList; + const start = recentCurrentPage * cardCount; + return recentDataList.slice(start, start + cardCount); + }, [recentDataList, recentCurrentPage, cardCount]); const handleTurnCards = (direction, mode) => { const current = mode === "popular" ? popularCurrentPage : recentCurrentPage; @@ -132,7 +160,7 @@ function ShowMessageList() { 인기 롤링 페이퍼 🔥 handleTurnCards(direction, "popular")} From a40d241cfa7d8816bb8df69d6c932a2f4ce9493c Mon Sep 17 00:00:00 2001 From: luli Date: Wed, 20 Aug 2025 05:20:57 +0900 Subject: [PATCH 155/253] =?UTF-8?q?[#61]=20=EB=AA=A8=EB=B0=94=EC=9D=BC?= =?UTF-8?q?=ED=99=94=EB=A9=B4=20=EC=B9=B4=EB=93=9C=EB=B0=B0=EA=B2=BD=20?= =?UTF-8?q?=EB=8F=84=ED=98=95=EC=A2=8C=ED=91=9C=20=EC=A1=B0=EA=B8=88=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 모바일화면에서 카드 배경 도형 좌표 조금 변경 --- .../rolling-paper/components/rolling-paper-list.jsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/features/rolling-paper/components/rolling-paper-list.jsx b/src/features/rolling-paper/components/rolling-paper-list.jsx index 72d33e2..17c6c27 100644 --- a/src/features/rolling-paper/components/rolling-paper-list.jsx +++ b/src/features/rolling-paper/components/rolling-paper-list.jsx @@ -111,6 +111,10 @@ const ellipseStyle = css` border-radius: 90.5px; top: 124px; left: 133px; + + ${media.mobile} { + left: 100.6px; + } `; const roundedRectangleStyle = css` @@ -120,6 +124,10 @@ const roundedRectangleStyle = css` background-color: #ffd382; top: 124px; left: 154px; + + ${media.mobile} { + left: 121.6px; + } `; function getTriangleBackgroundImage() { @@ -137,6 +145,10 @@ const roundedTriangleStyle = css` background-size: contain; top: 108px; left: 113px; + + ${media.mobile} { + left: 60.6px; + } `; const polygonStyle = { @@ -185,6 +197,7 @@ const OverProfile = styled.div` const MessageCountText = styled.span` color: ${(props) => props.$fontColor || "black"}; + z-index: 1; em { font-weight: 700; font-style: normal; From 86171286829df641a36cbeba17b2991f69abea3e Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 16 Aug 2025 12:44:05 +0900 Subject: [PATCH 156/253] =?UTF-8?q?refactor=20[#34]=20=EC=A4=91=EB=B3=B5?= =?UTF-8?q?=EB=90=98=EB=8A=94=20=EC=BD=94=EB=93=9C=EB=A5=BC=20=EB=B3=80?= =?UTF-8?q?=EC=88=98=EB=A1=9C=20=EC=B6=94=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/rolling-paper-header.jsx | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/features/rolling-paper/components/rolling-paper-header.jsx b/src/features/rolling-paper/components/rolling-paper-header.jsx index 0552e44..748c14f 100644 --- a/src/features/rolling-paper/components/rolling-paper-header.jsx +++ b/src/features/rolling-paper/components/rolling-paper-header.jsx @@ -103,19 +103,15 @@ const StyledRollingPaperHeader = styled.div` function RollingPaperHeader({ recipientName, messages, reactions }) { const { isDesktop, isMobile } = useMedia(); + const name = {`To. ${recipientName}`}; + return ( {isMobile && ( - - {`To. ${recipientName}`} - + {name} )} - {isMobile || ( -
- {`To. ${recipientName}`} -
- )} + {isMobile ||
{name}
} {isDesktop && ( From 375fe3876debe603f4e293a17df7b499fb223e1f Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 16 Aug 2025 12:51:01 +0900 Subject: [PATCH 157/253] =?UTF-8?q?config=20[#34]=20`emoji-picker-react`?= =?UTF-8?q?=20package=20=EC=84=A4=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 22 ++++++++++++++++++++++ package.json | 1 + 2 files changed, 23 insertions(+) diff --git a/package-lock.json b/package-lock.json index d602993..c9389d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.0", "dependencies": { "axios": "^1.11.0", + "emoji-picker-react": "^4.13.2", "react": "^19.1.1", "react-dom": "^19.1.1", "react-quill-new": "^3.6.0", @@ -1791,6 +1792,21 @@ "dev": true, "license": "ISC" }, + "node_modules/emoji-picker-react": { + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/emoji-picker-react/-/emoji-picker-react-4.13.2.tgz", + "integrity": "sha512-azaJQLTshEOZVhksgU136izJWJyZ4Clx6xQ6Vctzk1gOdPPAUbTa/JYDwZJ8rh97QxnjpyeftXl99eRlYr3vNA==", + "license": "MIT", + "dependencies": { + "flairup": "1.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16" + } + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -2157,6 +2173,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/flairup": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flairup/-/flairup-1.0.0.tgz", + "integrity": "sha512-IKlE+pNvL2R+kVL1kEhUYqRxVqeFnjiIvHWDMLFXNaqyUdFXQM2wte44EfMYJNHkW16X991t2Zg8apKkhv7OBA==", + "license": "MIT" + }, "node_modules/flat-cache": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", diff --git a/package.json b/package.json index ba5eeb7..e5304ea 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "axios": "^1.11.0", + "emoji-picker-react": "^4.13.2", "react": "^19.1.1", "react-dom": "^19.1.1", "react-quill-new": "^3.6.0", From 6f76f7edba1c2b99069ef15e7b82245a0e9e6159 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 16 Aug 2025 12:51:44 +0900 Subject: [PATCH 158/253] =?UTF-8?q?feat=20[#34]=20'=EC=B6=94=EA=B0=80'=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=EC=9D=84=20=ED=81=B4=EB=A6=AD=ED=95=98?= =?UTF-8?q?=EB=A9=B4=20`EmojiPIcker`=EB=A5=BC=20popover=EB=A1=9C=20?= =?UTF-8?q?=ED=91=9C=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/rolling-paper-header.jsx | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/features/rolling-paper/components/rolling-paper-header.jsx b/src/features/rolling-paper/components/rolling-paper-header.jsx index 748c14f..0e57f66 100644 --- a/src/features/rolling-paper/components/rolling-paper-header.jsx +++ b/src/features/rolling-paper/components/rolling-paper-header.jsx @@ -1,9 +1,12 @@ +import EmojiPicker from "emoji-picker-react"; import styled from "styled-components"; import addImage from "../../../assets/ic-face-smile-add.svg"; import shareImage from "../../../assets/ic-share.svg"; import { OutlinedButton } from "../../../components/button/button"; import BUTTON_SIZE from "../../../components/button/button-size"; import Colors from "../../../components/color/colors"; +import Popover from "../../../components/popover/popover"; +import POPOVER_ALIGNMENT from "../../../components/popover/popover-alignment"; import { useMedia } from "../../../hooks/use-media"; import { media } from "../../../utils/media"; import RollingPaperReactions from "./rolling-paper-reactions"; @@ -122,11 +125,19 @@ function RollingPaperHeader({ recipientName, messages, reactions }) { - + + } + > + + From ca43bfed34f81f782d4bf860493c1db79a1186c5 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 16 Aug 2025 13:02:17 +0900 Subject: [PATCH 159/253] =?UTF-8?q?feat=20[#34]=20=EA=B3=B5=EC=9C=A0?= =?UTF-8?q?=ED=95=98=EA=B8=B0=20=EB=B2=84=ED=8A=BC=EC=9D=84=20=ED=81=B4?= =?UTF-8?q?=EB=A6=AD=ED=95=98=EB=A9=B4=20=EA=B3=B5=EC=9C=A0=20=EC=98=B5?= =?UTF-8?q?=EC=85=98=20=EB=AA=A9=EB=A1=9D=EC=9D=84=20popover=EB=A1=9C=20?= =?UTF-8?q?=ED=91=9C=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/rolling-paper-header.jsx | 22 +++++++++++- .../rolling-paper-share-popover.jsx | 35 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/features/rolling-paper/components/rolling-paper-share-popover.jsx diff --git a/src/features/rolling-paper/components/rolling-paper-header.jsx b/src/features/rolling-paper/components/rolling-paper-header.jsx index 0e57f66..2af8a63 100644 --- a/src/features/rolling-paper/components/rolling-paper-header.jsx +++ b/src/features/rolling-paper/components/rolling-paper-header.jsx @@ -11,6 +11,7 @@ import { useMedia } from "../../../hooks/use-media"; import { media } from "../../../utils/media"; import RollingPaperReactions from "./rolling-paper-reactions"; import RollingPaperSenders from "./rolling-paper-senders"; +import RollingPaperSharePopover from "./rolling-paper-share-popover"; const RecipientName = styled.h2` margin: 0; @@ -108,6 +109,14 @@ function RollingPaperHeader({ recipientName, messages, reactions }) { const name = {`To. ${recipientName}`}; + const handleShareKakao = () => { + // TODO: KakaoTalk 공유하기 + }; + + const handleShareUrl = () => { + // TODO: URL 공유하기 (clipboard 저장) + }; + return ( {isMobile && ( @@ -138,7 +147,18 @@ function RollingPaperHeader({ recipientName, messages, reactions }) { >
- + + } + > + + diff --git a/src/features/rolling-paper/components/rolling-paper-share-popover.jsx b/src/features/rolling-paper/components/rolling-paper-share-popover.jsx new file mode 100644 index 0000000..9cb1079 --- /dev/null +++ b/src/features/rolling-paper/components/rolling-paper-share-popover.jsx @@ -0,0 +1,35 @@ +import styled from "styled-components"; +import Colors from "../../../components/color/colors"; + +const ShareOption = styled.li` + padding: 12px 16px; + font-size: 16px; + font-weight: 400; + line-height: 26px; + background-color: white; + + &:hover { + background-color: ${Colors.gray(100)}; + } +`; + +const StyledRollingPaperSharePopover = styled.ul` + display: flex; + flex-direction: column; + padding: 10px 0; + background-color: white; + width: 140px; + list-style: none; + margin: 0; +`; + +function RollingPaperSharePopover({ onShareKakao, onShareUrl }) { + return ( + + 카카오톡 공유 + URL 공유 + + ); +} + +export default RollingPaperSharePopover; From 8cdd47abd64311aebbd7c15547db3078ed4c1b80 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 16 Aug 2025 15:49:25 +0900 Subject: [PATCH 160/253] =?UTF-8?q?feat=20[#34]=20URL=20=EA=B3=B5=EC=9C=A0?= =?UTF-8?q?=ED=95=98=EA=B8=B0=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/rolling-paper-header.jsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/features/rolling-paper/components/rolling-paper-header.jsx b/src/features/rolling-paper/components/rolling-paper-header.jsx index 2af8a63..958885a 100644 --- a/src/features/rolling-paper/components/rolling-paper-header.jsx +++ b/src/features/rolling-paper/components/rolling-paper-header.jsx @@ -7,7 +7,9 @@ import BUTTON_SIZE from "../../../components/button/button-size"; import Colors from "../../../components/color/colors"; import Popover from "../../../components/popover/popover"; import POPOVER_ALIGNMENT from "../../../components/popover/popover-alignment"; +import Toast from "../../../components/toast/toast"; import { useMedia } from "../../../hooks/use-media"; +import { useToast } from "../../../hooks/use-toast"; import { media } from "../../../utils/media"; import RollingPaperReactions from "./rolling-paper-reactions"; import RollingPaperSenders from "./rolling-paper-senders"; @@ -105,6 +107,7 @@ const StyledRollingPaperHeader = styled.div` `; function RollingPaperHeader({ recipientName, messages, reactions }) { + const { showsToast, setShowsToast } = useToast(); const { isDesktop, isMobile } = useMedia(); const name = {`To. ${recipientName}`}; @@ -114,7 +117,9 @@ function RollingPaperHeader({ recipientName, messages, reactions }) { }; const handleShareUrl = () => { - // TODO: URL 공유하기 (clipboard 저장) + const url = window.location.href; + navigator.clipboard.writeText(url); + setShowsToast(true); }; return ( @@ -162,6 +167,12 @@ function RollingPaperHeader({ recipientName, messages, reactions }) { + {showsToast && ( + setShowsToast(false)} + /> + )} ); } From 9536469f8b86501296f42d87a4dd6cabd6868a3d Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Wed, 20 Aug 2025 13:07:31 +0900 Subject: [PATCH 161/253] =?UTF-8?q?feat=20[#34]=20=EC=B9=B4=EC=B9=B4?= =?UTF-8?q?=EC=98=A4=ED=86=A1=20=EA=B3=B5=EC=9C=A0=ED=95=98=EA=B8=B0=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 7 ++++++ .../components/rolling-paper-header.jsx | 13 +++++++++-- src/libs/kakao/kakao-service.js | 22 +++++++++++++++++++ src/main.jsx | 3 +++ src/pages/messages-page.jsx | 1 + 5 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 src/libs/kakao/kakao-service.js diff --git a/index.html b/index.html index 5888c7d..11cbe46 100644 --- a/index.html +++ b/index.html @@ -41,5 +41,12 @@
+ + + diff --git a/src/features/rolling-paper/components/rolling-paper-header.jsx b/src/features/rolling-paper/components/rolling-paper-header.jsx index 958885a..6a48d9c 100644 --- a/src/features/rolling-paper/components/rolling-paper-header.jsx +++ b/src/features/rolling-paper/components/rolling-paper-header.jsx @@ -10,6 +10,7 @@ import POPOVER_ALIGNMENT from "../../../components/popover/popover-alignment"; import Toast from "../../../components/toast/toast"; import { useMedia } from "../../../hooks/use-media"; import { useToast } from "../../../hooks/use-toast"; +import { shareRollingPaper } from "../../../libs/kakao/kakao-service"; import { media } from "../../../utils/media"; import RollingPaperReactions from "./rolling-paper-reactions"; import RollingPaperSenders from "./rolling-paper-senders"; @@ -106,14 +107,22 @@ const StyledRollingPaperHeader = styled.div` } `; -function RollingPaperHeader({ recipientName, messages, reactions }) { +function RollingPaperHeader({ + recipientId, + recipientName, + messages, + reactions, +}) { const { showsToast, setShowsToast } = useToast(); const { isDesktop, isMobile } = useMedia(); const name = {`To. ${recipientName}`}; const handleShareKakao = () => { - // TODO: KakaoTalk 공유하기 + shareRollingPaper({ + recipientId, + recipientName, + }); }; const handleShareUrl = () => { diff --git a/src/libs/kakao/kakao-service.js b/src/libs/kakao/kakao-service.js new file mode 100644 index 0000000..98ca85b --- /dev/null +++ b/src/libs/kakao/kakao-service.js @@ -0,0 +1,22 @@ +function initKakaoSDK() { + window.Kakao.init(import.meta.env.VITE_KAKAO_JAVASCRIPT_KEY); + window.Kakao.isInitialized(); +} + +function shareRollingPaper({ recipientId, recipientName }) { + if (!recipientId || !recipientName) return; + + const appIdString = import.meta.env.VITE_KAKAO_APP_ID; + const appId = Number(appIdString); + if (!appId) return; + + window.Kakao.Share.sendCustom({ + templateId: appId, + templateArgs: { + recipientId, + recipientName, + }, + }); +} + +export { initKakaoSDK, shareRollingPaper }; diff --git a/src/main.jsx b/src/main.jsx index 2f3a963..ec16707 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -1,6 +1,9 @@ import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; import App from "./app"; +import { initKakaoSDK } from "./libs/kakao/kakao-service"; + +initKakaoSDK(); const root = createRoot(document.getElementById("root")); diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx index 3a2cf17..6b93fa1 100644 --- a/src/pages/messages-page.jsx +++ b/src/pages/messages-page.jsx @@ -17,6 +17,7 @@ function MessagesPage() { {recipient && ( <> Date: Wed, 20 Aug 2025 13:08:28 +0900 Subject: [PATCH 162/253] =?UTF-8?q?feat=20[#34]=20=EC=B9=B4=EC=B9=B4?= =?UTF-8?q?=EC=98=A4=ED=86=A1=20=EB=B0=8F=20URL=20=EA=B3=B5=EC=9C=A0=20?= =?UTF-8?q?=EC=9A=94=EC=86=8C=EC=97=90=20pointer=20cursor=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rolling-paper/components/rolling-paper-share-popover.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/features/rolling-paper/components/rolling-paper-share-popover.jsx b/src/features/rolling-paper/components/rolling-paper-share-popover.jsx index 9cb1079..d2ffcb3 100644 --- a/src/features/rolling-paper/components/rolling-paper-share-popover.jsx +++ b/src/features/rolling-paper/components/rolling-paper-share-popover.jsx @@ -7,6 +7,7 @@ const ShareOption = styled.li` font-weight: 400; line-height: 26px; background-color: white; + cursor: pointer; &:hover { background-color: ${Colors.gray(100)}; From 62a7e97b0bac9d0fc893a07340e7138d1bfda41a Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Wed, 20 Aug 2025 14:43:27 +0900 Subject: [PATCH 163/253] =?UTF-8?q?fix=20#62=20=EC=B2=B4=ED=81=AC=20?= =?UTF-8?q?=EC=95=84=EC=9D=B4=EC=BD=98=20hover=20=EC=8B=9C=20=EC=83=89?= =?UTF-8?q?=EC=83=81=20=EB=B3=80=ED=99=94=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/option/background-select.jsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/option/background-select.jsx b/src/components/option/background-select.jsx index f844408..0e9b78b 100644 --- a/src/components/option/background-select.jsx +++ b/src/components/option/background-select.jsx @@ -29,6 +29,10 @@ const CheckedIcon = styled(OutlinedButton)` top: 50%; left: 50%; transform: translate(-50%, -50%); + + &:hover { + background-color: ${Colors.gray(500)}; + } `; const BackgroundOverlay = styled.div` From 023ba26eb4ff8c824c042c7b949f5c3d5c93da50 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Wed, 20 Aug 2025 16:14:59 +0900 Subject: [PATCH 164/253] =?UTF-8?q?refactor=20[#34]=20=EC=B9=B4=EC=B9=B4?= =?UTF-8?q?=EC=98=A4=ED=86=A1=20message=20template=20id=20=EB=B3=80?= =?UTF-8?q?=EC=88=98=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/libs/kakao/kakao-service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/kakao/kakao-service.js b/src/libs/kakao/kakao-service.js index 98ca85b..b782651 100644 --- a/src/libs/kakao/kakao-service.js +++ b/src/libs/kakao/kakao-service.js @@ -6,7 +6,7 @@ function initKakaoSDK() { function shareRollingPaper({ recipientId, recipientName }) { if (!recipientId || !recipientName) return; - const appIdString = import.meta.env.VITE_KAKAO_APP_ID; + const appIdString = import.meta.env.VITE_KAKAO_MESSAGE_TEMPLATE_ID; const appId = Number(appIdString); if (!appId) return; From ab22722b5083b9e6de7d9e6bc8617de9c8ce554d Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Wed, 20 Aug 2025 20:42:31 +0900 Subject: [PATCH 165/253] =?UTF-8?q?fix=20#62=20index.html=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(=EC=A4=91=EB=B3=B5=20=EC=BD=94=EB=93=9C,=20lang=3D?= =?UTF-8?q?ko,=20react=20quill=20=EA=B4=80=EB=A0=A8=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C=20-->=20=EB=B6=88=EB=A0=9B=EA=B3=BC=20?= =?UTF-8?q?=EC=88=AB=EC=9E=90=20=EA=B0=99=EC=9D=B4=20=EB=82=98=EC=98=A4?= =?UTF-8?q?=EB=8A=94=20=EB=AC=B8=EC=A0=9C=EB=8F=84=20=ED=95=B4=EA=B2=B0?= =?UTF-8?q?=EB=90=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/index.html b/index.html index 5888c7d..e9cbdf6 100644 --- a/index.html +++ b/index.html @@ -1,5 +1,5 @@ - + @@ -11,24 +11,16 @@ crossorigin href="https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css" /> - - - - - Date: Wed, 20 Aug 2025 21:14:03 +0900 Subject: [PATCH 166/253] =?UTF-8?q?refactor=20#62=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=84=A0=ED=83=9D=20?= =?UTF-8?q?=EC=8B=9C=20=ED=95=B4=EB=8B=B9=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20?= =?UTF-8?q?=ED=85=8C=EB=91=90=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/send-message-page.jsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pages/send-message-page.jsx b/src/pages/send-message-page.jsx index b368f0d..92bc2c2 100644 --- a/src/pages/send-message-page.jsx +++ b/src/pages/send-message-page.jsx @@ -53,6 +53,9 @@ const AvatarOption = styled.div` const AvatarPreview = styled.div` cursor: pointer; + box-shadow: ${({ $isSelected }) => + $isSelected ? `0 0 0 2px ${Colors.purple(400)}` : "none"}; + border-radius: 50%; `; const DefaultAvatar = styled.div` @@ -157,6 +160,7 @@ function SendMessagePage() { {avatarList.map((url, index) => ( setSelectedAvatar(url)} > From 4069bc24fc51f095a52e01f4921757eaecf8ef66 Mon Sep 17 00:00:00 2001 From: luli Date: Thu, 21 Aug 2025 03:19:09 +0900 Subject: [PATCH 167/253] =?UTF-8?q?[#61]=20pr=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EB=B0=98=EC=98=81=20=EB=B0=8F=20=EB=A9=98?= =?UTF-8?q?=ED=86=A0=EB=A7=81=20=EC=BD=94=EB=93=9C=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EB=B0=98=EC=98=81=20(=EC=9D=B4=EB=AA=A8=EC=A7=80=EB=8F=84=20ho?= =?UTF-8?q?ver=ED=96=88=EC=9D=84=EB=95=8C=20=EC=88=AB=EC=9E=90=EB=A7=8C=20?= =?UTF-8?q?=EB=B3=B4=EC=9D=B4=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95,=20?= =?UTF-8?q?=EB=AA=A8=EB=B0=94=EC=9D=BC=ED=99=94=EB=A9=B4=EC=97=90=EC=84=9C?= =?UTF-8?q?=20padding=EB=93=B1=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=9D=BC?= =?UTF-8?q?=EB=B6=80=20=EC=88=98=EC=A0=95)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pr 수정사항 반영 및 멘토링 코드리뷰 반영 (이모지도 hover했을때 숫자만 보이도록 수정, 모바일화면에서 padding등 스타일 일부 수정) --- src/app.jsx | 4 +- .../api/mock-rolling-paper-list.json} | 4 +- .../rolling-paper/api/rollingPaperList.js | 7 ++ .../components/rolling-paper-list.jsx | 66 +++++++------------ src/pages/rolling-paper-list-page.jsx | 54 +++++---------- 5 files changed, 52 insertions(+), 83 deletions(-) rename src/{pages/test_recipients_data.json => features/rolling-paper/api/mock-rolling-paper-list.json} (99%) create mode 100644 src/features/rolling-paper/api/rollingPaperList.js diff --git a/src/app.jsx b/src/app.jsx index 3f5d4c7..392043b 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -4,7 +4,7 @@ import ContentLayout from "./layouts/content-layout"; import OnboardingLayout from "./layouts/onboarding-layout"; import CreatePostPage from "./pages/create-post-page"; import MainPage from "./pages/main-page"; -import MessagePage from "./pages/rolling-paper-list-page"; +import RollingPaperListPage from "./pages/rolling-paper-list-page"; import MessagesPage from "./pages/messages-page"; import SendMessagePage from "./pages/send-message-page"; import TestPage from "./pages/test-page"; @@ -30,7 +30,7 @@ function App() { path="/list" element={ - + } /> diff --git a/src/pages/test_recipients_data.json b/src/features/rolling-paper/api/mock-rolling-paper-list.json similarity index 99% rename from src/pages/test_recipients_data.json rename to src/features/rolling-paper/api/mock-rolling-paper-list.json index 8d2dbf0..7be3a53 100644 --- a/src/pages/test_recipients_data.json +++ b/src/features/rolling-paper/api/mock-rolling-paper-list.json @@ -212,7 +212,7 @@ "topReactions": [ { "emoji": "❤️", - "count": 8 + "count": 88 }, { "emoji": "😀", @@ -220,7 +220,7 @@ }, { "emoji": "👍", - "count": 33 + "count": 333 } ] }, diff --git a/src/features/rolling-paper/api/rollingPaperList.js b/src/features/rolling-paper/api/rollingPaperList.js new file mode 100644 index 0000000..38442da --- /dev/null +++ b/src/features/rolling-paper/api/rollingPaperList.js @@ -0,0 +1,7 @@ +import mockRollingPaperList from "./mock-rolling-paper-list.json"; + +async function getRollingPaperList() { + return mockRollingPaperList; +} + +export { getRollingPaperList }; diff --git a/src/features/rolling-paper/components/rolling-paper-list.jsx b/src/features/rolling-paper/components/rolling-paper-list.jsx index 17c6c27..16e93b0 100644 --- a/src/features/rolling-paper/components/rolling-paper-list.jsx +++ b/src/features/rolling-paper/components/rolling-paper-list.jsx @@ -1,17 +1,7 @@ import ArrowButton from "../../../components/button/arrow-button"; import ARROW_BUTTON_DIRECTION from "../../../components/button/arrow-button-direction"; -import { - OutlinedButton, - PrimaryButton, - SecondaryButton, -} from "../../../components/button/button"; -import BUTTON_SIZE from "../../../components/button/button-size"; -import ToggleButton from "../../../components/button/toggle-button"; -import EmojiBadge from "../../../components/badge/emoji-badge"; import { media } from "../../../utils/media"; -// import React, { useEffect, useState } from "react"; - import styled, { css } from "styled-components"; const backgroundColors = { @@ -36,17 +26,17 @@ const CardContainer = styled.div` overflow-x: auto; scroll-snap-type: x mandatory; - scrollbar-width: none; // Firefox - -ms-overflow-style: none; // IE && Edge + scrollbar-width: none; + -ms-overflow-style: none; max-width: 1199px; width: 100%; padding: 0 24px; - } - ${media.tablet} > div { - flex: 0 0 275px; - scroll-snap-align: start; + & > div { + flex: 0 0 275px; + scroll-snap-align: start; + } } ${media.mobile} { @@ -84,6 +74,7 @@ const CardItem = styled.div` ${media.mobile} { width: 208px; height: 232px; + padding: 30px 15px 20px 15px; } /* 배경 도형 */ @@ -94,6 +85,7 @@ const CardItem = styled.div` ${({ $backgroundImageURL, $backgroundColor }) => { return $backgroundImageURL ? "" : polygonStyle[$backgroundColor]; }} + } & > * { position: relative; @@ -229,9 +221,6 @@ const CardEmoji = styled.span` font-size: 16px; font-weight: 400; - min-width: ${(props) => (props.$isLong ? "60px" : "auto")}; - max-width: ${(props) => (props.$isLong ? "44px" : "none")}; - transition: max-width 0.3s ease, z-index 0s; &:hover { @@ -242,6 +231,8 @@ const CardEmoji = styled.span` ${media.mobile} { font-size: 14px; + padding: 8px 8px; + margin-right: 3px; } `; @@ -281,57 +272,50 @@ const PreviewButtonWrapper = styled.div` function RollingPaperList({ cardData, totalPages, currentPage, onTurnCards }) { return ( - {cardData.map((item) => ( + {cardData.map((card) => ( - To. {item.name} + To. {card.name} - {item.recentMessages.slice(0, 3).map((messageItem, index) => ( + {card.recentMessages.slice(0, 3).map((messagecard, index) => ( ))} - {item.messageCount > 3 && ( + {card.messageCount > 3 && ( - +{item.messageCount - 3} + +{card.messageCount - 3} )} - {item.messageCount}명이 작성했어요! + {card.messageCount}명이 작성했어요! - {item.topReactions.map((emoji, index) => { + {card.topReactions.map((emoji, index) => { const countLength = emoji.count.toString().length; const isLongCount = countLength > 2; return ( - // - - {emoji.emoji} {isLongCount ? ( - + + {emoji.emoji} {emoji.count} ) : ( - ` ${emoji.count}` + `${emoji.emoji} ${emoji.count}` )} ); diff --git a/src/pages/rolling-paper-list-page.jsx b/src/pages/rolling-paper-list-page.jsx index 457e039..e7b410c 100644 --- a/src/pages/rolling-paper-list-page.jsx +++ b/src/pages/rolling-paper-list-page.jsx @@ -1,21 +1,14 @@ -import ArrowButton from "../components/button/arrow-button"; -import ARROW_BUTTON_DIRECTION from "../components/button/arrow-button-direction"; -import { - OutlinedButton, - PrimaryButton, - SecondaryButton, -} from "../components/button/button"; +import { PrimaryButton } from "../components/button/button"; import BUTTON_SIZE from "../components/button/button-size"; -import ToggleButton from "../components/button/toggle-button"; import { useNavigate } from "react-router"; import React, { useEffect, useState, useMemo } from "react"; -// import axiosInstance from "../api/axios-instance"; -import testDataFile from "./test_recipients_data.json"; +import { getRollingPaperList } from "../features/rolling-paper/api/rollingPaperList"; import styled from "styled-components"; import RollingPaperList from "../features/rolling-paper/components/rolling-paper-list"; import { media } from "../utils/media"; +import { useMedia } from "../hooks/use-media"; const TopContainer = styled.div` text-align: center; @@ -75,42 +68,23 @@ function ShowMessageList() { const [popularCurrentPage, setPopularCurrentPage] = useState(0); const [recentCurrentPage, setRecentCurrentPage] = useState(0); const [cardCount, setCardCount] = useState(4); + const { isDesktop } = useMedia(); useEffect(() => { - const mql = window.matchMedia("(max-width: 1199px)"); - const updateCardCount = (e) => { - if (e.matches) { - setCardCount(null); - } else { - setCardCount(4); - } - }; - - updateCardCount(mql); - mql.addEventListener("change", updateCardCount); - return () => mql.removeEventListener("change", updateCardCount); - }, []); + isDesktop ? setCardCount(4) : setCardCount(null); + }, [isDesktop]); const handleMakingButton = () => { navigate("/post"); }; useEffect(() => { - setTestData(testDataFile); - // axiosInstance - // .get("/18-3/recipients/?limit=5&offset=20") - // .then((res) => { - // setTestData(res.data); - // console.log(res.data); - // }) - // .catch((err) => { - // console.error("오류:", err); - // }); + getRollingPaperList().then(setTestData); }, []); useEffect(() => { - testData.forEach((item) => { - getCachedImage(item.imageURL); + testData.forEach((data) => { + getCachedImage(data.imageURL); }); }, [testData]); @@ -141,9 +115,13 @@ function ShowMessageList() { }, [recentDataList, recentCurrentPage, cardCount]); const handleTurnCards = (direction, mode) => { - const current = mode === "popular" ? popularCurrentPage : recentCurrentPage; - const setter = - mode === "popular" ? setPopularCurrentPage : setRecentCurrentPage; + const cardPageMap = { + popular: { current: popularCurrentPage, setter: setPopularCurrentPage }, + recent: { current: recentCurrentPage, setter: setRecentCurrentPage }, + }; + + const cardPageValue = cardPageMap[mode]; + const { current, setter } = cardPageValue; const total = totalPages; const additionalPageIndex = direction === "next" ? 1 : -1; From a50d146e207fa2645e7fdedc0ee11ff72f89bf50 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Thu, 21 Aug 2025 12:14:43 +0900 Subject: [PATCH 168/253] =?UTF-8?q?fix=20#62=20=EC=B2=B4=ED=81=AC=20?= =?UTF-8?q?=EC=95=84=EC=9D=B4=EC=BD=98=20=EB=B2=84=ED=8A=BC=20->=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/option/background-select.jsx | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/components/option/background-select.jsx b/src/components/option/background-select.jsx index 0e9b78b..3bf45f9 100644 --- a/src/components/option/background-select.jsx +++ b/src/components/option/background-select.jsx @@ -21,7 +21,7 @@ const OptionItem = styled.div` position: relative; `; -const CheckedIcon = styled(OutlinedButton)` +const CheckedIcon = styled.img` background-color: ${Colors.gray(500)}; box-shadow: none; border-radius: 50%; @@ -29,9 +29,7 @@ const CheckedIcon = styled(OutlinedButton)` top: 50%; left: 50%; transform: translate(-50%, -50%); - - &:hover { - background-color: ${Colors.gray(500)}; + padding: 5px; } `; @@ -104,9 +102,7 @@ function BackgroundSelect({ type, selected, onSelect }) { url={option.url} selected={selected === index} /> - {selected === index && ( - - )} + {selected === index && } ))} From e7ac5d267e0d63a7af0de910c5240dde47479956 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Thu, 21 Aug 2025 12:17:35 +0900 Subject: [PATCH 169/253] refactor #62 name.trim() -> trimmed --- src/pages/create-post-page.jsx | 5 +++-- src/pages/send-message-page.jsx | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/pages/create-post-page.jsx b/src/pages/create-post-page.jsx index 0bd1f21..f620723 100644 --- a/src/pages/create-post-page.jsx +++ b/src/pages/create-post-page.jsx @@ -60,8 +60,9 @@ function CreatePostPage() { setNameError(""); // 값 입력 중 에러 없애기 }; + const trimmed = name.trim(); + const handleBlur = () => { - const trimmed = name.trim(); setName(trimmed); if (trimmed === "") { setNameError("이름을 입력해 주세요"); @@ -82,7 +83,7 @@ function CreatePostPage() { navigate(`/post/${randomID}`); }; - const canCreate = name.trim() !== ""; + const canCreate = trimmed !== ""; return ( diff --git a/src/pages/send-message-page.jsx b/src/pages/send-message-page.jsx index 92bc2c2..27b24cf 100644 --- a/src/pages/send-message-page.jsx +++ b/src/pages/send-message-page.jsx @@ -94,8 +94,9 @@ function SendMessagePage() { } }; + const trimmed = name.trim(); + const handleBlur = () => { - const trimmed = name.trim(); setName(trimmed); if (trimmed === "") { setNameError("이름을 입력해 주세요"); @@ -121,7 +122,7 @@ function SendMessagePage() { }; const canCreate = - name.trim() !== "" && content.replace(/<[^>]+>/g, "").trim() !== ""; + trimmed !== "" && content.replace(/<[^>]+>/g, "").trim() !== ""; // 정규식 유효성 검사로 html 태그 찾기("<"로 시작해서 ">"로 끝나는 문자 중 > 를 제외한(^ not) 모든 문자 제외) const fontOptions = [ From 569ed9d8561f7764b73e61876f81e3eb4f057fe6 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Thu, 21 Aug 2025 13:09:05 +0900 Subject: [PATCH 170/253] =?UTF-8?q?refactor=20#62=20index.html=20=EC=9D=B4?= =?UTF-8?q?=EC=8A=88=20=EC=A4=91=EB=B3=B5=EB=90=98=EC=96=B4=20=EB=8B=A4?= =?UTF-8?q?=EC=8B=9C=20=EC=88=98=EC=A0=95~?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 2 +- src/components/option/background-select.jsx | 18 ++++++++++++------ src/pages/create-post-page.jsx | 18 ++++++++++++++++-- src/pages/send-message-page.jsx | 8 ++++++-- 4 files changed, 35 insertions(+), 11 deletions(-) diff --git a/index.html b/index.html index e9cbdf6..ec28fbb 100644 --- a/index.html +++ b/index.html @@ -1,5 +1,5 @@ - + diff --git a/src/components/option/background-select.jsx b/src/components/option/background-select.jsx index 3bf45f9..458c99b 100644 --- a/src/components/option/background-select.jsx +++ b/src/components/option/background-select.jsx @@ -4,19 +4,25 @@ import CheckImage from "../../assets/ic-check.svg"; import { useEffect, useState } from "react"; import { OutlinedButton } from "../button/button"; import BUTTON_SIZE from "../button/button-size"; +import { media } from "../../utils/media"; const BackgroundWrapper = styled.div` padding-top: 50px; - width: 720px; - display: flex; - justify-content: center; - align-items: center; + width: 100%; + max-width: 720px; + display: grid; + grid-template-columns: repeat(4, 1fr); gap: 16px; + + ${media.mobile} { + max-width: 100%; + grid-template-columns: repeat(2, 1fr); + } `; const OptionItem = styled.div` - width: 168px; - height: 168px; + width: 100%; + aspect-ratio: 1 / 1; cursor: pointer; position: relative; `; diff --git a/src/pages/create-post-page.jsx b/src/pages/create-post-page.jsx index f620723..b5f15cb 100644 --- a/src/pages/create-post-page.jsx +++ b/src/pages/create-post-page.jsx @@ -8,6 +8,7 @@ import { PrimaryButton } from "../components/button/button"; import BackgroundSelect from "../components/option/background-select"; import { useNavigate } from "react-router"; import BUTTON_SIZE from "../components/button/button-size"; +import { media } from "../utils/media"; const PostContainer = styled.div` display: flex; @@ -16,11 +17,23 @@ const PostContainer = styled.div` align-items: center; width: 100%; margin: 0 auto; + + ${media.tablet} { + width: 100%; + padding: 0 24px; + display: flex; + } + + ${media.mobile} { + width: 100%; + padding: 0 20px; + } `; const Wrapper = styled.div` padding-top: 50px; - width: 720px; + width: 100%; + max-width: 720px; `; const PostTitle = styled.h2` @@ -40,7 +53,8 @@ const ToggleButtonWrapper = styled.div` const ButtonWrapper = styled.div` padding-top: 50px; padding-bottom: 150px; - width: 720px; + width: 100%; + max-width: 720px; `; const CreateButton = styled(PrimaryButton)` diff --git a/src/pages/send-message-page.jsx b/src/pages/send-message-page.jsx index 27b24cf..34c9beb 100644 --- a/src/pages/send-message-page.jsx +++ b/src/pages/send-message-page.jsx @@ -72,6 +72,10 @@ const CreateButton = styled(PrimaryButton)` width: 100%; `; +const TextFieldStyle = styled(TextField)` + width: 50%; +`; + function SendMessagePage() { const [name, setName] = useState(""); const [nameError, setNameError] = useState(""); @@ -173,7 +177,7 @@ function SendMessagePage() { 상대와의 관계 - 폰트 선택 - Date: Thu, 21 Aug 2025 13:16:44 +0900 Subject: [PATCH 171/253] =?UTF-8?q?refactor=20#62=20=EB=B0=98=EC=9D=91?= =?UTF-8?q?=ED=98=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/create-post-page.jsx | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/pages/create-post-page.jsx b/src/pages/create-post-page.jsx index cac37ed..32539c1 100644 --- a/src/pages/create-post-page.jsx +++ b/src/pages/create-post-page.jsx @@ -8,6 +8,7 @@ import { PrimaryButton } from "../components/button/button"; import BackgroundSelect from "../components/option/background-select"; import { useNavigate } from "react-router"; import BUTTON_SIZE from "../components/button/button-size"; +import { media } from "../utils/media"; const PostContainer = styled.div` display: flex; @@ -16,11 +17,22 @@ const PostContainer = styled.div` align-items: center; width: 100%; margin: 0 auto; + + ${media.tablet} { + width: 100%; + padding: 0 24px; + display: flex; + } + ${media.mobile} { + width: 100%; + padding: 0 20px; + } `; const Wrapper = styled.div` padding-top: 50px; - width: 720px; + width: 100%; + max-width: 720px; `; const PostTitle = styled.h2` @@ -40,7 +52,8 @@ const ToggleButtonWrapper = styled.div` const ButtonWrapper = styled.div` padding-top: 50px; padding-bottom: 150px; - width: 720px; + width: 100%; + max-width: 720px; `; const CreateButton = styled(PrimaryButton)` @@ -63,10 +76,9 @@ function CreatePostPage() { const trimmed = name.trim(); const handleBlur = () => { + setName(trimmed); if (trimmed === "") { - setNameError("값을 입력해 주세요"); - } else if (trimmed !== name) { - setNameError("앞 뒤 공백 없이 입력해 주세요"); // 텍스트 앞 뒤 공백 에러 처리(임시) + setNameError("이름을 입력해 주세요"); } }; @@ -80,11 +92,7 @@ function CreatePostPage() { }; const handleCreate = () => { - const finalName = trimmed; const randomID = Math.floor(Math.random() * 10000); - if (finalName !== name) { - return; - } navigate(`/post/${randomID}`); }; From c4f1a5938ce6a81468f24fdd8bde6c3c18035571 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Thu, 21 Aug 2025 13:18:08 +0900 Subject: [PATCH 172/253] =?UTF-8?q?fix=20#62=20=EB=8B=A4=EB=A5=B8=20?= =?UTF-8?q?=EB=B8=8C=EB=9E=9C=EC=B9=98=20=EC=9E=91=EC=97=85...=20=EB=8B=A4?= =?UTF-8?q?=EC=8B=9C=20=EB=8F=8C=EB=A0=A4=EB=86=93=EC=9D=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/create-post-page.jsx | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/src/pages/create-post-page.jsx b/src/pages/create-post-page.jsx index b5f15cb..824014a 100644 --- a/src/pages/create-post-page.jsx +++ b/src/pages/create-post-page.jsx @@ -17,23 +17,11 @@ const PostContainer = styled.div` align-items: center; width: 100%; margin: 0 auto; - - ${media.tablet} { - width: 100%; - padding: 0 24px; - display: flex; - } - - ${media.mobile} { - width: 100%; - padding: 0 20px; - } `; const Wrapper = styled.div` padding-top: 50px; - width: 100%; - max-width: 720px; + width: 720px; `; const PostTitle = styled.h2` @@ -53,8 +41,7 @@ const ToggleButtonWrapper = styled.div` const ButtonWrapper = styled.div` padding-top: 50px; padding-bottom: 150px; - width: 100%; - max-width: 720px; + width: 720px; `; const CreateButton = styled(PrimaryButton)` From b898be37685a3976585b9b4217f704470e022d33 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Thu, 21 Aug 2025 13:22:31 +0900 Subject: [PATCH 173/253] =?UTF-8?q?refactor=20#64=20=EB=B0=98=EC=9D=91?= =?UTF-8?q?=ED=98=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/option/background-select.jsx | 77 +++++++++++---------- 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/src/components/option/background-select.jsx b/src/components/option/background-select.jsx index cc6cb27..458c99b 100644 --- a/src/components/option/background-select.jsx +++ b/src/components/option/background-select.jsx @@ -4,22 +4,46 @@ import CheckImage from "../../assets/ic-check.svg"; import { useEffect, useState } from "react"; import { OutlinedButton } from "../button/button"; import BUTTON_SIZE from "../button/button-size"; +import { media } from "../../utils/media"; const BackgroundWrapper = styled.div` padding-top: 50px; - width: 720px; - display: flex; - justify-content: center; - align-items: center; + width: 100%; + max-width: 720px; + display: grid; + grid-template-columns: repeat(4, 1fr); gap: 16px; + + ${media.mobile} { + max-width: 100%; + grid-template-columns: repeat(2, 1fr); + } `; const OptionItem = styled.div` - width: 168px; - height: 168px; - border-radius: 8px; + width: 100%; + aspect-ratio: 1 / 1; cursor: pointer; - background-color: ${({ type, color }) => (type === "color" ? color : "none")}; + position: relative; +`; + +const CheckedIcon = styled.img` + background-color: ${Colors.gray(500)}; + box-shadow: none; + border-radius: 50%; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + padding: 5px; + } +`; + +const BackgroundOverlay = styled.div` + height: 100%; + border-radius: 8px; + background-color: ${({ type, color }) => + type === "color" ? color : "transparent"}; background-image: ${({ type, url }) => type === "image" ? `url(${url})` : "none"}; background-position: center; @@ -28,18 +52,6 @@ const OptionItem = styled.div` opacity: ${({ selected }) => (selected ? 0.3 : 1)}; `; -const CircleButtonWrapper = styled.div` - height: 100%; - overflow: hidden; - display: flex; - justify-content: center; - align-items: center; - - & > button { - border-radius: 50%; - } -`; - function BackgroundSelect({ type, selected, onSelect }) { const [imageUrls, setImageUrls] = useState([]); @@ -89,23 +101,14 @@ function BackgroundSelect({ type, selected, onSelect }) { return ( {options.map((option, index) => ( - onSelect(index)} - selected={selected === index} - > - {selected === index && ( - - - - )} + onSelect(index)}> + + {selected === index && } ))} From 49c5da930c6eb6590ce39f40da4f02d06e4c07ca Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Thu, 21 Aug 2025 13:23:23 +0900 Subject: [PATCH 174/253] =?UTF-8?q?fix=20#62=20=EB=8B=A4=EB=A5=B8=20?= =?UTF-8?q?=EB=B8=8C=EB=9E=9C=EC=B9=98=20=EC=9E=91=EC=97=85=ED=95=9C?= =?UTF-8?q?=EA=B1=B0=20=EB=8B=A4=EC=8B=9C=20=EC=9B=90=EC=83=81=EB=B3=B5?= =?UTF-8?q?=EA=B5=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/option/background-select.jsx | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/components/option/background-select.jsx b/src/components/option/background-select.jsx index 458c99b..53824ca 100644 --- a/src/components/option/background-select.jsx +++ b/src/components/option/background-select.jsx @@ -4,27 +4,21 @@ import CheckImage from "../../assets/ic-check.svg"; import { useEffect, useState } from "react"; import { OutlinedButton } from "../button/button"; import BUTTON_SIZE from "../button/button-size"; -import { media } from "../../utils/media"; const BackgroundWrapper = styled.div` padding-top: 50px; - width: 100%; - max-width: 720px; - display: grid; - grid-template-columns: repeat(4, 1fr); + width: 720px; + display: flex; + justify-content: center; + align-items: center; gap: 16px; - - ${media.mobile} { - max-width: 100%; - grid-template-columns: repeat(2, 1fr); - } `; const OptionItem = styled.div` - width: 100%; - aspect-ratio: 1 / 1; + width: 168px; + height: 168px; + border-radius: 8px; cursor: pointer; - position: relative; `; const CheckedIcon = styled.img` From b8bc56b991aeb761983b02ba59d7d19578a82bba Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Thu, 21 Aug 2025 13:23:43 +0900 Subject: [PATCH 175/253] =?UTF-8?q?fix=20#62=20=EB=8B=A4=EB=A5=B8=20?= =?UTF-8?q?=EB=B8=8C=EB=9E=9C=EC=B9=98...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/create-post-page.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/create-post-page.jsx b/src/pages/create-post-page.jsx index 824014a..f620723 100644 --- a/src/pages/create-post-page.jsx +++ b/src/pages/create-post-page.jsx @@ -8,7 +8,6 @@ import { PrimaryButton } from "../components/button/button"; import BackgroundSelect from "../components/option/background-select"; import { useNavigate } from "react-router"; import BUTTON_SIZE from "../components/button/button-size"; -import { media } from "../utils/media"; const PostContainer = styled.div` display: flex; From acf9104dc68adad2255c601ef2fd32b51d4f7178 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Thu, 21 Aug 2025 13:26:54 +0900 Subject: [PATCH 176/253] fix #62 option item position: relative; --- src/components/option/background-select.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/option/background-select.jsx b/src/components/option/background-select.jsx index 53824ca..2fc8875 100644 --- a/src/components/option/background-select.jsx +++ b/src/components/option/background-select.jsx @@ -19,6 +19,7 @@ const OptionItem = styled.div` height: 168px; border-radius: 8px; cursor: pointer; + position: relative; `; const CheckedIcon = styled.img` From 06832d95253ba282c21a8d26cbad2d42878fc395 Mon Sep 17 00:00:00 2001 From: luli Date: Thu, 21 Aug 2025 13:41:53 +0900 Subject: [PATCH 177/253] =?UTF-8?q?[#61]=20=EB=88=84=EB=9D=BD=EB=90=9C?= =?UTF-8?q?=EB=B6=80=EB=B6=84=20=EC=88=98=EC=A0=95=20(api.jsx)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ㅎㅎ --- src/app.jsx | 2 +- src/features/rolling-paper/api/mock-rolling-paper-list.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app.jsx b/src/app.jsx index 392043b..4a9b453 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -54,7 +54,7 @@ function App() { } /> } /> - } /> + } /> diff --git a/src/features/rolling-paper/api/mock-rolling-paper-list.json b/src/features/rolling-paper/api/mock-rolling-paper-list.json index 7be3a53..c29b250 100644 --- a/src/features/rolling-paper/api/mock-rolling-paper-list.json +++ b/src/features/rolling-paper/api/mock-rolling-paper-list.json @@ -212,7 +212,7 @@ "topReactions": [ { "emoji": "❤️", - "count": 88 + "count": 888 }, { "emoji": "😀", @@ -220,7 +220,7 @@ }, { "emoji": "👍", - "count": 333 + "count": 33 } ] }, From 11d48cdfc3efbe7219153a2a8d1894be25bb41f8 Mon Sep 17 00:00:00 2001 From: gummmmmy0v0 Date: Thu, 21 Aug 2025 14:04:45 +0900 Subject: [PATCH 178/253] =?UTF-8?q?refactor=20#64=20=EB=B0=98=EC=9D=91?= =?UTF-8?q?=ED=98=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/create-post-page.jsx | 1 + src/pages/send-message-page.jsx | 37 +++++++++++++++++++++++++++------ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/pages/create-post-page.jsx b/src/pages/create-post-page.jsx index 32539c1..b5f15cb 100644 --- a/src/pages/create-post-page.jsx +++ b/src/pages/create-post-page.jsx @@ -23,6 +23,7 @@ const PostContainer = styled.div` padding: 0 24px; display: flex; } + ${media.mobile} { width: 100%; padding: 0 20px; diff --git a/src/pages/send-message-page.jsx b/src/pages/send-message-page.jsx index 4d07b18..eea309e 100644 --- a/src/pages/send-message-page.jsx +++ b/src/pages/send-message-page.jsx @@ -9,6 +9,7 @@ import BUTTON_SIZE from "../components/button/button-size"; import { useNavigate } from "react-router"; import { PrimaryButton } from "../components/button/button"; import TextEditor from "../components/text-editor/text-editor"; +import { media } from "../utils/media"; const SendContainer = styled.div` display: flex; @@ -17,11 +18,23 @@ const SendContainer = styled.div` align-items: center; width: 100%; margin: 0 auto; + + ${media.tablet} { + width: 100%; + padding: 0 24px; + display: flex; + } + + ${media.mobile} { + width: 100%; + padding: 0 20px; + } `; const Wrapper = styled.div` padding-top: 50px; - width: 720px; + width: 100%; + max-width: 720px; `; const SendTitle = styled.h2` @@ -30,7 +43,6 @@ const SendTitle = styled.h2` const AvatarWrapper = styled.div` display: flex; - align-items: center; gap: 32px; `; @@ -38,7 +50,7 @@ const AvatarOptionWrapper = styled.div` display: flex; flex-direction: column; justify-content: center; - width: 80%; + width: 100%; `; const AvatarDescription = styled.p` @@ -49,6 +61,13 @@ const AvatarDescription = styled.p` const AvatarOption = styled.div` display: flex; justify-content: space-between; + + ${media.mobile} { + display: grid; + grid-template-columns: repeat(5, 1fr); + gap: 5px; + width: 50%; + } `; const AvatarPreview = styled.div` @@ -57,18 +76,24 @@ const AvatarPreview = styled.div` const DefaultAvatar = styled.div` cursor: pointer; + padding-top: 20px; `; const ButtonWrapper = styled.div` padding-top: 50px; padding-bottom: 150px; - width: 720px; + width: 100%; + max-width: 720px; `; const CreateButton = styled(PrimaryButton)` width: 100%; `; +const TextFieldStyle = styled(TextField)` + width: 50%; +`; + function SendMessagePage() { const [name, setName] = useState(""); const [nameError, setNameError] = useState(""); @@ -158,7 +183,7 @@ function SendMessagePage() { 상대와의 관계 - 폰트 선택 - Date: Thu, 21 Aug 2025 14:45:14 +0900 Subject: [PATCH 179/253] =?UTF-8?q?fix=20#62=20=EC=9D=B4=EB=AF=B8=EC=A7=80?= =?UTF-8?q?=20url=20=EB=B3=80=EA=B2=BD,=20=EA=B8=B0=EB=B3=B8=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80=20=EC=9D=B4=EB=AF=B8=20=EC=A1=B4=EC=9E=AC?= =?UTF-8?q?=ED=95=98=EB=AF=80=EB=A1=9C=20=EB=94=94=ED=8F=B4=ED=8A=B8=20?= =?UTF-8?q?=EC=95=84=EB=B0=94=ED=83=80=20=ED=81=B4=EB=A6=AD=20=EC=8B=9C=20?= =?UTF-8?q?=EC=84=A0=ED=83=9D=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=ED=95=B4?= =?UTF-8?q?=EC=A0=9C=EB=90=98=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/option/background-select.jsx | 35 +++++---------------- src/pages/send-message-page.jsx | 32 +++++++------------ 2 files changed, 20 insertions(+), 47 deletions(-) diff --git a/src/components/option/background-select.jsx b/src/components/option/background-select.jsx index 2fc8875..2941375 100644 --- a/src/components/option/background-select.jsx +++ b/src/components/option/background-select.jsx @@ -48,7 +48,7 @@ const BackgroundOverlay = styled.div` `; function BackgroundSelect({ type, selected, onSelect }) { - const [imageUrls, setImageUrls] = useState([]); + const [backgroundUrls, setBackgroundUrls] = useState([]); const colorOptions = [ { color: Colors.beige(200) }, @@ -57,41 +57,22 @@ function BackgroundSelect({ type, selected, onSelect }) { { color: Colors.green(200) }, ]; - /* useEffect(() => { - if (type !== "image") return; - - const BackgroundImageUrls = async () => { - try { - const response = await fetch( - "https://rolling-api.vercel.app/background-images" - ); - const data = await response.json(); - setImageUrls(data.imageUrls || []); - } catch (error) { - console.error(error); - setImageUrls([]); - } - }; - BackgroundImageUrls(); - }, [type]); */ - - // 이미지 옵션 테스트 코드 useEffect(() => { if (type !== "image") return; - const testImages = [ - "https://i.pinimg.com/280x280_RS/44/d2/b0/44d2b0b9e08cf1f05b7215356925a146.jpg", - "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTPe2BEhk6RfeibdWPG-1Iac78Tk1bdO1Rtqg&s", - "https://center.exm.co.kr/data/goodsimg/phob/l/0018/027/18027744/61709_1661145612.jpg", - "https://i.pinimg.com/736x/35/4e/03/354e03cd79702063da7353ffea0c8f8b.jpg", + const imageUrls = [ + "https://picsum.photos/id/683/3840/2160", + "https://picsum.photos/id/24/3840/2160", + "https://picsum.photos/id/599/3840/2160", + "https://picsum.photos/id/1058/3840/2160", ]; - setImageUrls(testImages || []); + setBackgroundUrls(imageUrls || []); }, [type]); const options = type === "color" ? colorOptions - : imageUrls.map((url, index) => ({ label: `${index}`, url })); + : backgroundUrls.map((url, index) => ({ label: `${index}`, url })); return ( diff --git a/src/pages/send-message-page.jsx b/src/pages/send-message-page.jsx index 34c9beb..33c6ea1 100644 --- a/src/pages/send-message-page.jsx +++ b/src/pages/send-message-page.jsx @@ -54,14 +54,10 @@ const AvatarOption = styled.div` const AvatarPreview = styled.div` cursor: pointer; box-shadow: ${({ $isSelected }) => - $isSelected ? `0 0 0 2px ${Colors.purple(400)}` : "none"}; + $isSelected ? `0 0 0 2px ${Colors.purple(600)}` : "none"}; border-radius: 50%; `; -const DefaultAvatar = styled.div` - cursor: pointer; -`; - const ButtonWrapper = styled.div` padding-top: 50px; padding-bottom: 150px; @@ -108,16 +104,16 @@ function SendMessagePage() { }; const avatarList = [ - "https://i.pinimg.com/236x/49/86/62/4986627b45cecd1a5c4330bda777c2bf.jpg", - "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRok3sjZOWtm7o5kFf0BdW0w7IUHI1oAlC-Z6RCKAiCvvCExG_qq7qMzPOQlEzfknS3B3U&usqp=CAU", - "https://i.pinimg.com/236x/20/d1/6f/20d16f236500e8daa315a298a8586193.jpg", - "https://i.pinimg.com/474x/28/6c/fd/286cfdcdaeaf2768d4b285a226c33a02.jpg", - "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRvxR-Twic2lXwfF87JweyQ81vrGDUgn7zzYj60N-wD21DwS4JzOc0BLhzaOuUt4PGfLcI&usqp=CAU", - "https://i.pinimg.com/236x/74/68/89/7468894ce7592357a3514dbb8dc5f181.jpg", - "https://mblogthumb-phinf.pstatic.net/MjAyMTA5MDNfMjE1/MDAxNjMwNTk5NjE4NTc5.b-OgHjcav5kz8kt_9Cr2u1Z_eJYmKY_H9Ii9mOnwo74g.r0G6iGYg-oQMLnTymwyrjDlOMGLEnWGYJXefCSy2ixwg.JPEG.gmlwjd5363/FB_IMG_1630599533529.jpg?type=w800", - "https://mblogthumb-phinf.pstatic.net/MjAyMTA5MDNfMTIy/MDAxNjMwNTk5NjE5MDA5.w_wMeYmMF2kOhDAVXXxe0JgVqJhtGd0EuR0b2D2k3S0g.Nds6Oxagjks2DjjwFz5yWyjCGcEOL1iS84XqhAQw3wUg.JPEG.gmlwjd5363/FB_IMG_1630599535069.jpg?type=w800", - "https://mblogthumb-phinf.pstatic.net/MjAyMTA5MDNfNDQg/MDAxNjMwNTk5NjE5MzQ4.J4lhtJZRKMzEXj0HjrG1aH65qIcBv9GI1LdVQsWlC-Ug.10QCNt81CdbIyBkd1bFOAOAolDL6hxYXrb9dXgmS8zQg.JPEG.gmlwjd5363/FB_IMG_1630599536666.jpg?type=w800", - "https://mblogthumb-phinf.pstatic.net/MjAyMTA5MDNfMzAg/MDAxNjMwNTk5NjE5ODI2.cmwNyDHTza4N64bhN0rIRu2KaFHUxqv0BkuaX6GBHJ0g.ufZqe7x1GLrCLJg2zb6N_nJ_fTgFPXq09TTe_fhsMiog.JPEG.gmlwjd5363/FB_IMG_1630599538261.jpg?type=w800", + "https://learn-codeit-kr-static.s3.ap-northeast-2.amazonaws.com/sprint-proj-image/default_avatar.png", + "https://picsum.photos/id/522/100/100", + "https://picsum.photos/id/547/100/100", + "https://picsum.photos/id/268/100/100", + "https://picsum.photos/id/1082/100/100", + "https://picsum.photos/id/571/100/100", + "https://picsum.photos/id/494/100/100", + "https://picsum.photos/id/859/100/100", + "https://picsum.photos/id/437/100/100", + "https://picsum.photos/id/1064/100/100", ]; const handleCreate = () => { @@ -152,11 +148,7 @@ function SendMessagePage() { 프로필 이미지 - setSelectedAvatar((prev) => (prev ? null : prev))} // 아바타 선택 상태에서 재클릭 시 기본 아바타로 - > - - + 프로필 이미지를 선택해 주세요! From b6edaa812e59d1cb5f24b7d01809b0d0c603ac12 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 16 Aug 2025 16:49:34 +0900 Subject: [PATCH 180/253] =?UTF-8?q?feat=20[#35]=20=EB=A9=94=EC=8B=9C?= =?UTF-8?q?=EC=A7=80=20=EB=AA=A9=EB=A1=9D=20=EC=98=81=EC=97=AD=EC=9D=B4=20?= =?UTF-8?q?=EB=82=98=EB=A8=B8=EC=A7=80=20=EB=86=92=EC=9D=B4=EB=A5=BC=20?= =?UTF-8?q?=EA=BD=89=20=EC=B1=84=EC=9A=B0=EB=8F=84=EB=A1=9D=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../rolling-paper/api/mock-recipient.json | 2 +- src/layouts/content-layout.jsx | 18 +++++++++++++++--- src/pages/messages-page.jsx | 10 +++++++--- 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/features/rolling-paper/api/mock-recipient.json b/src/features/rolling-paper/api/mock-recipient.json index 3ef6d7e..1d73284 100644 --- a/src/features/rolling-paper/api/mock-recipient.json +++ b/src/features/rolling-paper/api/mock-recipient.json @@ -1,7 +1,7 @@ { "id": 2, "name": "강영훈", - "backgroundColor": "green", + "backgroundColor": "#FFE2AD", "backgroundImageURL": null, "createdAt": "2023-10-26T13:19:31.401765Z", "messageCount": 30, diff --git a/src/layouts/content-layout.jsx b/src/layouts/content-layout.jsx index d6b6307..ee6e9fb 100644 --- a/src/layouts/content-layout.jsx +++ b/src/layouts/content-layout.jsx @@ -1,11 +1,23 @@ +import styled from "styled-components"; import Header from "../components/header/header"; +const Main = styled.main` + flex-grow: 1; + min-height: 100vh - 64px; +`; + +const StyledContentLayout = styled.div` + display: flex; + flex-direction: column; + height: 100vh; +`; + function ContentLayout({ children }) { return ( - <> +
-
{children}
- +
{children}
+ ); } diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx index 6b93fa1..dfedd34 100644 --- a/src/pages/messages-page.jsx +++ b/src/pages/messages-page.jsx @@ -1,9 +1,15 @@ import { useEffect, useState } from "react"; +import styled from "styled-components"; import { getRecipient } from "../features/rolling-paper/api/recipients"; import RollingPaperHeader from "../features/rolling-paper/components/rolling-paper-header"; import { useMedia } from "../hooks/use-media"; import ContentLayout from "../layouts/content-layout"; +const Content = styled.div` + background-color: ${({ $backgroundColor }) => $backgroundColor}; + height: calc(100% - 68px); +`; + function MessagesPage() { const { isMobile } = useMedia(); const [recipient, setRecipient] = useState(); @@ -22,9 +28,7 @@ function MessagesPage() { messages={recipient.recentMessages} reactions={recipient.topReactions} /> -
-

Messages Page

-
+ )} From 7b1667876d8f914b225694af9e92b2b2124f93e7 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 21 Aug 2025 07:47:34 +0900 Subject: [PATCH 181/253] =?UTF-8?q?refactor=20[#35]=20header=20=EA=B4=80?= =?UTF-8?q?=EB=A0=A8=20=ED=8C=8C=EC=9D=BC=EC=9D=84=20=ED=8F=B4=EB=8D=94?= =?UTF-8?q?=EB=A1=9C=20=EB=AC=B6=EC=9D=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{ => header}/rolling-paper-header.jsx | 24 +++++++++---------- .../{ => header}/rolling-paper-reactions.jsx | 12 +++++----- .../rolling-paper-sender-avatars.jsx | 4 ++-- .../{ => header}/rolling-paper-senders.jsx | 0 .../rolling-paper-share-popover.jsx | 2 +- src/pages/messages-page.jsx | 2 +- 6 files changed, 22 insertions(+), 22 deletions(-) rename src/features/rolling-paper/components/{ => header}/rolling-paper-header.jsx (84%) rename src/features/rolling-paper/components/{ => header}/rolling-paper-reactions.jsx (78%) rename src/features/rolling-paper/components/{ => header}/rolling-paper-sender-avatars.jsx (94%) rename src/features/rolling-paper/components/{ => header}/rolling-paper-senders.jsx (100%) rename src/features/rolling-paper/components/{ => header}/rolling-paper-share-popover.jsx (93%) diff --git a/src/features/rolling-paper/components/rolling-paper-header.jsx b/src/features/rolling-paper/components/header/rolling-paper-header.jsx similarity index 84% rename from src/features/rolling-paper/components/rolling-paper-header.jsx rename to src/features/rolling-paper/components/header/rolling-paper-header.jsx index 6a48d9c..5c86ecd 100644 --- a/src/features/rolling-paper/components/rolling-paper-header.jsx +++ b/src/features/rolling-paper/components/header/rolling-paper-header.jsx @@ -1,17 +1,17 @@ import EmojiPicker from "emoji-picker-react"; import styled from "styled-components"; -import addImage from "../../../assets/ic-face-smile-add.svg"; -import shareImage from "../../../assets/ic-share.svg"; -import { OutlinedButton } from "../../../components/button/button"; -import BUTTON_SIZE from "../../../components/button/button-size"; -import Colors from "../../../components/color/colors"; -import Popover from "../../../components/popover/popover"; -import POPOVER_ALIGNMENT from "../../../components/popover/popover-alignment"; -import Toast from "../../../components/toast/toast"; -import { useMedia } from "../../../hooks/use-media"; -import { useToast } from "../../../hooks/use-toast"; -import { shareRollingPaper } from "../../../libs/kakao/kakao-service"; -import { media } from "../../../utils/media"; +import addImage from "../../../../assets/ic-face-smile-add.svg"; +import shareImage from "../../../../assets/ic-share.svg"; +import { OutlinedButton } from "../../../../components/button/button"; +import BUTTON_SIZE from "../../../../components/button/button-size"; +import Colors from "../../../../components/color/colors"; +import Popover from "../../../../components/popover/popover"; +import POPOVER_ALIGNMENT from "../../../../components/popover/popover-alignment"; +import Toast from "../../../../components/toast/toast"; +import { useMedia } from "../../../../hooks/use-media"; +import { useToast } from "../../../../hooks/use-toast"; +import { shareRollingPaper } from "../../../../libs/kakao/kakao-service"; +import { media } from "../../../../utils/media"; import RollingPaperReactions from "./rolling-paper-reactions"; import RollingPaperSenders from "./rolling-paper-senders"; import RollingPaperSharePopover from "./rolling-paper-share-popover"; diff --git a/src/features/rolling-paper/components/rolling-paper-reactions.jsx b/src/features/rolling-paper/components/header/rolling-paper-reactions.jsx similarity index 78% rename from src/features/rolling-paper/components/rolling-paper-reactions.jsx rename to src/features/rolling-paper/components/header/rolling-paper-reactions.jsx index 689a4c0..ec66dc8 100644 --- a/src/features/rolling-paper/components/rolling-paper-reactions.jsx +++ b/src/features/rolling-paper/components/header/rolling-paper-reactions.jsx @@ -1,10 +1,10 @@ import styled from "styled-components"; -import arrowDownImage from "../../../assets/ic-chevron-down.svg"; -import EmojiBadge from "../../../components/badge/emoji-badge"; -import Popover from "../../../components/popover/popover"; -import POPOVER_ALIGNMENT from "../../../components/popover/popover-alignment"; -import { useMedia } from "../../../hooks/use-media"; -import { media } from "../../../utils/media"; +import arrowDownImage from "../../../../assets/ic-chevron-down.svg"; +import EmojiBadge from "../../../../components/badge/emoji-badge"; +import Popover from "../../../../components/popover/popover"; +import POPOVER_ALIGNMENT from "../../../../components/popover/popover-alignment"; +import { useMedia } from "../../../../hooks/use-media"; +import { media } from "../../../../utils/media"; const MoreButton = styled.button` background: none; diff --git a/src/features/rolling-paper/components/rolling-paper-sender-avatars.jsx b/src/features/rolling-paper/components/header/rolling-paper-sender-avatars.jsx similarity index 94% rename from src/features/rolling-paper/components/rolling-paper-sender-avatars.jsx rename to src/features/rolling-paper/components/header/rolling-paper-sender-avatars.jsx index 9a127f9..2183b49 100644 --- a/src/features/rolling-paper/components/rolling-paper-sender-avatars.jsx +++ b/src/features/rolling-paper/components/header/rolling-paper-sender-avatars.jsx @@ -1,7 +1,7 @@ import { useEffect, useRef, useState } from "react"; import styled from "styled-components"; -import Avatar from "../../../components/avatar/avatar"; -import AVATAR_SIZE from "../../../components/avatar/avatar-size"; +import Avatar from "../../../../components/avatar/avatar"; +import AVATAR_SIZE from "../../../../components/avatar/avatar-size"; const METRICS = { size: AVATAR_SIZE.extraSmall, diff --git a/src/features/rolling-paper/components/rolling-paper-senders.jsx b/src/features/rolling-paper/components/header/rolling-paper-senders.jsx similarity index 100% rename from src/features/rolling-paper/components/rolling-paper-senders.jsx rename to src/features/rolling-paper/components/header/rolling-paper-senders.jsx diff --git a/src/features/rolling-paper/components/rolling-paper-share-popover.jsx b/src/features/rolling-paper/components/header/rolling-paper-share-popover.jsx similarity index 93% rename from src/features/rolling-paper/components/rolling-paper-share-popover.jsx rename to src/features/rolling-paper/components/header/rolling-paper-share-popover.jsx index d2ffcb3..310479f 100644 --- a/src/features/rolling-paper/components/rolling-paper-share-popover.jsx +++ b/src/features/rolling-paper/components/header/rolling-paper-share-popover.jsx @@ -1,5 +1,5 @@ import styled from "styled-components"; -import Colors from "../../../components/color/colors"; +import Colors from "../../../../components/color/colors"; const ShareOption = styled.li` padding: 12px 16px; diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx index dfedd34..0ac9e46 100644 --- a/src/pages/messages-page.jsx +++ b/src/pages/messages-page.jsx @@ -1,7 +1,7 @@ import { useEffect, useState } from "react"; import styled from "styled-components"; import { getRecipient } from "../features/rolling-paper/api/recipients"; -import RollingPaperHeader from "../features/rolling-paper/components/rolling-paper-header"; +import RollingPaperHeader from "../features/rolling-paper/components/header/rolling-paper-header"; import { useMedia } from "../hooks/use-media"; import ContentLayout from "../layouts/content-layout"; From 7d8c8f0d1ec0406ab97634ebb109c01e086c5d00 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 16 Aug 2025 17:03:40 +0900 Subject: [PATCH 182/253] =?UTF-8?q?feat=20[#35]=20Messages=20Grid=20layout?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../messages/rolling-paper-messages-grid.jsx | 42 +++++++++++++++++++ src/pages/messages-page.jsx | 5 ++- 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx diff --git a/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx b/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx new file mode 100644 index 0000000..11aec3f --- /dev/null +++ b/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx @@ -0,0 +1,42 @@ +import styled from "styled-components"; +import { media } from "../../../../utils/media"; + +const MessageCard = styled.div` + background-color: blue; + height: 200px; +`; + +const StyledRollingPaperMessagesGrid = styled.div` + display: grid; + grid-template-columns: repeat(3, 1fr); + column-gap: 24px; + row-gap: 28px; + margin: 0 auto; + max-width: 1200px; + padding: 112px 0 246px; + + @media (max-width: 1248px) { + padding: 93px 24px 91px; + grid-template-columns: repeat(2, 1fr); + gap: 16px; + } + + ${media.mobile} { + padding: 24px 20px 38px; + grid-template-columns: repeat(1, 1fr); + } +`; + +function RollingPaperMessagesGrid() { + return ( + + + + + + + + ); +} + +export default RollingPaperMessagesGrid; diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx index 0ac9e46..8a9542f 100644 --- a/src/pages/messages-page.jsx +++ b/src/pages/messages-page.jsx @@ -2,6 +2,7 @@ import { useEffect, useState } from "react"; import styled from "styled-components"; import { getRecipient } from "../features/rolling-paper/api/recipients"; import RollingPaperHeader from "../features/rolling-paper/components/header/rolling-paper-header"; +import RollingPaperMessagesGrid from "../features/rolling-paper/components/messages/rolling-paper-messages-grid"; import { useMedia } from "../hooks/use-media"; import ContentLayout from "../layouts/content-layout"; @@ -28,7 +29,9 @@ function MessagesPage() { messages={recipient.recentMessages} reactions={recipient.topReactions} /> - + + + )} From ce2f6fa9c90f85fe2fc4365aadcab1cb25f3be14 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 16 Aug 2025 17:30:56 +0900 Subject: [PATCH 183/253] =?UTF-8?q?feat=20[#35]=20`formatDate`=EC=97=90=20?= =?UTF-8?q?=EB=AC=B8=EC=9E=90=EC=97=B4=20=ED=98=95=EC=8B=9D=20=EB=82=A0?= =?UTF-8?q?=EC=A7=9C=EB=A5=BC=20=EC=A0=84=EB=8B=AC=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=EA=B2=BD=EC=9A=B0=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/formatter.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/utils/formatter.js b/src/utils/formatter.js index 14596a1..cb992c5 100644 --- a/src/utils/formatter.js +++ b/src/utils/formatter.js @@ -1,7 +1,14 @@ function formatDate(date, token = "-") { - const year = date.getFullYear(); - const month = `${date.getMonth() + 1}`.padStart(2, "0"); - const day = `${date.getDate()}`.padStart(2, "0"); + let _date; + if (typeof date === 'string') { + _date = new Date(date); + } else { + _date = date; + } + + const year = _date.getFullYear(); + const month = `${_date.getMonth() + 1}`.padStart(2, "0"); + const day = `${_date.getDate()}`.padStart(2, "0"); return `${year}${token}${month}${token}${day}`; } From acb591926270b065615cf0969a683bb50bbce9f3 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 16 Aug 2025 17:31:28 +0900 Subject: [PATCH 184/253] =?UTF-8?q?feat=20[#35]=20MessageCard=20component?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84=20=EB=B0=8F=20messages=20grid=EC=97=90=20?= =?UTF-8?q?=ED=91=9C=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../message/components/message-card.jsx.jsx | 56 +++++++++++++++++++ .../message/components/message-sender.jsx | 54 ++++++++++++++++++ .../messages/rolling-paper-messages-grid.jsx | 16 ++---- src/pages/messages-page.jsx | 2 +- 4 files changed, 116 insertions(+), 12 deletions(-) create mode 100644 src/features/message/components/message-card.jsx.jsx create mode 100644 src/features/message/components/message-sender.jsx diff --git a/src/features/message/components/message-card.jsx.jsx b/src/features/message/components/message-card.jsx.jsx new file mode 100644 index 0000000..1301fe4 --- /dev/null +++ b/src/features/message/components/message-card.jsx.jsx @@ -0,0 +1,56 @@ +import styled from "styled-components"; +import Colors from "../../../components/color/colors"; +import { formatDate } from "../../../utils/formatter"; +import { media } from "../../../utils/media"; +import MessageSender from "./message-sender"; + +const Header = styled.header` + padding-bottom: 16px; + border-bottom: 1px solid ${Colors.gray(200)}; +`; + +const Content = styled.div` + margin: 16px 0; + font-size: 18px; + font-weight: 400; + line-height: 28px; + color: ${Colors.gray(600)}; + + ${media.mobile} { + font-size: 15px; + line-height: 22px; + } +`; + +const CreatedDate = styled.span` + font-size: 12px; + font-weight: 400; + line-height: 18px; + color: ${Colors.gray(400)}; +`; + +const StyledMessageCard = styled.article` + display: flex; + flex-direction: column; + padding: 24px; + border-radius: 16px; + background-color: white; + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08); +`; + +function MessageCard({ message }) { + return ( + +
+ +
+ {message.content} + {formatDate(message.createdAt, ".")} +
+ ); +} + +export default MessageCard; diff --git a/src/features/message/components/message-sender.jsx b/src/features/message/components/message-sender.jsx new file mode 100644 index 0000000..d59d0ee --- /dev/null +++ b/src/features/message/components/message-sender.jsx @@ -0,0 +1,54 @@ +import styled from "styled-components"; +import Avatar from "../../../components/avatar/avatar"; +import Badge from "../../../components/badge/badge"; +import BADGE_TYPE from "../../../components/badge/badge-type"; +import { media } from "../../../utils/media"; + +const SenderName = styled.span` + font-size: 20px; + font-weight: 400; + line-height: 24px; + + span { + font-weight: 700; + } + + ${media.mobile} { + font-size: 16px; + line-height: 26px; + } +`; + +const StyledSenderInfo = styled.div` + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 6px; +`; + +function SenderInfo({ name, type }) { + return ( + + + From.{` ${name}`} + + + + ); +} +const StyledMessageSender = styled.div` + display: flex; + align-items: center; + gap: 14px; +`; + +function MessageSender({ profileImage, name }) { + return ( + + + + + ); +} + +export default MessageSender; diff --git a/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx b/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx index 11aec3f..e95f805 100644 --- a/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx +++ b/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx @@ -1,10 +1,6 @@ import styled from "styled-components"; import { media } from "../../../../utils/media"; - -const MessageCard = styled.div` - background-color: blue; - height: 200px; -`; +import MessageCard from "../../../message/components/message-card.jsx"; const StyledRollingPaperMessagesGrid = styled.div` display: grid; @@ -27,14 +23,12 @@ const StyledRollingPaperMessagesGrid = styled.div` } `; -function RollingPaperMessagesGrid() { +function RollingPaperMessagesGrid({ messages }) { return ( - - - - - + {messages.map((message) => ( + + ))} ); } diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx index 8a9542f..e821ab1 100644 --- a/src/pages/messages-page.jsx +++ b/src/pages/messages-page.jsx @@ -30,7 +30,7 @@ function MessagesPage() { reactions={recipient.topReactions} /> - + )} From f3a3e5a4c957edb31f2d0c5feb9b40a369d271dd Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 16 Aug 2025 17:33:26 +0900 Subject: [PATCH 185/253] =?UTF-8?q?feat=20[#35]=20MessageCard=EC=97=90=20?= =?UTF-8?q?=EC=B5=9C=EC=86=8C=20=EB=86=92=EC=9D=B4=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/message/components/message-card.jsx.jsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/features/message/components/message-card.jsx.jsx b/src/features/message/components/message-card.jsx.jsx index 1301fe4..7515303 100644 --- a/src/features/message/components/message-card.jsx.jsx +++ b/src/features/message/components/message-card.jsx.jsx @@ -36,6 +36,15 @@ const StyledMessageCard = styled.article` border-radius: 16px; background-color: white; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08); + min-height: 280px; + + ${media.tablet} { + min-height: 284px; + } + + ${media.mobile} { + min-height: 230px; + } `; function MessageCard({ message }) { From 02deef27dad447cf725dd1698da7f984b406fa10 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 16 Aug 2025 18:47:31 +0900 Subject: [PATCH 186/253] =?UTF-8?q?refactor=20[]=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=EC=97=90=20`.jsx`=20=EB=91=90=20=EB=B2=88=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=ED=95=9C=20=EA=B2=83=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../message/components/{message-card.jsx.jsx => message-card.jsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/features/message/components/{message-card.jsx.jsx => message-card.jsx} (100%) diff --git a/src/features/message/components/message-card.jsx.jsx b/src/features/message/components/message-card.jsx similarity index 100% rename from src/features/message/components/message-card.jsx.jsx rename to src/features/message/components/message-card.jsx From d2f36e3a0578009248cdd9164d90c6da7f345171 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 16 Aug 2025 18:55:48 +0900 Subject: [PATCH 187/253] =?UTF-8?q?feat=20[#35]=20MessagedCard=20grid=20?= =?UTF-8?q?=EC=B2=AB=20=EB=B2=88=EC=A7=B8=20item=EC=9D=84=20message=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B2=84=ED=8A=BC=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EA=B3=A0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `post/:id/message` page로 이동 --- src/assets/ic-plus.svg | 4 ++ .../message/components/message-card-add.jsx | 46 +++++++++++++++++++ .../messages/rolling-paper-messages-grid.jsx | 10 ++++ 3 files changed, 60 insertions(+) create mode 100644 src/assets/ic-plus.svg create mode 100644 src/features/message/components/message-card-add.jsx diff --git a/src/assets/ic-plus.svg b/src/assets/ic-plus.svg new file mode 100644 index 0000000..27c0fd4 --- /dev/null +++ b/src/assets/ic-plus.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/features/message/components/message-card-add.jsx b/src/features/message/components/message-card-add.jsx new file mode 100644 index 0000000..9fbeb23 --- /dev/null +++ b/src/features/message/components/message-card-add.jsx @@ -0,0 +1,46 @@ +import styled from "styled-components"; +import plusImage from "../../../assets/ic-plus.svg"; +import Colors from "../../../components/color/colors"; +import { media } from "../../../utils/media"; + +const AddCircle = styled.div` + width: 56px; + height: 56px; + border-radius: 28px; + background-color: ${Colors.gray(500)}; + display: flex; + justify-content: center; + align-items: center; +`; + +const StyledMessageCardAdd = styled.button` + border: none; + display: flex; + justify-content: center; + align-items: center; + border-radius: 16px; + background-color: white; + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08); + min-height: 280px; + cursor: pointer; + + ${media.tablet} { + min-height: 284px; + } + + ${media.mobile} { + min-height: 230px; + } +`; + +function MessageCardAdd({ onClick }) { + return ( + + + Message 추가 + + + ); +} + +export default MessageCardAdd; diff --git a/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx b/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx index e95f805..413ae44 100644 --- a/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx +++ b/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx @@ -1,5 +1,7 @@ +import { useNavigate, useParams } from "react-router"; import styled from "styled-components"; import { media } from "../../../../utils/media"; +import MessageCardAdd from "../../../message/components/message-card-add.jsx"; import MessageCard from "../../../message/components/message-card.jsx"; const StyledRollingPaperMessagesGrid = styled.div` @@ -24,8 +26,16 @@ const StyledRollingPaperMessagesGrid = styled.div` `; function RollingPaperMessagesGrid({ messages }) { + const navigate = useNavigate(); + const { id } = useParams(); + + const handleAddClick = () => { + navigate(`/post/${id}/message`); + }; + return ( + {messages.map((message) => ( ))} From 46a351e088fe82c3234d0872948f532d40a69d5f Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 16 Aug 2025 19:30:42 +0900 Subject: [PATCH 188/253] =?UTF-8?q?feat=20[#35]=20MessageCard=20=EB=86=92?= =?UTF-8?q?=EC=9D=B4=EB=A5=BC=20=EC=A4=84=20=EC=88=98=20=EA=B8=B0=EB=B0=98?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EA=B2=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Desktop, tablet : 최대 4줄 - Mobile : 최대 3줄 - MessageCard를 클릭해서 나타나는 modal로 전체 message를 확인할 수 있게 될 것 --- .../message/components/message-card.jsx | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/features/message/components/message-card.jsx b/src/features/message/components/message-card.jsx index 7515303..290a0d9 100644 --- a/src/features/message/components/message-card.jsx +++ b/src/features/message/components/message-card.jsx @@ -15,10 +15,16 @@ const Content = styled.div` font-weight: 400; line-height: 28px; color: ${Colors.gray(600)}; + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-line-clamp: 4; + -webkit-box-orient: vertical; ${media.mobile} { font-size: 15px; line-height: 22px; + -webkit-line-clamp: 3; } `; @@ -36,15 +42,6 @@ const StyledMessageCard = styled.article` border-radius: 16px; background-color: white; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08); - min-height: 280px; - - ${media.tablet} { - min-height: 284px; - } - - ${media.mobile} { - min-height: 230px; - } `; function MessageCard({ message }) { @@ -56,7 +53,15 @@ function MessageCard({ message }) { name={message.sender} />
- {message.content} + + {message.content + + message.content + + message.content + + message.content + + message.content + + message.content + + message.content} + {formatDate(message.createdAt, ".")} ); From c3c05e592278ab4b17bc4e771817d83289984a2a Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 16 Aug 2025 19:54:35 +0900 Subject: [PATCH 189/253] =?UTF-8?q?feat=20[#35]=20=EA=B3=B5=ED=86=B5=20com?= =?UTF-8?q?ponent=EC=9D=B8=20`Modal`=EC=97=90=EC=84=9C=20domain=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20data=EB=A5=BC=20=EC=A0=9C=EA=B1=B0?= =?UTF-8?q?=ED=95=98=EA=B3=A0=20=EC=99=B8=EB=B6=80=EC=97=90=EC=84=9C=20con?= =?UTF-8?q?tent=20=EC=A3=BC=EC=9E=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/modal/modal.jsx | 133 +++------------------------------ src/pages/test-page.jsx | 7 +- 2 files changed, 15 insertions(+), 125 deletions(-) diff --git a/src/components/modal/modal.jsx b/src/components/modal/modal.jsx index a098817..088e5c1 100644 --- a/src/components/modal/modal.jsx +++ b/src/components/modal/modal.jsx @@ -1,118 +1,14 @@ import styled from "styled-components"; import { useModal } from "../../hooks/use-modal"; -import { formatDate } from "../../utils/formatter"; -import Avatar from "../avatar/avatar"; -import Badge from "../badge/badge"; -import BADGE_TYPE from "../badge/badge-type"; import { PrimaryButton } from "../button/button"; import BUTTON_SIZE from "../button/button-size"; -import Colors from "../color/colors"; import Portal from "../portal/portal"; -/* UserInfo */ - -const Name = styled.span` - font-size: 20px; - font-weight: 400; - line-height: 24px; - - span { - font-weight: 700; - } -`; - -const StyledUserInfo = styled.div` +const Content = styled.div` + width: 100%; display: flex; flex-direction: column; - align-items: flex-start; - gap: 6px; -`; - -function UserInfo({ name, type }) { - return ( - - - From.{` ${name}`} - - - - ); -} - -/* UserProfile */ - -const StyledUserProfile = styled.div` - display: flex; - align-items: center; - gap: 16px; -`; - -function UserProfile({ profileImage, name }) { - return ( - - - - - ); -} - -/* Header */ - -const Date = styled.span` - font-size: 14px; - font-weight: 400; - line-height: 20px; - color: ${Colors.gray(400)}; -`; - -const StyledHeader = styled.div` - width: 100%; - border-bottom: 1px solid ${Colors.gray(200)}; - - & > div { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 19px; - } -`; - -function Header({ profileImage, name, date }) { - return ( - -
- - {formatDate(date, ".")} -
-
- ); -} - -/* Modal */ - -const Content = styled.p` - margin: 16px 0 24px; - height: 240px; - overflow: scroll; - font-size: 18px; - font-weight: 400; - line-height: 28px; - color: #5a5a5a; - padding-right: 16px; - - &::-webkit-scrollbar { - width: 4px; - height: 0px; - } - - &::-webkit-scrollbar-thumb { - background-color: ${Colors.gray(300)}; - border-radius: 2px; - - &:hover { - background-color: ${Colors.gray(400)}; - } - } + gap: 24px; `; const StyledModal = styled.div` @@ -126,8 +22,6 @@ const StyledModal = styled.div` align-items: center; `; -/* Container */ - const ModalContainer = styled.div` position: fixed; top: 0; @@ -140,7 +34,7 @@ const ModalContainer = styled.div` align-items: center; `; -function Modal({ id, user, date, content, action }) { +function Modal({ id, action, children }) { const { showsModal, setShowsModal } = useModal({ id: id, type: "modal", @@ -156,17 +50,14 @@ function Modal({ id, user, date, content, action }) { -
- {content} - + + {children} + + diff --git a/src/pages/test-page.jsx b/src/pages/test-page.jsx index 11df80e..c6849dd 100644 --- a/src/pages/test-page.jsx +++ b/src/pages/test-page.jsx @@ -201,11 +201,10 @@ function TestPage() {
} - /> + > +

This is Modal.

+
Date: Sat, 16 Aug 2025 20:12:08 +0900 Subject: [PATCH 190/253] =?UTF-8?q?feat=20[#35]=20MessageCard=EB=A5=BC=20?= =?UTF-8?q?=ED=81=B4=EB=A6=AD=ED=95=98=EB=A9=B4=20modal=EB=A1=9C=20?= =?UTF-8?q?=EC=A0=84=EC=B2=B4=20message=20=EB=B3=B4=EC=97=AC=EC=A3=BC?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/message-card-detail.jsx | 61 +++++++++++++++++++ .../messages/rolling-paper-messages-grid.jsx | 12 +++- 2 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 src/features/message/components/message-card-detail.jsx diff --git a/src/features/message/components/message-card-detail.jsx b/src/features/message/components/message-card-detail.jsx new file mode 100644 index 0000000..8d4c628 --- /dev/null +++ b/src/features/message/components/message-card-detail.jsx @@ -0,0 +1,61 @@ +import styled from "styled-components"; +import Colors from "../../../components/color/colors"; +import { formatDate } from "../../../utils/formatter"; +import MessageSender from "./message-sender"; + +const Header = styled.header` + display: flex; + justify-content: space-between; + align-items: center; + padding-bottom: 19px; + border-bottom: 1px solid ${Colors.gray(200)}; +`; + +const Content = styled.div` + margin-top: 16px; + font-size: 18px; + font-weight: 400; + line-height: 28px; + color: #5a5a5a; + max-height: 240px; + overflow: scroll; + + &::-webkit-scrollbar { + width: 4px; + } + + &::-webkit-scrollbar-thumb { + background-color: ${Colors.gray(300)}; + border-radius: 2px; + + &:hover { + background-color: ${Colors.gray(400)}; + } + } +`; + +const CreatedDate = styled.span` + font-size: 14px; + font-weight: 400; + line-height: 20px; + color: ${Colors.gray(400)}; +`; + +const StyledMessageCardDetail = styled.div``; + +function MessageCardDetail({ message }) { + return ( +
+
+ + {formatDate(message.createdAt, ".")} +
+ {message.content} +
+ ); +} + +export default MessageCardDetail; diff --git a/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx b/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx index 413ae44..4c4b3c2 100644 --- a/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx +++ b/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx @@ -1,7 +1,9 @@ import { useNavigate, useParams } from "react-router"; import styled from "styled-components"; -import { media } from "../../../../utils/media"; +import Modal from "../../../../components/modal/modal.jsx"; +import { media } from "../../../../utils/media.js"; import MessageCardAdd from "../../../message/components/message-card-add.jsx"; +import MessageCardDetail from "../../../message/components/message-card-detail.jsx"; import MessageCard from "../../../message/components/message-card.jsx"; const StyledRollingPaperMessagesGrid = styled.div` @@ -37,7 +39,13 @@ function RollingPaperMessagesGrid({ messages }) { {messages.map((message) => ( - + } + > + + ))} ); From 9b7c0ee0399c5fabc29a7036a9bda4cc7f1a96f5 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 16 Aug 2025 20:12:29 +0900 Subject: [PATCH 191/253] =?UTF-8?q?fix=20[#35]=20MessageCard=20=EC=B5=9C?= =?UTF-8?q?=EC=86=8C=20=EB=86=92=EC=9D=B4=20=EC=84=A4=EC=A0=95,=20test?= =?UTF-8?q?=EC=9A=A9=20=EC=BD=94=EB=93=9C=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/message/components/message-card.jsx | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/features/message/components/message-card.jsx b/src/features/message/components/message-card.jsx index 290a0d9..221786e 100644 --- a/src/features/message/components/message-card.jsx +++ b/src/features/message/components/message-card.jsx @@ -20,11 +20,13 @@ const Content = styled.div` display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; + min-height: 112px; /* line-height x 4 */ ${media.mobile} { font-size: 15px; line-height: 22px; -webkit-line-clamp: 3; + min-height: 66px; /* line-height x 3 */ } `; @@ -53,15 +55,7 @@ function MessageCard({ message }) { name={message.sender} />
- - {message.content + - message.content + - message.content + - message.content + - message.content + - message.content + - message.content} - + {message.content} {formatDate(message.createdAt, ".")} ); From 375d22f7c5a3ecf1a52749961ad5b63757751ca4 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 16 Aug 2025 20:13:34 +0900 Subject: [PATCH 192/253] =?UTF-8?q?feat=20[#35]=20Modal=EC=9D=98=20action?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8A=94=20com?= =?UTF-8?q?ponent=EC=97=90=20=ED=95=AD=EC=83=81=20pointer=20cursor=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/modal/modal.jsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/modal/modal.jsx b/src/components/modal/modal.jsx index 088e5c1..deb75b5 100644 --- a/src/components/modal/modal.jsx +++ b/src/components/modal/modal.jsx @@ -34,6 +34,10 @@ const ModalContainer = styled.div` align-items: center; `; +const ActionButton = styled.div` + cursor: pointer; +`; + function Modal({ id, action, children }) { const { showsModal, setShowsModal } = useModal({ id: id, @@ -45,7 +49,7 @@ function Modal({ id, action, children }) { return ( <> -
{action}
+ {action} {showsModal && ( From 6ff3c1fbff5777a45cf9972719aa6ec496ae856e Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 16 Aug 2025 20:16:02 +0900 Subject: [PATCH 193/253] =?UTF-8?q?fix=20[#35]=20ContentLayout=EC=9D=98=20?= =?UTF-8?q?header=20=ED=81=AC=EA=B8=B0=EA=B0=80=20=EC=A4=84=EC=96=B4?= =?UTF-8?q?=EB=93=A4=EC=A7=80=20=EC=95=8A=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/layouts/content-layout.jsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/layouts/content-layout.jsx b/src/layouts/content-layout.jsx index ee6e9fb..1c42e54 100644 --- a/src/layouts/content-layout.jsx +++ b/src/layouts/content-layout.jsx @@ -1,6 +1,10 @@ import styled from "styled-components"; import Header from "../components/header/header"; +const LayoutHeader = styled(Header)` + flex-shrink: 0; +`; + const Main = styled.main` flex-grow: 1; min-height: 100vh - 64px; @@ -15,7 +19,7 @@ const StyledContentLayout = styled.div` function ContentLayout({ children }) { return ( -
+
{children}
); From ffdb3aaf65a64c1a18f68d05e5fc0b34fbb2e347 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Wed, 20 Aug 2025 17:20:29 +0900 Subject: [PATCH 194/253] =?UTF-8?q?feat=20[#35]=20Mock=20data=EC=97=90=20b?= =?UTF-8?q?ackground=20image=20url=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/rolling-paper/api/mock-recipient.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/rolling-paper/api/mock-recipient.json b/src/features/rolling-paper/api/mock-recipient.json index 1d73284..3423c1b 100644 --- a/src/features/rolling-paper/api/mock-recipient.json +++ b/src/features/rolling-paper/api/mock-recipient.json @@ -2,7 +2,7 @@ "id": 2, "name": "강영훈", "backgroundColor": "#FFE2AD", - "backgroundImageURL": null, + "backgroundImageURL": "https://picsum.photos/id/1058/3840/2160", "createdAt": "2023-10-26T13:19:31.401765Z", "messageCount": 30, "recentMessages": [ From 70e36d904aea4bbe8a674f2111ce63935f676e38 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Wed, 20 Aug 2025 19:09:17 +0900 Subject: [PATCH 195/253] =?UTF-8?q?feat=20[#35]=20Background=20image=20url?= =?UTF-8?q?=EC=9D=B4=20=EC=97=86=EC=9D=84=20=EB=95=8C=EB=A7=8C=20backgroun?= =?UTF-8?q?d=20color=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/messages-page.jsx | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx index e821ab1..6dc99f3 100644 --- a/src/pages/messages-page.jsx +++ b/src/pages/messages-page.jsx @@ -6,8 +6,19 @@ import RollingPaperMessagesGrid from "../features/rolling-paper/components/messa import { useMedia } from "../hooks/use-media"; import ContentLayout from "../layouts/content-layout"; +const backgroundStyle = ({ $backgroundImageUrl, $backgroundColor }) => { + if (!$backgroundImageUrl) { + return `background-color: ${$backgroundColor}`; + } + + return ` + background: url('${$backgroundImageUrl}'); + background-size: contain; + `; +}; + const Content = styled.div` - background-color: ${({ $backgroundColor }) => $backgroundColor}; + ${backgroundStyle}; height: calc(100% - 68px); `; @@ -29,7 +40,10 @@ function MessagesPage() { messages={recipient.recentMessages} reactions={recipient.topReactions} /> - + From c8c06ecc691e3a37bb5a59b766c18a1003159e03 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Wed, 20 Aug 2025 19:14:26 +0900 Subject: [PATCH 196/253] =?UTF-8?q?fix=20[#35]=20Desktop=20size=EC=97=90?= =?UTF-8?q?=EC=84=9C=20message=20card=20grid=EC=9D=98=20=EB=84=88=EB=B9=84?= =?UTF-8?q?=EB=A5=BC=201200px=EB=A1=9C=20=EA=B3=A0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/messages/rolling-paper-messages-grid.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx b/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx index 4c4b3c2..a7e5b05 100644 --- a/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx +++ b/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx @@ -12,10 +12,11 @@ const StyledRollingPaperMessagesGrid = styled.div` column-gap: 24px; row-gap: 28px; margin: 0 auto; - max-width: 1200px; + width: 1200px; padding: 112px 0 246px; @media (max-width: 1248px) { + width: 100%; padding: 93px 24px 91px; grid-template-columns: repeat(2, 1fr); gap: 16px; From d57587e9aa747157171741fc3ba2a48808b7b375 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Wed, 20 Aug 2025 20:12:29 +0900 Subject: [PATCH 197/253] =?UTF-8?q?feat=20[#35]=20Message=20card=20grid=20?= =?UTF-8?q?=EC=83=81=EB=8B=A8=EC=97=90=20=EC=88=98=EC=A0=95=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=20=EC=B6=94=EA=B0=80,=20edit=20path=EC=97=90=20?= =?UTF-8?q?=EA=B0=99=EC=9D=80=20component=20page=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.jsx | 21 ++++---- .../messages/rolling-paper-messages-grid.jsx | 6 --- src/pages/messages-page.jsx | 48 ++++++++++++++++++- 3 files changed, 59 insertions(+), 16 deletions(-) diff --git a/src/app.jsx b/src/app.jsx index 2ee741b..a13aac0 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -43,15 +43,18 @@ function App() { } /> - - - - } - /> - } /> + + } /> + } /> + + + + } + /> + } /> } /> diff --git a/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx b/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx index a7e5b05..0b7dc2c 100644 --- a/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx +++ b/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx @@ -11,19 +11,13 @@ const StyledRollingPaperMessagesGrid = styled.div` grid-template-columns: repeat(3, 1fr); column-gap: 24px; row-gap: 28px; - margin: 0 auto; - width: 1200px; - padding: 112px 0 246px; @media (max-width: 1248px) { - width: 100%; - padding: 93px 24px 91px; grid-template-columns: repeat(2, 1fr); gap: 16px; } ${media.mobile} { - padding: 24px 20px 38px; grid-template-columns: repeat(1, 1fr); } `; diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx index 6dc99f3..4d4e7b3 100644 --- a/src/pages/messages-page.jsx +++ b/src/pages/messages-page.jsx @@ -1,10 +1,14 @@ import { useEffect, useState } from "react"; +import { useLocation, useNavigate } from "react-router"; import styled from "styled-components"; +import { PrimaryButton } from "../components/button/button"; +import BUTTON_SIZE from "../components/button/button-size"; import { getRecipient } from "../features/rolling-paper/api/recipients"; import RollingPaperHeader from "../features/rolling-paper/components/header/rolling-paper-header"; import RollingPaperMessagesGrid from "../features/rolling-paper/components/messages/rolling-paper-messages-grid"; import { useMedia } from "../hooks/use-media"; import ContentLayout from "../layouts/content-layout"; +import { media } from "../utils/media"; const backgroundStyle = ({ $backgroundImageUrl, $backgroundColor }) => { if (!$backgroundImageUrl) { @@ -20,11 +24,50 @@ const backgroundStyle = ({ $backgroundImageUrl, $backgroundColor }) => { const Content = styled.div` ${backgroundStyle}; height: calc(100% - 68px); + + & > div { + display: flex; + flex-direction: column; + gap: 12px; + width: 1200px; + margin: 0 auto; + padding: 112px 0 246px; + + @media (max-width: 1248px) { + width: 100%; + padding: 93px 24px 91px; + } + + ${media.mobile} { + padding: 24px 20px 38px; + } + } +`; + +const StyledEditButton = styled(PrimaryButton)` + align-self: flex-end; `; +function EditButton({ isEditing }) { + const navigate = useNavigate(); + + const handleEditClick = () => { + navigate(isEditing ? -1 : "edit"); + }; + + return ( + + ); +} + function MessagesPage() { const { isMobile } = useMedia(); const [recipient, setRecipient] = useState(); + const location = useLocation(); useEffect(() => { getRecipient().then(setRecipient); @@ -44,7 +87,10 @@ function MessagesPage() { $backgroundImageUrl={recipient.backgroundImageURL} $backgroundColor={recipient.backgroundColor} > - +
+ + +
)} From c6f9eaaa1b651590f662094298b2f5852b77e890 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Wed, 20 Aug 2025 20:13:58 +0900 Subject: [PATCH 198/253] =?UTF-8?q?refactor=20[#35]=20Style=20=EC=97=86?= =?UTF-8?q?=EB=8A=94=20div=EB=A5=BC=20styled-components=EB=A1=9C=20?= =?UTF-8?q?=EB=A7=8C=EB=93=A0=20component=EB=A1=9C=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/message/components/message-card-detail.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/features/message/components/message-card-detail.jsx b/src/features/message/components/message-card-detail.jsx index 8d4c628..5eba950 100644 --- a/src/features/message/components/message-card-detail.jsx +++ b/src/features/message/components/message-card-detail.jsx @@ -45,7 +45,7 @@ const StyledMessageCardDetail = styled.div``; function MessageCardDetail({ message }) { return ( -
+
{formatDate(message.createdAt, ".")}
{message.content} -
+ ); } From 57911db9c1923dbddbef0249741a81d8a557915b Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Wed, 20 Aug 2025 20:56:08 +0900 Subject: [PATCH 199/253] =?UTF-8?q?feat=20[#35]=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EC=A4=91=20MessageCard=EC=97=90=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=20=ED=91=9C=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/ic-trash.svg | 3 +++ src/features/message/components/message-card.jsx | 15 ++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 src/assets/ic-trash.svg diff --git a/src/assets/ic-trash.svg b/src/assets/ic-trash.svg new file mode 100644 index 0000000..3735eb8 --- /dev/null +++ b/src/assets/ic-trash.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/features/message/components/message-card.jsx b/src/features/message/components/message-card.jsx index 221786e..bd22f08 100644 --- a/src/features/message/components/message-card.jsx +++ b/src/features/message/components/message-card.jsx @@ -1,4 +1,7 @@ import styled from "styled-components"; +import deleteImage from "../../../assets/ic-trash.svg"; +import { OutlinedButton } from "../../../components/button/button"; +import BUTTON_SIZE from "../../../components/button/button-size"; import Colors from "../../../components/color/colors"; import { formatDate } from "../../../utils/formatter"; import { media } from "../../../utils/media"; @@ -7,6 +10,9 @@ import MessageSender from "./message-sender"; const Header = styled.header` padding-bottom: 16px; border-bottom: 1px solid ${Colors.gray(200)}; + display: flex; + justify-content: space-between; + align-items: center; `; const Content = styled.div` @@ -46,7 +52,7 @@ const StyledMessageCard = styled.article` box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08); `; -function MessageCard({ message }) { +function MessageCard({ isEditing, message, onDelete }) { return (
@@ -54,6 +60,13 @@ function MessageCard({ message }) { profileImage={message.profileImage} name={message.sender} /> + {isEditing && ( + + )}
{message.content} {formatDate(message.createdAt, ".")} From fe5d07c97d6b3d8415183cd4b8c168263965999f Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Wed, 20 Aug 2025 20:56:46 +0900 Subject: [PATCH 200/253] =?UTF-8?q?feat=20[#35]=20=EC=88=98=EC=A0=95,=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C,=20=EC=B7=A8=EC=86=8C=20=EB=B2=84=ED=8A=BC?= =?UTF-8?q?=EC=9D=84=20=EC=B6=94=EA=B0=80=ED=95=98=EA=B3=A0=20navigation?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 실제 삭제 기능은 API 연동 후 개발 예정입니다. --- .../messages/rolling-paper-messages-grid.jsx | 33 +++++--- src/pages/messages-page.jsx | 83 +++++++++++++++---- 2 files changed, 90 insertions(+), 26 deletions(-) diff --git a/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx b/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx index 0b7dc2c..a695359 100644 --- a/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx +++ b/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx @@ -22,7 +22,7 @@ const StyledRollingPaperMessagesGrid = styled.div` } `; -function RollingPaperMessagesGrid({ messages }) { +function RollingPaperMessagesGrid({ isEditing, messages, onDelete }) { const navigate = useNavigate(); const { id } = useParams(); @@ -30,18 +30,31 @@ function RollingPaperMessagesGrid({ messages }) { navigate(`/post/${id}/message`); }; + const handleDeleteClick = (messageId) => { + onDelete(messageId); + }; + + const messageCard = (message) => ( + handleDeleteClick(event, message.id)} + /> + ); + return ( - {messages.map((message) => ( - } - > - - - ))} + {messages.map((message) => + isEditing ? ( + messageCard(message) + ) : ( + + + + ) + )} ); } diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx index 4d4e7b3..015c703 100644 --- a/src/pages/messages-page.jsx +++ b/src/pages/messages-page.jsx @@ -1,7 +1,7 @@ -import { useEffect, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import { useLocation, useNavigate } from "react-router"; import styled from "styled-components"; -import { PrimaryButton } from "../components/button/button"; +import { OutlinedButton, PrimaryButton } from "../components/button/button"; import BUTTON_SIZE from "../components/button/button-size"; import { getRecipient } from "../features/rolling-paper/api/recipients"; import RollingPaperHeader from "../features/rolling-paper/components/header/rolling-paper-header"; @@ -44,23 +44,38 @@ const Content = styled.div` } `; -const StyledEditButton = styled(PrimaryButton)` +const ButtonContainer = styled.div` align-self: flex-end; + display: flex; + gap: 16px; `; -function EditButton({ isEditing }) { - const navigate = useNavigate(); - - const handleEditClick = () => { - navigate(isEditing ? -1 : "edit"); - }; +function ViewerButtons({ onEdit }) { + return ( + + + + ); +} +function EditingButtons({ onDelete, onCancel }) { return ( - + + + + ); } @@ -68,6 +83,31 @@ function MessagesPage() { const { isMobile } = useMedia(); const [recipient, setRecipient] = useState(); const location = useLocation(); + const navigate = useNavigate(); + + const isEditing = useMemo( + () => location.pathname.includes("edit"), + [location] + ); + + const handleEditClick = () => { + navigate("edit"); + }; + + const handleRollingPaperDelete = () => { + // TODO: Rolling Paper 삭제 + console.log(`Delete Rolling Paper ${recipient.id}`); + navigate(-1); + }; + + const handleEditCancel = () => { + navigate(-1); + }; + + const handleMessageDelete = (messageId) => { + // TODO: Message 삭제 + console.log(`Delete Message ${messageId}`); + }; useEffect(() => { getRecipient().then(setRecipient); @@ -88,8 +128,19 @@ function MessagesPage() { $backgroundColor={recipient.backgroundColor} >
- - + {isEditing ? ( + + ) : ( + + )} +
From e3911692045acab379a77b29f4fc7b97f22d7a35 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 21 Aug 2025 08:44:06 +0900 Subject: [PATCH 201/253] =?UTF-8?q?feat=20[#51]=20Edit=20mode=EC=97=90?= =?UTF-8?q?=EC=84=9C=20reaction=20=EC=B6=94=EA=B0=80=20=EB=B2=84=ED=8A=BC?= =?UTF-8?q?=20=EC=88=A8=EA=B9=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../header/rolling-paper-header.jsx | 29 ++++++++++--------- src/pages/messages-page.jsx | 1 + 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/src/features/rolling-paper/components/header/rolling-paper-header.jsx b/src/features/rolling-paper/components/header/rolling-paper-header.jsx index 5c86ecd..e88d131 100644 --- a/src/features/rolling-paper/components/header/rolling-paper-header.jsx +++ b/src/features/rolling-paper/components/header/rolling-paper-header.jsx @@ -108,6 +108,7 @@ const StyledRollingPaperHeader = styled.div` `; function RollingPaperHeader({ + isEditing, recipientId, recipientName, messages, @@ -148,19 +149,21 @@ function RollingPaperHeader({ - - } - > - - + {isEditing || ( + + } + > + + + )} Date: Thu, 21 Aug 2025 15:24:39 +0900 Subject: [PATCH 202/253] =?UTF-8?q?feat=20[#52]=20API=20=ED=98=B8=EC=B6=9C?= =?UTF-8?q?=20=EC=8B=9C=20=EC=82=AC=EC=9A=A9=ED=95=A0=20client=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/axios-instance.js | 9 --------- src/api/client.js | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 9 deletions(-) delete mode 100644 src/api/axios-instance.js create mode 100644 src/api/client.js diff --git a/src/api/axios-instance.js b/src/api/axios-instance.js deleted file mode 100644 index 217889d..0000000 --- a/src/api/axios-instance.js +++ /dev/null @@ -1,9 +0,0 @@ -import axios from "axios"; - -const axiosInstance = axios.create({ - baseURL: "https://rolling-api.vercel.app/", - timeout: 5000, - headers: { "Content-Type": "application/json" }, -}); - -export default axiosInstance; diff --git a/src/api/client.js b/src/api/client.js new file mode 100644 index 0000000..896de2d --- /dev/null +++ b/src/api/client.js @@ -0,0 +1,15 @@ +import axios from "axios"; + +const timeout = 5000; + +const baseClient = axios.create({ + baseURL: import.meta.env.VITE_API_BASE_URL, + timeout, +}); + +const apiClient = axios.create({ + baseURL: `${import.meta.env.VITE_API_BASE_URL}/18-3`, + timeout, +}); + +export { apiClient, baseClient }; From 72d7752e5136837cef5df8902dbee2eb471ef9ff Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 21 Aug 2025 17:25:12 +0900 Subject: [PATCH 203/253] =?UTF-8?q?feat=20[#52]=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EB=8D=B0=EC=9D=B4=ED=84=B0=EB=A5=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80/=EC=9D=BD=EA=B8=B0/=EC=82=AD=EC=A0=9C=ED=95=98?= =?UTF-8?q?=EA=B8=B0=20=EC=9C=84=ED=95=9C=20API=20=EB=AA=A8=EB=93=88=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/tests/test-api.js | 77 ++++++++++++++++ src/tests/test-message-body.json | 142 +++++++++++++++++++++++++++++ src/tests/test-reaction-body.json | 42 +++++++++ src/tests/test-recipient-body.json | 90 ++++++++++++++++++ 4 files changed, 351 insertions(+) create mode 100644 src/tests/test-api.js create mode 100644 src/tests/test-message-body.json create mode 100644 src/tests/test-reaction-body.json create mode 100644 src/tests/test-recipient-body.json diff --git a/src/tests/test-api.js b/src/tests/test-api.js new file mode 100644 index 0000000..a7a98a0 --- /dev/null +++ b/src/tests/test-api.js @@ -0,0 +1,77 @@ +import { apiClient } from "../api/client"; +import messageBody from "./test-message-body.json"; +import reactionBody from "./test-reaction-body.json"; +import recipientBody from "./test-recipient-body.json"; + +/* Recipients */ + +export async function createRecipients() { + let promises = []; + for (const body of recipientBody) { + const promise = apiClient.post("recipients/", body); + promises.push(promise); + } + await Promise.all(promises); +} + +export async function getAllRecipients() { + const response = await apiClient.get("/recipients/?limit=20"); + return response.data.results; +} + +export async function deleteAllRecipients(recipients) { + let promises = []; + for (const recipient of recipients) { + const promise = apiClient.delete(`recipients/${recipient.id}/`); + promises.push(promise); + } + await Promise.all(promises); +} + +/* Messages */ + +export async function createMessages({ recipientId }) { + let promises = []; + for (const body of messageBody) { + const promise = apiClient.post(`recipients/${recipientId}/messages/`, body); + promises.push(promise); + } + await Promise.all(promises); +} + +export async function getAllMessages({ recipientId }) { + const response = await apiClient.get( + `/recipients/${recipientId}/messages/?limit=20` + ); + return response.data.results; +} + +export async function deleteAllMessages(messages) { + let promises = []; + for (const message of messages) { + const promise = apiClient.delete(`messages/${message.id}/`); + promises.push(promise); + } + await Promise.all(promises); +} + +/* Reactions */ + +export async function createReactions({ recipientId }) { + let promises = []; + for (const body of reactionBody) { + const promise = apiClient.post( + `recipients/${recipientId}/reactions/`, + body + ); + promises.push(promise); + } + await Promise.all(promises); +} + +export async function getAllReactions({ recipientId }) { + const response = await apiClient.get( + `/recipients/${recipientId}/reactions/?limit=10` + ); + return response.data.results; +} diff --git a/src/tests/test-message-body.json b/src/tests/test-message-body.json new file mode 100644 index 0000000..e7844f4 --- /dev/null +++ b/src/tests/test-message-body.json @@ -0,0 +1,142 @@ +[ + { + "sender": "이혜진", + "profileImageURL": "https://picsum.photos/id/522/100/100", + "relationship": "친구", + "content": "축하해! 항상 밝은 모습이 너무 보기 좋아. 올해도 건강하고 행복한 일만 가득하길 바라~", + "font": "Pretendard" + }, + { + "sender": "박성민", + "profileImageURL": "https://picsum.photos/id/547/100/100", + "relationship": "동료", + "content": "정말 축하드립니다! 함께 일하면서 많이 배우고 있어요. 앞으로도 잘 부탁드려요!", + "font": "Noto Sans" + }, + { + "sender": "김소영", + "profileImageURL": "https://picsum.photos/id/268/100/100", + "relationship": "가족", + "content": "축하해♡ 엄마가 항상 응원하고 있다는 거 알지? 사랑해!", + "font": "나눔손글씨 손편지체" + }, + { + "sender": "최준영", + "profileImageURL": "https://picsum.photos/id/1082/100/100", + "relationship": "친구", + "content": "축하한다! 오늘 저녁에 맛있는 거 먹으러 가자. 내가 쏠게!", + "font": "Pretendard" + }, + { + "sender": "정은지", + "profileImageURL": "https://picsum.photos/id/571/100/100", + "relationship": "지인", + "content": "축하해요! 늘 웃는 모습이 인상적이에요. 좋은 하루 보내세요~", + "font": "나눔명조" + }, + { + "sender": "장현석", + "profileImageURL": "https://picsum.photos/id/494/100/100", + "relationship": "친구", + "content": "축하해! 시간 진짜 빠르다. 오늘 하루 특별하게 보내!", + "font": "Pretendard" + }, + { + "sender": "윤서현", + "profileImageURL": "https://picsum.photos/id/859/100/100", + "relationship": "동료", + "content": "축하드려요! 덕분에 프로젝트가 잘 진행되고 있어요. 감사합니다!", + "font": "Noto Sans" + }, + { + "sender": "김태호", + "profileImageURL": "https://picsum.photos/id/437/100/100", + "relationship": "친구", + "content": "축하해! 정말 수고 많았어. 이제 새로운 시작이네!", + "font": "나눔명조" + }, + { + "sender": "박미영", + "profileImageURL": "https://picsum.photos/id/1064/100/100", + "relationship": "친구", + "content": "드디어구나~ 그동안 정말 열심히 했어. 앞으로도 화이팅!", + "font": "나눔손글씨 손편지체" + }, + { + "sender": "이준수", + "profileImageURL": "https://learn-codeit-kr-static.s3.ap-northeast-2.amazonaws.com/sprint-proj-image/default_avatar.png", + "relationship": "지인", + "content": "축하드려요! 앞으로의 새로운 도전을 응원합니다.", + "font": "나눔명조" + }, + { + "sender": "최유나", + "profileImageURL": "https://picsum.photos/id/522/100/100", + "relationship": "친구", + "content": "축하해♡ 우리 추억 정말 많았는데 이제 또 새로운 추억 만들어가자!", + "font": "Pretendard" + }, + { + "sender": "강민호", + "profileImageURL": "https://picsum.photos/id/547/100/100", + "relationship": "동료", + "content": "축하합니다! 함께 활동했던 시간이 좋은 추억이에요.", + "font": "Noto Sans" + }, + { + "sender": "홍서윤", + "profileImageURL": "https://picsum.photos/id/268/100/100", + "relationship": "가족", + "content": "축하해! 언니가 너무 자랑스러워. 앞으로 하고 싶은 일 다 해봐!", + "font": "나눔손글씨 손편지체" + }, + { + "sender": "노진우", + "profileImageURL": "https://picsum.photos/id/1082/100/100", + "relationship": "친구", + "content": "축하해! 새로운 변화가 기대되네. 응원할게!", + "font": "Pretendard" + }, + { + "sender": "임소은", + "profileImageURL": "https://picsum.photos/id/571/100/100", + "relationship": "친구", + "content": "정말 축하해! 그동안 고생 많았어. 이제 좋은 일만 있을 거야!", + "font": "나눔명조" + }, + { + "sender": "조민석", + "profileImageURL": "https://picsum.photos/id/494/100/100", + "relationship": "지인", + "content": "축하드려요! 앞으로의 여정을 응원합니다.", + "font": "Noto Sans" + }, + { + "sender": "김다은", + "profileImageURL": "https://picsum.photos/id/859/100/100", + "relationship": "친구", + "content": "축하해! 정말 열심히 하더니 결실을 맺었네. 너무 축하해!", + "font": "Pretendard" + }, + { + "sender": "이현우", + "profileImageURL": "https://picsum.photos/id/437/100/100", + "relationship": "동료", + "content": "축하드립니다! 앞으로도 많이 배우고 싶어요.", + "font": "Noto Sans" + }, + { + "sender": "박지민", + "profileImageURL": "https://picsum.photos/id/1064/100/100", + "relationship": "가족", + "content": "축하해! 아빠가 정말 자랑스럽다. 건강 조심하고 화이팅!", + "font": "나눔명조" + }, + { + "sender": "정수빈", + "profileImageURL": "https://learn-codeit-kr-static.s3.ap-northeast-2.amazonaws.com/sprint-proj-image/default_avatar.png", + "relationship": "친구", + "content": "축하축하~ 이제 더 바빠지겠네. 건강 챙기면서 해!", + "font": "Pretendard" + } +] diff --git a/src/tests/test-reaction-body.json b/src/tests/test-reaction-body.json new file mode 100644 index 0000000..5018692 --- /dev/null +++ b/src/tests/test-reaction-body.json @@ -0,0 +1,42 @@ +[ + { + "emoji": "👏", + "type": "increase" + }, + { + "emoji": "🎉", + "type": "increase" + }, + { + "emoji": "❤️", + "type": "increase" + }, + { + "emoji": "👍", + "type": "increase" + }, + { + "emoji": "🔥", + "type": "increase" + }, + { + "emoji": "😊", + "type": "increase" + }, + { + "emoji": "💪", + "type": "increase" + }, + { + "emoji": "🎊", + "type": "increase" + }, + { + "emoji": "✨", + "type": "increase" + }, + { + "emoji": "🙌", + "type": "increase" + } +] diff --git a/src/tests/test-recipient-body.json b/src/tests/test-recipient-body.json new file mode 100644 index 0000000..83520d8 --- /dev/null +++ b/src/tests/test-recipient-body.json @@ -0,0 +1,90 @@ +[ + { + "name": "김민수", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/id/683/3840/2160" + }, + { + "name": "이지영", + "backgroundColor": "purple" + }, + { + "name": "박준호", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/id/24/3840/2160" + }, + { + "name": "최서연", + "backgroundColor": "green" + }, + { + "name": "정태윤", + "backgroundColor": "beige" + }, + { + "name": "한소희", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/id/599/3840/2160" + }, + { + "name": "임재현", + "backgroundColor": "blue" + }, + { + "name": "송유진", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/id/1058/3840/2160" + }, + { + "name": "강동훈", + "backgroundColor": "beige" + }, + { + "name": "윤미래", + "backgroundColor": "purple" + }, + { + "name": "조현우", + "backgroundColor": "blue", + "backgroundImageURL": "https://picsum.photos/id/683/3840/2160" + }, + { + "name": "배수지", + "backgroundColor": "green" + }, + { + "name": "신예린", + "backgroundColor": "beige" + }, + { + "name": "오준석", + "backgroundColor": "purple", + "backgroundImageURL": "https://picsum.photos/id/24/3840/2160" + }, + { + "name": "안채원", + "backgroundColor": "blue" + }, + { + "name": "문지훈", + "backgroundColor": "green" + }, + { + "name": "서다은", + "backgroundColor": "beige", + "backgroundImageURL": "https://picsum.photos/id/599/3840/2160" + }, + { + "name": "황민규", + "backgroundColor": "purple" + }, + { + "name": "김나영", + "backgroundColor": "blue" + }, + { + "name": "이도현", + "backgroundColor": "green", + "backgroundImageURL": "https://picsum.photos/id/1058/3840/2160" + } +] From d2b15c0ddb6a49b647584b48192db22b142aeaed Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 21 Aug 2025 17:25:41 +0900 Subject: [PATCH 204/253] =?UTF-8?q?feat=20[#52]=20`test-api`=20path?= =?UTF-8?q?=EC=97=90=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=EA=B4=80=EB=A6=AC=EC=9A=A9=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.jsx | 2 + src/tests/test-api-page.jsx | 294 ++++++++++++++++++++++++++++++++++++ 2 files changed, 296 insertions(+) create mode 100644 src/tests/test-api-page.jsx diff --git a/src/app.jsx b/src/app.jsx index a13aac0..ddb2624 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -8,6 +8,7 @@ import MessagePage from "./pages/message-list"; import MessagesPage from "./pages/messages-page"; import SendMessagePage from "./pages/send-message-page"; import TestPage from "./pages/test-page"; +import TestApiPage from "./tests/test-api-page"; function Provider({ children }) { return {children}; @@ -57,6 +58,7 @@ function App() { } /> + } /> } /> diff --git a/src/tests/test-api-page.jsx b/src/tests/test-api-page.jsx new file mode 100644 index 0000000..d2c5cf9 --- /dev/null +++ b/src/tests/test-api-page.jsx @@ -0,0 +1,294 @@ +import { useCallback, useEffect, useState } from "react"; +import styled from "styled-components"; +import { PrimaryButton } from "../components/button/button"; +import BUTTON_SIZE from "../components/button/button-size"; +import Colors from "../components/color/colors"; +import { + createMessages, + createReactions, + createRecipients, + deleteAllMessages, + deleteAllRecipients, + getAllMessages, + getAllReactions, + getAllRecipients, +} from "./test-api"; + +const Page = styled.div` + margin: 24px; +`; + +const Row = styled.div` + display: flex; + gap: 16px; +`; + +const Column = styled.div` + display: flex; + flex-direction: column; + gap: 12px; +`; + +const Table = styled.table` + border: 1px solid black; + border-collapse: collapse; + text-align: center; +`; + +const TableHeader = styled.thead` + font-weight: 700; + background-color: ${Colors.gray(100)}; +`; + +const TableRow = styled.tr``; + +const TableBody = styled.tbody` + & > tr:hover { + cursor: pointer; + background-color: ${Colors.gray(100)}; + } +`; + +const TableData = styled.td` + border: 1px solid black; + border-collapse: collapse; + padding: 4px 12px; +`; + +function RecipientsTable({ recipients, onClick }) { + return ( + + + + id + name + backgroundColor + backgroundImageURL + messageCount + reactionCount + createdAt + + + + {recipients.map((recipient) => ( + onClick(recipient) : undefined} + > + {recipient.id} + {recipient.name} + {recipient.backgroundColor} + {recipient.backgroundImageURL} + {recipient.messageCount} + {recipient.reactionCount} + {recipient.createdAt} + + ))} + +
+ ); +} + +function MessagesTable({ messages }) { + return ( + + + + id + recipientId + sender + profileImageURL + relationship + content + font + createdAt + + + + {messages.map((message) => ( + + {message.id} + {message.recipientId} + {message.sender} + {message.profileImageURL} + {message.relationship} + {message.content} + {message.font} + {message.createdAt} + + ))} + +
+ ); +} + +function ReactionsTable({ reactions }) { + return ( + + + + id + emoji + count + + + + {reactions.map((reaction) => ( + + {reaction.id} + {reaction.emoji} + {reaction.count} + + ))} + +
+ ); +} + +function TestApiPage() { + const [recipients, setRecipients] = useState([]); + const [messages, setMessages] = useState([]); + const [reactions, setReactions] = useState([]); + const [selectedRecipient, setSelectedRecipient] = useState(null); + + const buttonSize = BUTTON_SIZE.medium; + + const updateRecipients = useCallback(async () => { + const recipients = await getAllRecipients(); + setRecipients(recipients); + }, []); + + /* Recipients */ + + const handleCreateRecipientsClick = async () => { + await createRecipients(); + updateRecipients(); + }; + + const handleDeleteRecipientsClick = async () => { + await deleteAllRecipients(recipients); + setRecipients([]); + setMessages([]); + setReactions([]); + setSelectedRecipient(null); + }; + + const handleRecipientClick = async (recipient) => { + setSelectedRecipient(recipient); + + const messages = await getAllMessages({ recipientId: recipient.id }); + setMessages(messages); + + const reactions = await getAllReactions({ recipientId: recipient.id }); + setReactions(reactions); + }; + + /* Messages */ + + const handleCreateMessagesClick = async () => { + const recipientId = prompt("추가할 recipient id", ""); + await createMessages({ recipientId }); + updateRecipients(); + }; + + const handleDeleteMessagesClick = async () => { + if (messages.length > 0) { + await deleteAllMessages(messages); + setMessages([]); + } else { + const recipientId = prompt("삭제할 recipient id", ""); + const messages = await getAllMessages({ recipientId }); + await deleteAllMessages(messages); + setMessages([]); + } + + updateRecipients(); + }; + + /* Reactions */ + + const handleCreateReactionsClick = async () => { + const recipientId = prompt("추가할 recipient id", ""); + await createReactions({ recipientId }); + + const reactions = await getAllReactions({ recipientId }); + setReactions(reactions); + + updateRecipients(); + }; + + useEffect(() => { + updateRecipients(); + }, [updateRecipients]); + + return ( + + + + + + + + + + + +

{`현재 생성된 롤링페이퍼 (${recipients.length}개)`}

+ {recipients.length > 0 && ( + + )} + {selectedRecipient && ( +

{`${selectedRecipient.name} 에게 달린 메시지 (${ + messages.length ?? 0 + }개)`}

+ )} + {messages.length > 0 && } + {selectedRecipient && ( +

{`${selectedRecipient.name} 에게 달린 리액션 (${ + reactions.length ?? 0 + }개)`}

+ )} + {reactions.length > 0 && } +
+
+ ); +} + +export default TestApiPage; From 1e509e5e46e9f8edd3fd35f8a4c2973e09ff1d6f Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 21 Aug 2025 17:26:49 +0900 Subject: [PATCH 205/253] =?UTF-8?q?refactor=20[#52]=20`test-components`=20?= =?UTF-8?q?path=EC=97=90=20=EB=8C=80=ED=95=9C=20page=20component=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EB=B0=8F=20=EC=9C=84=EC=B9=98=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.jsx | 4 ++-- src/{pages/test-page.jsx => tests/test-components-page.jsx} | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename src/{pages/test-page.jsx => tests/test-components-page.jsx} (99%) diff --git a/src/app.jsx b/src/app.jsx index ddb2624..2637ecf 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -7,8 +7,8 @@ import MainPage from "./pages/main-page"; import MessagePage from "./pages/message-list"; import MessagesPage from "./pages/messages-page"; import SendMessagePage from "./pages/send-message-page"; -import TestPage from "./pages/test-page"; import TestApiPage from "./tests/test-api-page"; +import TestComponentsPage from "./tests/test-components-page"; function Provider({ children }) { return {children}; @@ -57,7 +57,7 @@ function App() { />
- } /> + } /> } /> } /> diff --git a/src/pages/test-page.jsx b/src/tests/test-components-page.jsx similarity index 99% rename from src/pages/test-page.jsx rename to src/tests/test-components-page.jsx index c6849dd..0b72d2f 100644 --- a/src/pages/test-page.jsx +++ b/src/tests/test-components-page.jsx @@ -28,7 +28,7 @@ const OutlinedHeader = styled(Header)` border: 1px solid black; `; -function TestPage() { +function TestComponentsPage() { /* Dropdown type TextField */ const [option1, setOption1] = useState(); const [option2, setOption2] = useState(); @@ -251,4 +251,4 @@ function TestPage() { ); } -export default TestPage; +export default TestComponentsPage; From 6447a35e36bbd725695d198ab8b24b98f9d36031 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 21 Aug 2025 17:27:54 +0900 Subject: [PATCH 206/253] =?UTF-8?q?refactor=20[#52]=20API=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80=EC=97=90?= =?UTF-8?q?=EC=84=9C=20reaction=20=EC=83=9D=EC=84=B1=20=ED=9B=84,=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=EB=90=9C=20reaction=EC=9D=84=20=EB=B0=94?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=B4=EC=97=AC=EC=A3=BC=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EC=9D=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/tests/test-api-page.jsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/tests/test-api-page.jsx b/src/tests/test-api-page.jsx index d2c5cf9..1716a2b 100644 --- a/src/tests/test-api-page.jsx +++ b/src/tests/test-api-page.jsx @@ -210,10 +210,6 @@ function TestApiPage() { const handleCreateReactionsClick = async () => { const recipientId = prompt("추가할 recipient id", ""); await createReactions({ recipientId }); - - const reactions = await getAllReactions({ recipientId }); - setReactions(reactions); - updateRecipients(); }; From 93bfcf8fdf8da047bae4e9a07ecfccddd1628419 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 21 Aug 2025 17:37:04 +0900 Subject: [PATCH 207/253] =?UTF-8?q?feat=20[#52]=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EB=A6=AC=EC=95=A1=EC=85=98=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=EB=A5=BC=2010=EA=B0=9C=EA=B9=8C=EC=A7=80=20=EB=9E=9C?= =?UTF-8?q?=EB=8D=A4=ED=95=98=EA=B2=8C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/tests/test-api.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/tests/test-api.js b/src/tests/test-api.js index a7a98a0..fed2e5c 100644 --- a/src/tests/test-api.js +++ b/src/tests/test-api.js @@ -60,11 +60,14 @@ export async function deleteAllMessages(messages) { export async function createReactions({ recipientId }) { let promises = []; for (const body of reactionBody) { - const promise = apiClient.post( - `recipients/${recipientId}/reactions/`, - body - ); - promises.push(promise); + const randomCount = Math.ceil(Math.random() * 10); + Array.from({ length: randomCount }).forEach(() => { + const promise = apiClient.post( + `recipients/${recipientId}/reactions/`, + body + ); + promises.push(promise); + }); } await Promise.all(promises); } From 6c2f6f6594f0dc4978b480f59482a7fa1b533b4c Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 21 Aug 2025 17:37:33 +0900 Subject: [PATCH 208/253] =?UTF-8?q?feat=20[#52]=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20api=20page=EC=97=90=EC=84=9C=20recipient=20?= =?UTF-8?q?=EC=84=A0=ED=83=9D=ED=96=88=EC=9D=84=20=EB=95=8C=EB=8A=94=20?= =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80,=20=EB=A6=AC=EC=95=A1=EC=85=98=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=ED=9B=84=20=EA=B3=A7=EB=B0=94=EB=A1=9C=20?= =?UTF-8?q?=EA=B0=B1=EC=8B=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/tests/test-api-page.jsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/tests/test-api-page.jsx b/src/tests/test-api-page.jsx index 1716a2b..2ed9272 100644 --- a/src/tests/test-api-page.jsx +++ b/src/tests/test-api-page.jsx @@ -189,6 +189,11 @@ function TestApiPage() { const recipientId = prompt("추가할 recipient id", ""); await createMessages({ recipientId }); updateRecipients(); + + if (selectedRecipient) { + const messages = await getAllMessages({ recipientId }); + setMessages(messages); + } }; const handleDeleteMessagesClick = async () => { @@ -211,6 +216,11 @@ function TestApiPage() { const recipientId = prompt("추가할 recipient id", ""); await createReactions({ recipientId }); updateRecipients(); + + if (selectedRecipient) { + const reactions = await getAllReactions({ recipientId }); + setReactions(reactions); + } }; useEffect(() => { From 9a728f062f24d91ff585fc56308dfd4cd4d1bbde Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 21 Aug 2025 19:09:27 +0900 Subject: [PATCH 209/253] =?UTF-8?q?fix=20[]=20error=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/message-list.jsx | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/pages/message-list.jsx b/src/pages/message-list.jsx index 1635722..7f05696 100644 --- a/src/pages/message-list.jsx +++ b/src/pages/message-list.jsx @@ -1,15 +1,9 @@ import ArrowButton from "../components/button/arrow-button"; import ARROW_BUTTON_DIRECTION from "../components/button/arrow-button-direction"; -import { - OutlinedButton, - PrimaryButton, - SecondaryButton, -} from "../components/button/button"; +import { PrimaryButton } from "../components/button/button"; import BUTTON_SIZE from "../components/button/button-size"; -import ToggleButton from "../components/button/toggle-button"; -import React, { useEffect, useState } from "react"; -import axiosInstance from "../api/axios-instance"; +import { useEffect, useState } from "react"; import styled from "styled-components"; /* styled components */ From 42d3a19e5e51f4157c2c0b244dbf48118dbf478f Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 21 Aug 2025 23:47:13 +0900 Subject: [PATCH 210/253] =?UTF-8?q?refactor=20[]=20Count=20=EC=83=81?= =?UTF-8?q?=EC=9C=84=20top=203=EC=9D=98=20reaction=EC=9D=84=20=EB=B3=B4?= =?UTF-8?q?=EC=97=AC=EC=A3=BC=EB=8A=94=20component=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/top-reactions-layout.js | 6 +++++ .../reaction/components/top-reactions.jsx | 25 +++++++++++++++++++ .../header/rolling-paper-reactions.jsx | 12 ++------- 3 files changed, 33 insertions(+), 10 deletions(-) create mode 100644 src/features/reaction/components/top-reactions-layout.js create mode 100644 src/features/reaction/components/top-reactions.jsx diff --git a/src/features/reaction/components/top-reactions-layout.js b/src/features/reaction/components/top-reactions-layout.js new file mode 100644 index 0000000..c95413b --- /dev/null +++ b/src/features/reaction/components/top-reactions-layout.js @@ -0,0 +1,6 @@ +const TOP_REACTIONS_LAYOUT = Object.freeze({ + normal: "normal", + compact: "compact", +}); + +export default TOP_REACTIONS_LAYOUT; diff --git a/src/features/reaction/components/top-reactions.jsx b/src/features/reaction/components/top-reactions.jsx new file mode 100644 index 0000000..594fc9f --- /dev/null +++ b/src/features/reaction/components/top-reactions.jsx @@ -0,0 +1,25 @@ +import styled from "styled-components"; +import EmojiBadge from "../../../components/badge/emoji-badge"; +import TOP_REACTIONS_LAYOUT from "./top-reactions-layout"; + +const gap = { + [TOP_REACTIONS_LAYOUT.normal]: "8px", + [TOP_REACTIONS_LAYOUT.compact]: "4px", +}; + +const StyledTopReactions = styled.div` + display: flex; + gap: ${({ $layout }) => gap[$layout]}; +`; + +function TopReactions({ reactions, layout = TOP_REACTIONS_LAYOUT.normal }) { + return ( + + {reactions.map(({ id, emoji, count }) => ( + + ))} + + ); +} + +export default TopReactions; diff --git a/src/features/rolling-paper/components/header/rolling-paper-reactions.jsx b/src/features/rolling-paper/components/header/rolling-paper-reactions.jsx index ec66dc8..87248a5 100644 --- a/src/features/rolling-paper/components/header/rolling-paper-reactions.jsx +++ b/src/features/rolling-paper/components/header/rolling-paper-reactions.jsx @@ -5,6 +5,7 @@ import Popover from "../../../../components/popover/popover"; import POPOVER_ALIGNMENT from "../../../../components/popover/popover-alignment"; import { useMedia } from "../../../../hooks/use-media"; import { media } from "../../../../utils/media"; +import TopReactions from "../../../reaction/components/top-reactions"; const MoreButton = styled.button` background: none; @@ -14,11 +15,6 @@ const MoreButton = styled.button` cursor: pointer; `; -const TopThreeReactions = styled.div` - display: flex; - gap: 8px; -`; - const AllReactions = styled.div` padding: 24px; display: grid; @@ -42,11 +38,7 @@ function RollingPaperReactions({ reactions }) { return ( - - {reactions.slice(0, 3).map(({ id, emoji, count }) => ( - - ))} - + Date: Thu, 21 Aug 2025 23:54:54 +0900 Subject: [PATCH 211/253] =?UTF-8?q?refactor=20[]=20Top=203=20reactions=20?= =?UTF-8?q?=EB=B0=8F=20popover=EB=A1=9C=20=EC=A0=84=EC=B2=B4=20reactions?= =?UTF-8?q?=EB=A5=BC=20=EB=B3=B4=EC=97=AC=EC=A3=BC=EB=8A=94=20component=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/all-reactions-popover.jsx | 53 ++++++++++++++++ .../components/received-reactions.jsx | 23 +++++++ .../header/rolling-paper-header.jsx | 4 +- .../header/rolling-paper-reactions.jsx | 61 ------------------- 4 files changed, 78 insertions(+), 63 deletions(-) create mode 100644 src/features/reaction/components/all-reactions-popover.jsx create mode 100644 src/features/reaction/components/received-reactions.jsx delete mode 100644 src/features/rolling-paper/components/header/rolling-paper-reactions.jsx diff --git a/src/features/reaction/components/all-reactions-popover.jsx b/src/features/reaction/components/all-reactions-popover.jsx new file mode 100644 index 0000000..cd8d3b4 --- /dev/null +++ b/src/features/reaction/components/all-reactions-popover.jsx @@ -0,0 +1,53 @@ +import styled from "styled-components"; +import arrowDownImage from "../../../assets/ic-chevron-down.svg"; +import EmojiBadge from "../../../components/badge/emoji-badge"; +import Popover from "../../../components/popover/popover"; +import POPOVER_ALIGNMENT from "../../../components/popover/popover-alignment"; +import { media } from "../../../utils/media"; + +const StyledPopoverAction = styled.button` + background: none; + border: none; + width: 36px; + height: 36px; + cursor: pointer; + padding: 0; +`; + +function PopoverAction() { + return ( + + 전체 리액션 보기 + + ); +} + +const StyledAllReactions = styled.div` + padding: 24px; + display: grid; + grid-template-columns: repeat(4, min-content); + row-gap: 10px; + column-gap: 8px; + + ${media.mobile} { + grid-template-columns: repeat(3, min-content); + } +`; + +function AllReactionsPopover({ reactions }) { + return ( + } + > + + {reactions.map(({ id, emoji, count }) => ( + + ))} + + + ); +} + +export default AllReactionsPopover; diff --git a/src/features/reaction/components/received-reactions.jsx b/src/features/reaction/components/received-reactions.jsx new file mode 100644 index 0000000..f529cf7 --- /dev/null +++ b/src/features/reaction/components/received-reactions.jsx @@ -0,0 +1,23 @@ +import styled from "styled-components"; +import { useMedia } from "../../../hooks/use-media"; +import AllReactionsPopover from "./all-reactions-popover"; +import TopReactions from "./top-reactions"; + +const StyledRollingPaperReactions = styled.div` + display: flex; + gap: 2px; + align-items: center; +`; + +function ReceivedReactions({ topReactions, reactions }) { + const { isMobile } = useMedia(); + + return ( + + + + + ); +} + +export default ReceivedReactions; diff --git a/src/features/rolling-paper/components/header/rolling-paper-header.jsx b/src/features/rolling-paper/components/header/rolling-paper-header.jsx index e88d131..1867884 100644 --- a/src/features/rolling-paper/components/header/rolling-paper-header.jsx +++ b/src/features/rolling-paper/components/header/rolling-paper-header.jsx @@ -12,7 +12,7 @@ import { useMedia } from "../../../../hooks/use-media"; import { useToast } from "../../../../hooks/use-toast"; import { shareRollingPaper } from "../../../../libs/kakao/kakao-service"; import { media } from "../../../../utils/media"; -import RollingPaperReactions from "./rolling-paper-reactions"; +import ReceivedReactions from "../../../reaction/components/received-reactions"; import RollingPaperSenders from "./rolling-paper-senders"; import RollingPaperSharePopover from "./rolling-paper-share-popover"; @@ -146,7 +146,7 @@ function RollingPaperHeader({ profiles={messages.map((message) => message.profileImageURL)} /> )} - +
{isEditing || ( diff --git a/src/features/rolling-paper/components/header/rolling-paper-reactions.jsx b/src/features/rolling-paper/components/header/rolling-paper-reactions.jsx deleted file mode 100644 index 87248a5..0000000 --- a/src/features/rolling-paper/components/header/rolling-paper-reactions.jsx +++ /dev/null @@ -1,61 +0,0 @@ -import styled from "styled-components"; -import arrowDownImage from "../../../../assets/ic-chevron-down.svg"; -import EmojiBadge from "../../../../components/badge/emoji-badge"; -import Popover from "../../../../components/popover/popover"; -import POPOVER_ALIGNMENT from "../../../../components/popover/popover-alignment"; -import { useMedia } from "../../../../hooks/use-media"; -import { media } from "../../../../utils/media"; -import TopReactions from "../../../reaction/components/top-reactions"; - -const MoreButton = styled.button` - background: none; - border: none; - width: 36px; - height: 36px; - cursor: pointer; -`; - -const AllReactions = styled.div` - padding: 24px; - display: grid; - grid-template-columns: repeat(4, min-content); - row-gap: 10px; - column-gap: 8px; - - ${media.mobile} { - grid-template-columns: repeat(3, min-content); - } -`; - -const StyledRollingPaperReactions = styled.div` - display: flex; - gap: 2px; - align-items: center; -`; - -function RollingPaperReactions({ reactions }) { - const { isMobile } = useMedia(); - - return ( - - - - 열기 버튼 - - } - > - - {reactions.slice(0, isMobile ? 6 : 8).map(({ id, emoji, count }) => ( - - ))} - - - - ); -} - -export default RollingPaperReactions; From eb63697098467c095735e257021a3c7feb5123b7 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Fri, 22 Aug 2025 08:43:41 +0900 Subject: [PATCH 212/253] =?UTF-8?q?refactor=20[]=20=EB=A6=AC=EC=95=A1?= =?UTF-8?q?=EC=85=98=20=EC=B6=94=EA=B0=80=20popover,=20`DividedContainer`?= =?UTF-8?q?=20component=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/add-reaction-popover.jsx | 41 +++++++ .../components/header/divided-container.jsx | 36 ++++++ .../header/rolling-paper-header.jsx | 103 ++++++------------ 3 files changed, 109 insertions(+), 71 deletions(-) create mode 100644 src/features/reaction/components/add-reaction-popover.jsx create mode 100644 src/features/rolling-paper/components/header/divided-container.jsx diff --git a/src/features/reaction/components/add-reaction-popover.jsx b/src/features/reaction/components/add-reaction-popover.jsx new file mode 100644 index 0000000..c880f35 --- /dev/null +++ b/src/features/reaction/components/add-reaction-popover.jsx @@ -0,0 +1,41 @@ +import EmojiPicker from "emoji-picker-react"; +import styled from "styled-components"; +import addImage from "../../../assets/ic-face-smile-add.svg"; +import { OutlinedButton } from "../../../components/button/button"; +import BUTTON_SIZE from "../../../components/button/button-size"; +import Popover from "../../../components/popover/popover"; +import POPOVER_ALIGNMENT from "../../../components/popover/popover-alignment"; +import { useMedia } from "../../../hooks/use-media"; +import { media } from "../../../utils/media"; + +const StyledPopoverAction = styled(OutlinedButton)` + ${media.mobile} { + padding: 0 8px; + } +`; + +function PopoverAction() { + const { isMobile } = useMedia(); + + return ( + + ); +} + +function AddReactionPopover() { + return ( + } + > + + + ); +} + +export default AddReactionPopover; diff --git a/src/features/rolling-paper/components/header/divided-container.jsx b/src/features/rolling-paper/components/header/divided-container.jsx new file mode 100644 index 0000000..88b3d08 --- /dev/null +++ b/src/features/rolling-paper/components/header/divided-container.jsx @@ -0,0 +1,36 @@ +import styled from "styled-components"; +import Colors from "../../../../components/color/colors"; +import { media } from "../../../../utils/media"; + +const gap = { + normal: "28px", + compact: "12px", +}; + +const Divider = styled.div` + width: 1px; + height: 28px; + background-color: ${Colors.gray(200)}; +`; + +const StyledDividedContainer = styled.div` + display: flex; + align-items: center; + gap: ${({ $layout }) => gap[$layout]}; + + ${media.mobile} { + gap: 16px; + } +`; + +function DividedContainer({ children, layout = "normal" }) { + return ( + + {children[0]} + {children[0] && } + {children[1]} + + ); +} + +export default DividedContainer; diff --git a/src/features/rolling-paper/components/header/rolling-paper-header.jsx b/src/features/rolling-paper/components/header/rolling-paper-header.jsx index 1867884..cf75490 100644 --- a/src/features/rolling-paper/components/header/rolling-paper-header.jsx +++ b/src/features/rolling-paper/components/header/rolling-paper-header.jsx @@ -1,6 +1,4 @@ -import EmojiPicker from "emoji-picker-react"; import styled from "styled-components"; -import addImage from "../../../../assets/ic-face-smile-add.svg"; import shareImage from "../../../../assets/ic-share.svg"; import { OutlinedButton } from "../../../../components/button/button"; import BUTTON_SIZE from "../../../../components/button/button-size"; @@ -12,7 +10,9 @@ import { useMedia } from "../../../../hooks/use-media"; import { useToast } from "../../../../hooks/use-toast"; import { shareRollingPaper } from "../../../../libs/kakao/kakao-service"; import { media } from "../../../../utils/media"; +import AddReactionPopover from "../../../reaction/components/add-reaction-popover"; import ReceivedReactions from "../../../reaction/components/received-reactions"; +import DividedContainer from "./divided-container"; import RollingPaperSenders from "./rolling-paper-senders"; import RollingPaperSharePopover from "./rolling-paper-share-popover"; @@ -29,53 +29,12 @@ const RecipientName = styled.h2` } `; -const Divider = styled.div` - width: 1px; - height: 28px; - background-color: ${Colors.gray(200)}; -`; - -const StyledDividedContainer = styled.div` - display: flex; - align-items: center; - gap: 28px; - - ${media.mobile} { - gap: 16px; - } -`; - -function DividedContainer({ children }) { - return ( - - {children[0]} - {children[0] && } - {children[1]} - - ); -} - const HeaderTrailing = styled.div` display: flex; gap: 8px; align-items: center; `; -const AddButton = styled(OutlinedButton)` - ${media.mobile} { - padding: 0 8px; - } -`; - -const ShareButton = styled(OutlinedButton)` - width: auto; - padding: 0 16px; - - ${media.mobile} { - padding: 0 8px; - } -`; - const RollingPaperHeaderContent = styled.div` width: 100%; max-width: 1200px; @@ -107,6 +66,30 @@ const StyledRollingPaperHeader = styled.div` } `; +const ShareButton = styled(OutlinedButton)` + width: auto; + padding: 0 16px; + + ${media.mobile} { + padding: 0 8px; + } +`; + +function SharePopover({ onShareKakao, onShareUrl }) { + return ( + } + > + + + ); +} + function RollingPaperHeader({ isEditing, recipientId, @@ -148,34 +131,12 @@ function RollingPaperHeader({ )} - - {isEditing || ( - - } - > - - - )} - - } - > - - + + {isEditing || } + From f25a5f05df646bfe482369f8c28d0a9da57440e2 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Fri, 22 Aug 2025 09:01:04 +0900 Subject: [PATCH 213/253] =?UTF-8?q?refactor=20[]=20=EA=B3=B5=EC=9C=A0=20po?= =?UTF-8?q?pover=EB=A5=BC=20component=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../header/rolling-paper-header.jsx | 32 +---------------- .../header/rolling-paper-share-popover.jsx | 35 ++++++++++++++++--- 2 files changed, 32 insertions(+), 35 deletions(-) diff --git a/src/features/rolling-paper/components/header/rolling-paper-header.jsx b/src/features/rolling-paper/components/header/rolling-paper-header.jsx index cf75490..71ed1f4 100644 --- a/src/features/rolling-paper/components/header/rolling-paper-header.jsx +++ b/src/features/rolling-paper/components/header/rolling-paper-header.jsx @@ -1,10 +1,5 @@ import styled from "styled-components"; -import shareImage from "../../../../assets/ic-share.svg"; -import { OutlinedButton } from "../../../../components/button/button"; -import BUTTON_SIZE from "../../../../components/button/button-size"; import Colors from "../../../../components/color/colors"; -import Popover from "../../../../components/popover/popover"; -import POPOVER_ALIGNMENT from "../../../../components/popover/popover-alignment"; import Toast from "../../../../components/toast/toast"; import { useMedia } from "../../../../hooks/use-media"; import { useToast } from "../../../../hooks/use-toast"; @@ -65,31 +60,6 @@ const StyledRollingPaperHeader = styled.div` align-items: flex-start; } `; - -const ShareButton = styled(OutlinedButton)` - width: auto; - padding: 0 16px; - - ${media.mobile} { - padding: 0 8px; - } -`; - -function SharePopover({ onShareKakao, onShareUrl }) { - return ( - } - > - - - ); -} - function RollingPaperHeader({ isEditing, recipientId, @@ -133,7 +103,7 @@ function RollingPaperHeader({ {isEditing || } - diff --git a/src/features/rolling-paper/components/header/rolling-paper-share-popover.jsx b/src/features/rolling-paper/components/header/rolling-paper-share-popover.jsx index 310479f..6163b61 100644 --- a/src/features/rolling-paper/components/header/rolling-paper-share-popover.jsx +++ b/src/features/rolling-paper/components/header/rolling-paper-share-popover.jsx @@ -1,5 +1,11 @@ import styled from "styled-components"; +import shareImage from "../../../../assets/ic-share.svg"; +import { OutlinedButton } from "../../../../components/button/button"; +import BUTTON_SIZE from "../../../../components/button/button-size"; import Colors from "../../../../components/color/colors"; +import Popover from "../../../../components/popover/popover"; +import POPOVER_ALIGNMENT from "../../../../components/popover/popover-alignment"; +import { media } from "../../../../utils/media"; const ShareOption = styled.li` padding: 12px 16px; @@ -14,7 +20,7 @@ const ShareOption = styled.li` } `; -const StyledRollingPaperSharePopover = styled.ul` +const ShareOptions = styled.ul` display: flex; flex-direction: column; padding: 10px 0; @@ -24,12 +30,33 @@ const StyledRollingPaperSharePopover = styled.ul` margin: 0; `; -function RollingPaperSharePopover({ onShareKakao, onShareUrl }) { +function PopoverContent({ onShareKakao, onShareUrl }) { return ( - + 카카오톡 공유 URL 공유 - + + ); +} + +const PopoverAction = styled(OutlinedButton)` + width: auto; + padding: 0 16px; + + ${media.mobile} { + padding: 0 8px; + } +`; + +function RollingPaperSharePopover({ onShareKakao, onShareUrl }) { + return ( + } + > + + ); } From 298352a57ddd6afa0428395ab1f7a40dcfbd42d8 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Fri, 22 Aug 2025 09:01:40 +0900 Subject: [PATCH 214/253] =?UTF-8?q?fix=20[]=20Popover=20=EC=98=A4=EB=A5=B8?= =?UTF-8?q?=EC=AA=BD=20=EC=A0=95=EB=A0=AC=20=EC=8B=9C=20=EC=9C=84=EC=B9=98?= =?UTF-8?q?=20=EC=98=A4=EC=B0=A8=20=EB=B3=B4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/use-popover.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hooks/use-popover.jsx b/src/hooks/use-popover.jsx index 1d775fb..ffe8ebb 100644 --- a/src/hooks/use-popover.jsx +++ b/src/hooks/use-popover.jsx @@ -16,7 +16,7 @@ function calculatePopoverPosition(target, alignment) { switch (alignment) { case POPOVER_ALIGNMENT.right: - position.right = window.innerWidth - targetRect.right; + position.right = window.innerWidth - targetRect.right - 16; // 오른쪽 정렬 시 -16px 보정 break; default: position.left = targetRect.left; From 95087a1877bc4f8dd00895f1cc4a60db66cc67a3 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 21 Aug 2025 19:30:55 +0900 Subject: [PATCH 215/253] =?UTF-8?q?feat=20[#52]=20=EB=A1=A4=EB=A7=81?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=ED=8D=BC=20=EC=A0=95=EB=B3=B4=EB=A5=BC=20?= =?UTF-8?q?=EA=B0=80=EC=A0=B8=EC=98=A4=EB=8A=94=20API=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/rolling-paper/api/recipients.js | 12 ++++++++---- src/pages/messages-page.jsx | 12 +++++++++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/features/rolling-paper/api/recipients.js b/src/features/rolling-paper/api/recipients.js index 1e0a566..42a8bcd 100644 --- a/src/features/rolling-paper/api/recipients.js +++ b/src/features/rolling-paper/api/recipients.js @@ -1,8 +1,12 @@ -import mockRecipient from "./mock-recipient.json"; +import { apiClient } from "../../../api/client"; -async function getRecipient() { - // NOTE: API를 연동하기 전에 mock data로 먼저 개발합니다. - return mockRecipient; +async function getRecipient({ id }) { + const response = await apiClient.get(`recipients/${id}/`); + if (response.status !== 200) { + throw new Error("Recipient data를 가져오는데 실패했습니다."); + } + + return response.data; } export { getRecipient }; diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx index c13abc0..5bbf41f 100644 --- a/src/pages/messages-page.jsx +++ b/src/pages/messages-page.jsx @@ -1,5 +1,5 @@ import { useEffect, useMemo, useState } from "react"; -import { useLocation, useNavigate } from "react-router"; +import { useLocation, useNavigate, useParams } from "react-router"; import styled from "styled-components"; import { OutlinedButton, PrimaryButton } from "../components/button/button"; import BUTTON_SIZE from "../components/button/button-size"; @@ -84,6 +84,7 @@ function MessagesPage() { const [recipient, setRecipient] = useState(); const location = useLocation(); const navigate = useNavigate(); + const { id } = useParams(); const isEditing = useMemo( () => location.pathname.includes("edit"), @@ -110,8 +111,13 @@ function MessagesPage() { }; useEffect(() => { - getRecipient().then(setRecipient); - }, []); + getRecipient({ id }) + .then(setRecipient) + .catch((error) => { + // TODO: Error 처리 필요 + console.error(error); + }); + }, [id]); const content = ( <> From 797d4bbd4c6b3fe4f7de557bef5db063a6568c75 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 21 Aug 2025 19:31:04 +0900 Subject: [PATCH 216/253] =?UTF-8?q?feat=20[#52]=20=EB=A1=A4=EB=A7=81?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=ED=8D=BC=20=EB=B0=B0=EA=B2=BD=20=EC=83=89?= =?UTF-8?q?=EC=83=81=EC=9D=84=20=EC=84=9C=EB=B2=84=EA=B0=80=20=EB=B0=98?= =?UTF-8?q?=ED=99=98=ED=95=98=EB=8A=94=20=EC=9D=91=EB=8B=B5=EC=9D=98=20col?= =?UTF-8?q?or=20token=EA=B3=BC=20=EC=9D=BC=EC=B9=98=ED=95=98=EB=8A=94=20ke?= =?UTF-8?q?y=EB=A1=9C=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/color/background-color.js | 10 ++++++++++ src/components/option/background-select.jsx | 13 +++++++------ src/pages/messages-page.jsx | 3 ++- 3 files changed, 19 insertions(+), 7 deletions(-) create mode 100644 src/components/color/background-color.js diff --git a/src/components/color/background-color.js b/src/components/color/background-color.js new file mode 100644 index 0000000..8c996ab --- /dev/null +++ b/src/components/color/background-color.js @@ -0,0 +1,10 @@ +import Colors from "./colors"; + +const BACKGROUND_COLOR = Object.freeze({ + beige: Colors.beige(200), + purple: Colors.purple(200), + blue: Colors.blue(200), + green: Colors.green(200), +}); + +export default BACKGROUND_COLOR; diff --git a/src/components/option/background-select.jsx b/src/components/option/background-select.jsx index cc6cb27..98db3cc 100644 --- a/src/components/option/background-select.jsx +++ b/src/components/option/background-select.jsx @@ -1,9 +1,10 @@ +import { useEffect, useState } from "react"; import styled from "styled-components"; -import Colors from "../color/colors"; import CheckImage from "../../assets/ic-check.svg"; -import { useEffect, useState } from "react"; import { OutlinedButton } from "../button/button"; import BUTTON_SIZE from "../button/button-size"; +import BACKGROUND_COLOR from "../color/background-color"; +import Colors from "../color/colors"; const BackgroundWrapper = styled.div` padding-top: 50px; @@ -44,10 +45,10 @@ function BackgroundSelect({ type, selected, onSelect }) { const [imageUrls, setImageUrls] = useState([]); const colorOptions = [ - { color: Colors.beige(200) }, - { color: Colors.purple(200) }, - { color: Colors.blue(200) }, - { color: Colors.green(200) }, + { color: BACKGROUND_COLOR.beige }, + { color: BACKGROUND_COLOR.purple }, + { color: BACKGROUND_COLOR.blue }, + { color: BACKGROUND_COLOR.green }, ]; /* useEffect(() => { diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx index 5bbf41f..6168975 100644 --- a/src/pages/messages-page.jsx +++ b/src/pages/messages-page.jsx @@ -3,6 +3,7 @@ import { useLocation, useNavigate, useParams } from "react-router"; import styled from "styled-components"; import { OutlinedButton, PrimaryButton } from "../components/button/button"; import BUTTON_SIZE from "../components/button/button-size"; +import BACKGROUND_COLOR from "../components/color/background-color"; import { getRecipient } from "../features/rolling-paper/api/recipients"; import RollingPaperHeader from "../features/rolling-paper/components/header/rolling-paper-header"; import RollingPaperMessagesGrid from "../features/rolling-paper/components/messages/rolling-paper-messages-grid"; @@ -132,7 +133,7 @@ function MessagesPage() { />
{isEditing ? ( From bc6dad200b6c6f4a658547fbe651559c004b01b4 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Fri, 22 Aug 2025 09:19:48 +0900 Subject: [PATCH 217/253] =?UTF-8?q?feat=20[#52]=20=EC=A0=84=EC=B2=B4=20mes?= =?UTF-8?q?sage=20=EB=AA=A9=EB=A1=9D=EC=9D=84=20=EA=B0=80=EC=A0=B8?= =?UTF-8?q?=EC=98=A4=EB=8A=94=20API=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/message/api/messages.js | 21 +++++++++++++++++++++ src/pages/messages-page.jsx | 23 +++++++++++++++++------ 2 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 src/features/message/api/messages.js diff --git a/src/features/message/api/messages.js b/src/features/message/api/messages.js new file mode 100644 index 0000000..c24d0a1 --- /dev/null +++ b/src/features/message/api/messages.js @@ -0,0 +1,21 @@ +import { apiClient } from "../../../api/client"; + +async function getMessages({ recipientId, limit, page = 1 }) { + const searchParams = new URLSearchParams(); + searchParams.append("page", page); + if (limit) { + searchParams.append("limit", limit); + } + + const response = await apiClient.get( + `recipients/${recipientId}/messages/?${searchParams.toString()}` + ); + if (response.status !== 200) { + throw new Error("Message data를 가져오는데 실패했습니다."); + } + + const data = response.data; + return data.results; +} + +export { getMessages }; diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx index 6168975..c29e5fd 100644 --- a/src/pages/messages-page.jsx +++ b/src/pages/messages-page.jsx @@ -4,6 +4,7 @@ import styled from "styled-components"; import { OutlinedButton, PrimaryButton } from "../components/button/button"; import BUTTON_SIZE from "../components/button/button-size"; import BACKGROUND_COLOR from "../components/color/background-color"; +import { getMessages } from "../features/message/api/messages"; import { getRecipient } from "../features/rolling-paper/api/recipients"; import RollingPaperHeader from "../features/rolling-paper/components/header/rolling-paper-header"; import RollingPaperMessagesGrid from "../features/rolling-paper/components/messages/rolling-paper-messages-grid"; @@ -83,6 +84,7 @@ function EditingButtons({ onDelete, onCancel }) { function MessagesPage() { const { isMobile } = useMedia(); const [recipient, setRecipient] = useState(); + const [messages, setMessages] = useState([]); const location = useLocation(); const navigate = useNavigate(); const { id } = useParams(); @@ -112,12 +114,21 @@ function MessagesPage() { }; useEffect(() => { - getRecipient({ id }) - .then(setRecipient) - .catch((error) => { + async function fetchRollingPaper() { + try { + const [recipient, messages] = await Promise.all([ + getRecipient({ id }), + getMessages({ recipientId: id }), + ]); + setRecipient(recipient); + setMessages(messages); + } catch (error) { // TODO: Error 처리 필요 console.error(error); - }); + } + } + + fetchRollingPaper(); }, [id]); const content = ( @@ -128,7 +139,7 @@ function MessagesPage() { isEditing={isEditing} recipientId={recipient.id} recipientName={recipient.name} - messages={recipient.recentMessages} + messages={messages} reactions={recipient.topReactions} />
From 77c2223c4fdf01760c6c2a5bdb9683438c2d4c87 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 21 Aug 2025 20:49:39 +0900 Subject: [PATCH 218/253] =?UTF-8?q?fix=20[#52]=20Message=20data=EC=97=90?= =?UTF-8?q?=20=EB=A7=9E=EB=8A=94=20profile=20image=20=EB=B0=8F=20=EA=B4=80?= =?UTF-8?q?=EA=B3=84=20=EB=B0=B0=EC=A7=80=EB=A5=BC=20=EB=B3=B4=EC=97=AC?= =?UTF-8?q?=EC=A3=BC=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/badge/badge-type.js | 8 ++++---- src/components/badge/badge.jsx | 17 +++++------------ .../message/components/message-card.jsx | 3 ++- .../message/components/message-sender.jsx | 6 +++--- src/tests/test-components-page.jsx | 8 ++++---- 5 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/components/badge/badge-type.js b/src/components/badge/badge-type.js index 6c9b086..c5580bd 100644 --- a/src/components/badge/badge-type.js +++ b/src/components/badge/badge-type.js @@ -1,8 +1,8 @@ const BADGE_TYPE = Object.freeze({ - acquaintance: "acquaintance", - coworker: "coworker", - family: "family", - friend: "friend", + 지인: "지인", + 동료: "동료", + 가족: "가족", + 친구: "친구", }); export default BADGE_TYPE; diff --git a/src/components/badge/badge.jsx b/src/components/badge/badge.jsx index 9bc69ef..a206aff 100644 --- a/src/components/badge/badge.jsx +++ b/src/components/badge/badge.jsx @@ -3,31 +3,24 @@ import Colors from "../color/colors"; import BADGE_TYPE from "./badge-type"; const styles = { - [BADGE_TYPE.acquaintance]: { + [BADGE_TYPE.지인]: { backgroundColor: Colors.beige(100), color: Colors.beige(500), }, - [BADGE_TYPE.coworker]: { + [BADGE_TYPE.동료]: { backgroundColor: Colors.purple(100), color: Colors.purple(600), }, - [BADGE_TYPE.family]: { + [BADGE_TYPE.가족]: { backgroundColor: Colors.green(100), color: Colors.green(500), }, - [BADGE_TYPE.friend]: { + [BADGE_TYPE.친구]: { backgroundColor: Colors.blue(100), color: Colors.blue(500), }, }; -const title = { - [BADGE_TYPE.acquaintance]: "지인", - [BADGE_TYPE.coworker]: "동료", - [BADGE_TYPE.family]: "가족", - [BADGE_TYPE.friend]: "친구", -}; - const StyledBadge = styled.div` background-color: ${({ $type }) => styles[$type].backgroundColor}; color: ${({ $type }) => styles[$type].color}; @@ -39,7 +32,7 @@ const StyledBadge = styled.div` `; function Badge({ type }) { - return {title[type]}; + return {type}; } export default Badge; diff --git a/src/features/message/components/message-card.jsx b/src/features/message/components/message-card.jsx index bd22f08..d20a7cd 100644 --- a/src/features/message/components/message-card.jsx +++ b/src/features/message/components/message-card.jsx @@ -57,7 +57,8 @@ function MessageCard({ isEditing, message, onDelete }) {
{isEditing && ( diff --git a/src/features/message/components/message-sender.jsx b/src/features/message/components/message-sender.jsx index d59d0ee..7ce9d28 100644 --- a/src/features/message/components/message-sender.jsx +++ b/src/features/message/components/message-sender.jsx @@ -42,11 +42,11 @@ const StyledMessageSender = styled.div` gap: 14px; `; -function MessageSender({ profileImage, name }) { +function MessageSender({ profileImageUrl, relationship, name }) { return ( - - + + ); } diff --git a/src/tests/test-components-page.jsx b/src/tests/test-components-page.jsx index 0b72d2f..7e3cbb7 100644 --- a/src/tests/test-components-page.jsx +++ b/src/tests/test-components-page.jsx @@ -128,10 +128,10 @@ function TestComponentsPage() {
- - - - + + + +
From 9a00e66ffe0b730ad137f91e02c75643b298da5b Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Thu, 21 Aug 2025 20:54:02 +0900 Subject: [PATCH 219/253] =?UTF-8?q?fix=20[#52]=20MessageCard=20modal?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=ED=94=84=EB=A1=9C=ED=95=84=20=EC=82=AC?= =?UTF-8?q?=EC=A7=84=20=EB=B0=8F=20=EA=B4=80=EA=B3=84=20=EB=B0=B0=EC=A7=80?= =?UTF-8?q?=EA=B0=80=20=EC=A0=95=EC=83=81=EC=A0=81=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=ED=91=9C=EC=8B=9C=EB=90=98=EB=8F=84=EB=A1=9D=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/message/components/message-card-detail.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/features/message/components/message-card-detail.jsx b/src/features/message/components/message-card-detail.jsx index 5eba950..2f90ae9 100644 --- a/src/features/message/components/message-card-detail.jsx +++ b/src/features/message/components/message-card-detail.jsx @@ -48,7 +48,8 @@ function MessageCardDetail({ message }) {
{formatDate(message.createdAt, ".")} From bedaff649cc4cef5318e7605d53df727b6804793 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Fri, 22 Aug 2025 11:48:54 +0900 Subject: [PATCH 220/253] =?UTF-8?q?feat=20[#52]=20Reaction=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=EC=97=90=20API=20=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/reaction/api/reaction.js | 13 ++++ .../header/rolling-paper-header.jsx | 19 ++++- .../header/rolling-paper-reactions.jsx | 69 +++++++++++++++++++ src/pages/messages-page.jsx | 3 +- 4 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 src/features/reaction/api/reaction.js create mode 100644 src/features/rolling-paper/components/header/rolling-paper-reactions.jsx diff --git a/src/features/reaction/api/reaction.js b/src/features/reaction/api/reaction.js new file mode 100644 index 0000000..1ac7ef7 --- /dev/null +++ b/src/features/reaction/api/reaction.js @@ -0,0 +1,13 @@ +import { apiClient } from "../../../api/client"; + +async function getReactions({ recipientId }) { + const response = await apiClient.get(`recipients/${recipientId}/reactions/`); + if (response.status !== 200) { + throw new Error("Reactions data를 가져오는데 실패했습니다."); + } + + const data = response.data; + return data.results; +} + +export { getReactions }; diff --git a/src/features/rolling-paper/components/header/rolling-paper-header.jsx b/src/features/rolling-paper/components/header/rolling-paper-header.jsx index 71ed1f4..05a50c5 100644 --- a/src/features/rolling-paper/components/header/rolling-paper-header.jsx +++ b/src/features/rolling-paper/components/header/rolling-paper-header.jsx @@ -1,3 +1,4 @@ +import { useEffect, useState } from "react"; import styled from "styled-components"; import Colors from "../../../../components/color/colors"; import Toast from "../../../../components/toast/toast"; @@ -5,6 +6,7 @@ import { useMedia } from "../../../../hooks/use-media"; import { useToast } from "../../../../hooks/use-toast"; import { shareRollingPaper } from "../../../../libs/kakao/kakao-service"; import { media } from "../../../../utils/media"; +import { getReactions } from "../../../reaction/api/reaction"; import AddReactionPopover from "../../../reaction/components/add-reaction-popover"; import ReceivedReactions from "../../../reaction/components/received-reactions"; import DividedContainer from "./divided-container"; @@ -65,10 +67,11 @@ function RollingPaperHeader({ recipientId, recipientName, messages, - reactions, + topReactions, }) { const { showsToast, setShowsToast } = useToast(); const { isDesktop, isMobile } = useMedia(); + const [reactions, setReactions] = useState([]); const name = {`To. ${recipientName}`}; @@ -85,6 +88,15 @@ function RollingPaperHeader({ setShowsToast(true); }; + useEffect(() => { + getReactions({ recipientId }) + .then(setReactions) + .catch((error) => { + // TODO: Error 처리 필요 + console.error(error); + }); + }, [recipientId]); + return ( {isMobile && ( @@ -99,7 +111,10 @@ function RollingPaperHeader({ profiles={messages.map((message) => message.profileImageURL)} /> )} - + {isEditing || } diff --git a/src/features/rolling-paper/components/header/rolling-paper-reactions.jsx b/src/features/rolling-paper/components/header/rolling-paper-reactions.jsx new file mode 100644 index 0000000..ca74682 --- /dev/null +++ b/src/features/rolling-paper/components/header/rolling-paper-reactions.jsx @@ -0,0 +1,69 @@ +import styled from "styled-components"; +import arrowDownImage from "../../../../assets/ic-chevron-down.svg"; +import EmojiBadge from "../../../../components/badge/emoji-badge"; +import Popover from "../../../../components/popover/popover"; +import POPOVER_ALIGNMENT from "../../../../components/popover/popover-alignment"; +import { useMedia } from "../../../../hooks/use-media"; +import { media } from "../../../../utils/media"; + +const MoreButton = styled.button` + background: none; + border: none; + width: 36px; + height: 36px; + cursor: pointer; +`; + +const TopThreeReactions = styled.div` + display: flex; + gap: 8px; +`; + +const AllReactions = styled.div` + padding: 24px; + display: grid; + grid-template-columns: repeat(4, min-content); + row-gap: 10px; + column-gap: 8px; + + ${media.mobile} { + grid-template-columns: repeat(3, min-content); + } +`; + +const StyledRollingPaperReactions = styled.div` + display: flex; + gap: 2px; + align-items: center; +`; + +function RollingPaperReactions({ topReactions, reactions }) { + const { isMobile } = useMedia(); + + return ( + + + {topReactions.map(({ id, emoji, count }) => ( + + ))} + + + 열기 버튼 + + } + > + + {reactions.slice(0, isMobile ? 6 : 8).map(({ id, emoji, count }) => ( + + ))} + + + + ); +} + +export default RollingPaperReactions; diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx index c29e5fd..2e78edc 100644 --- a/src/pages/messages-page.jsx +++ b/src/pages/messages-page.jsx @@ -120,6 +120,7 @@ function MessagesPage() { getRecipient({ id }), getMessages({ recipientId: id }), ]); + setRecipient(recipient); setMessages(messages); } catch (error) { @@ -140,7 +141,7 @@ function MessagesPage() { recipientId={recipient.id} recipientName={recipient.name} messages={messages} - reactions={recipient.topReactions} + topReactions={recipient.topReactions} /> Date: Fri, 22 Aug 2025 12:50:43 +0900 Subject: [PATCH 221/253] =?UTF-8?q?fix=20[]=20Popover=20content=EB=A5=BC?= =?UTF-8?q?=20=ED=81=B4=EB=A6=AD=ED=95=A0=20=EB=95=8C=EB=8A=94=20popover?= =?UTF-8?q?=EB=A5=BC=20=EB=8B=AB=EC=A7=80=20=EC=95=8A=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/popover/popover.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/popover/popover.jsx b/src/components/popover/popover.jsx index e6d31e8..156e457 100644 --- a/src/components/popover/popover.jsx +++ b/src/components/popover/popover.jsx @@ -37,6 +37,7 @@ function Popover({ id, alignment, action, children }) { const handleClick = () => handleTargetClick(true); const handleBackdropClick = () => setShowsPopover(false); + const handlePopoverClick = (event) => event.stopPropagation(); return ( <> @@ -46,7 +47,9 @@ function Popover({ id, alignment, action, children }) { {showsPopover && ( - {children} + + {children} + )} From d27ab3579313866d1f4c174e8804cb7875f5c5f9 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Fri, 22 Aug 2025 12:53:25 +0900 Subject: [PATCH 222/253] =?UTF-8?q?refactor=20[#52]=20=EA=B0=9C=EC=88=98?= =?UTF-8?q?=EA=B0=80=20=EA=B0=80=EC=9E=A5=20=EB=A7=8E=EC=9D=80=20=EB=A6=AC?= =?UTF-8?q?=EC=95=A1=EC=85=98=203=EA=B0=9C=20=ED=91=9C=EC=8B=9C=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EB=B0=A9=EC=8B=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - as-is : API가 반환한 recipient data의 `topReactions` 값 사용 - to-be : API가 반환한 리액션 목록의 상위 3개 사용 --- src/features/reaction/components/received-reactions.jsx | 4 ++-- .../components/header/rolling-paper-header.jsx | 7 ++----- src/pages/messages-page.jsx | 1 - 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/features/reaction/components/received-reactions.jsx b/src/features/reaction/components/received-reactions.jsx index f529cf7..cafdcef 100644 --- a/src/features/reaction/components/received-reactions.jsx +++ b/src/features/reaction/components/received-reactions.jsx @@ -9,12 +9,12 @@ const StyledRollingPaperReactions = styled.div` align-items: center; `; -function ReceivedReactions({ topReactions, reactions }) { +function ReceivedReactions({ reactions }) { const { isMobile } = useMedia(); return ( - + ); diff --git a/src/features/rolling-paper/components/header/rolling-paper-header.jsx b/src/features/rolling-paper/components/header/rolling-paper-header.jsx index 05a50c5..68c4c1c 100644 --- a/src/features/rolling-paper/components/header/rolling-paper-header.jsx +++ b/src/features/rolling-paper/components/header/rolling-paper-header.jsx @@ -62,12 +62,12 @@ const StyledRollingPaperHeader = styled.div` align-items: flex-start; } `; + function RollingPaperHeader({ isEditing, recipientId, recipientName, messages, - topReactions, }) { const { showsToast, setShowsToast } = useToast(); const { isDesktop, isMobile } = useMedia(); @@ -111,10 +111,7 @@ function RollingPaperHeader({ profiles={messages.map((message) => message.profileImageURL)} /> )} - + {isEditing || } diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx index 2e78edc..c057092 100644 --- a/src/pages/messages-page.jsx +++ b/src/pages/messages-page.jsx @@ -141,7 +141,6 @@ function MessagesPage() { recipientId={recipient.id} recipientName={recipient.name} messages={messages} - topReactions={recipient.topReactions} /> Date: Fri, 22 Aug 2025 12:53:43 +0900 Subject: [PATCH 223/253] =?UTF-8?q?feat=20[#52]=20Reaction=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/reaction/api/reaction.js | 18 +++++++++- .../components/add-reaction-popover.jsx | 8 +++-- .../header/rolling-paper-header.jsx | 33 +++++++++++++------ 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/features/reaction/api/reaction.js b/src/features/reaction/api/reaction.js index 1ac7ef7..3494677 100644 --- a/src/features/reaction/api/reaction.js +++ b/src/features/reaction/api/reaction.js @@ -10,4 +10,20 @@ async function getReactions({ recipientId }) { return data.results; } -export { getReactions }; +async function addReaction({ recipientId, emoji }) { + const response = await apiClient.post( + `recipients/${recipientId}/reactions/`, + { + emoji, + type: "increase", + } + ); + if (response.status !== 201) { + throw new Error("Reaction을 추가하는데 실패했습니다."); + } + + const data = response.data; + return data; +} + +export { addReaction, getReactions }; diff --git a/src/features/reaction/components/add-reaction-popover.jsx b/src/features/reaction/components/add-reaction-popover.jsx index c880f35..b191d66 100644 --- a/src/features/reaction/components/add-reaction-popover.jsx +++ b/src/features/reaction/components/add-reaction-popover.jsx @@ -26,14 +26,18 @@ function PopoverAction() { ); } -function AddReactionPopover() { +function AddReactionPopover({ onSelect }) { + const handleEmojiClick = (data) => { + onSelect(data.emoji); + }; + return ( } > - + ); } diff --git a/src/features/rolling-paper/components/header/rolling-paper-header.jsx b/src/features/rolling-paper/components/header/rolling-paper-header.jsx index 68c4c1c..5127f4b 100644 --- a/src/features/rolling-paper/components/header/rolling-paper-header.jsx +++ b/src/features/rolling-paper/components/header/rolling-paper-header.jsx @@ -1,4 +1,4 @@ -import { useEffect, useState } from "react"; +import { useCallback, useEffect, useState } from "react"; import styled from "styled-components"; import Colors from "../../../../components/color/colors"; import Toast from "../../../../components/toast/toast"; @@ -6,7 +6,7 @@ import { useMedia } from "../../../../hooks/use-media"; import { useToast } from "../../../../hooks/use-toast"; import { shareRollingPaper } from "../../../../libs/kakao/kakao-service"; import { media } from "../../../../utils/media"; -import { getReactions } from "../../../reaction/api/reaction"; +import { addReaction, getReactions } from "../../../reaction/api/reaction"; import AddReactionPopover from "../../../reaction/components/add-reaction-popover"; import ReceivedReactions from "../../../reaction/components/received-reactions"; import DividedContainer from "./divided-container"; @@ -75,6 +75,22 @@ function RollingPaperHeader({ const name = {`To. ${recipientName}`}; + const updateReactions = useCallback( + () => + getReactions({ recipientId }) + .then(setReactions) + .catch((error) => { + // TODO: Error 처리 필요 + console.error(error); + }), + [recipientId] + ); + + const handleReactionSelect = async (emoji) => { + await addReaction({ recipientId, emoji }); + updateReactions(); + }; + const handleShareKakao = () => { shareRollingPaper({ recipientId, @@ -89,13 +105,8 @@ function RollingPaperHeader({ }; useEffect(() => { - getReactions({ recipientId }) - .then(setReactions) - .catch((error) => { - // TODO: Error 처리 필요 - console.error(error); - }); - }, [recipientId]); + updateReactions(); + }, [updateReactions]); return ( @@ -114,7 +125,9 @@ function RollingPaperHeader({ - {isEditing || } + {isEditing || ( + + )} Date: Fri, 22 Aug 2025 13:57:37 +0900 Subject: [PATCH 224/253] =?UTF-8?q?refactor=20[]=20`RollingPaperMessagesGr?= =?UTF-8?q?id`=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B2=BD=EB=A1=9C?= =?UTF-8?q?=20=EB=B0=8F=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/messages-grid.jsx} | 14 +++++++------- src/pages/messages-page.jsx | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) rename src/features/{rolling-paper/components/messages/rolling-paper-messages-grid.jsx => message/components/messages-grid.jsx} (73%) diff --git a/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx b/src/features/message/components/messages-grid.jsx similarity index 73% rename from src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx rename to src/features/message/components/messages-grid.jsx index a695359..bdf974d 100644 --- a/src/features/rolling-paper/components/messages/rolling-paper-messages-grid.jsx +++ b/src/features/message/components/messages-grid.jsx @@ -1,10 +1,10 @@ import { useNavigate, useParams } from "react-router"; import styled from "styled-components"; -import Modal from "../../../../components/modal/modal.jsx"; -import { media } from "../../../../utils/media.js"; -import MessageCardAdd from "../../../message/components/message-card-add.jsx"; -import MessageCardDetail from "../../../message/components/message-card-detail.jsx"; -import MessageCard from "../../../message/components/message-card.jsx"; +import Modal from "../../../components/modal/modal.jsx"; +import { media } from "../../../utils/media.js"; +import MessageCardAdd from "./message-card-add.jsx"; +import MessageCardDetail from "./message-card-detail.jsx"; +import MessageCard from "./message-card.jsx"; const StyledRollingPaperMessagesGrid = styled.div` display: grid; @@ -22,7 +22,7 @@ const StyledRollingPaperMessagesGrid = styled.div` } `; -function RollingPaperMessagesGrid({ isEditing, messages, onDelete }) { +function MessagesGrid({ isEditing, messages, onDelete }) { const navigate = useNavigate(); const { id } = useParams(); @@ -59,4 +59,4 @@ function RollingPaperMessagesGrid({ isEditing, messages, onDelete }) { ); } -export default RollingPaperMessagesGrid; +export default MessagesGrid; diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx index c057092..110e445 100644 --- a/src/pages/messages-page.jsx +++ b/src/pages/messages-page.jsx @@ -5,9 +5,9 @@ import { OutlinedButton, PrimaryButton } from "../components/button/button"; import BUTTON_SIZE from "../components/button/button-size"; import BACKGROUND_COLOR from "../components/color/background-color"; import { getMessages } from "../features/message/api/messages"; +import MessagesGrid from "../features/message/components/messages-grid"; import { getRecipient } from "../features/rolling-paper/api/recipients"; import RollingPaperHeader from "../features/rolling-paper/components/header/rolling-paper-header"; -import RollingPaperMessagesGrid from "../features/rolling-paper/components/messages/rolling-paper-messages-grid"; import { useMedia } from "../hooks/use-media"; import ContentLayout from "../layouts/content-layout"; import { media } from "../utils/media"; @@ -155,7 +155,7 @@ function MessagesPage() { ) : ( )} - Date: Fri, 22 Aug 2025 19:19:40 +0900 Subject: [PATCH 225/253] =?UTF-8?q?feat=20[#52]=20=EB=A1=A4=EB=A7=81?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=ED=8D=BC=EC=97=90=20=EB=8B=AC=EB=A6=B0=20?= =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80=20=EB=AA=A9=EB=A1=9D=EC=97=90=20?= =?UTF-8?q?=EB=AC=B4=ED=95=9C=20=EC=8A=A4=ED=81=AC=EB=A1=A4=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/message/api/messages.js | 21 +++++++++++++++++- .../message/components/messages-grid.jsx | 12 +++++++++- src/hooks/use-intersection-observer.jsx | 19 ++++++++++++++++ src/pages/messages-page.jsx | 22 ++++++++++++++++++- 4 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 src/hooks/use-intersection-observer.jsx diff --git a/src/features/message/api/messages.js b/src/features/message/api/messages.js index c24d0a1..ea1890e 100644 --- a/src/features/message/api/messages.js +++ b/src/features/message/api/messages.js @@ -1,5 +1,8 @@ +import axios from "axios"; import { apiClient } from "../../../api/client"; +let nextPage; + async function getMessages({ recipientId, limit, page = 1 }) { const searchParams = new URLSearchParams(); searchParams.append("page", page); @@ -15,7 +18,23 @@ async function getMessages({ recipientId, limit, page = 1 }) { } const data = response.data; + nextPage = data.next; + + return data.results; +} + +async function getNextPageMessages() { + if (!nextPage) return; + + const response = await axios.get(nextPage); + if (response.status !== 200) { + throw new Error("Message data를 가져오는데 실패했습니다."); + } + + const data = response.data; + nextPage = data.next; + return data.results; } -export { getMessages }; +export { getMessages, getNextPageMessages }; diff --git a/src/features/message/components/messages-grid.jsx b/src/features/message/components/messages-grid.jsx index bdf974d..9dccf08 100644 --- a/src/features/message/components/messages-grid.jsx +++ b/src/features/message/components/messages-grid.jsx @@ -1,6 +1,8 @@ +import { useRef } from "react"; import { useNavigate, useParams } from "react-router"; import styled from "styled-components"; import Modal from "../../../components/modal/modal.jsx"; +import { useIntersectionObserver } from "../../../hooks/use-intersection-observer.jsx"; import { media } from "../../../utils/media.js"; import MessageCardAdd from "./message-card-add.jsx"; import MessageCardDetail from "./message-card-detail.jsx"; @@ -22,9 +24,16 @@ const StyledRollingPaperMessagesGrid = styled.div` } `; -function MessagesGrid({ isEditing, messages, onDelete }) { +function MessagesGrid({ isEditing, messages, onDelete, onInfiniteScroll }) { const navigate = useNavigate(); const { id } = useParams(); + const infiniteScrollTargetRef = useRef(); + + const observerCallback = (entry) => { + if (!entry.isIntersecting) return; + onInfiniteScroll(); + }; + useIntersectionObserver(infiniteScrollTargetRef, observerCallback); const handleAddClick = () => { navigate(`/post/${id}/message`); @@ -55,6 +64,7 @@ function MessagesGrid({ isEditing, messages, onDelete }) { ) )} +
); } diff --git a/src/hooks/use-intersection-observer.jsx b/src/hooks/use-intersection-observer.jsx new file mode 100644 index 0000000..37e8ddb --- /dev/null +++ b/src/hooks/use-intersection-observer.jsx @@ -0,0 +1,19 @@ +import { useEffect } from "react"; + +function useIntersectionObserver(targetRef, callback) { + useEffect(() => { + const observer = new IntersectionObserver((entries) => { + entries.forEach(callback); + }); + + if (targetRef) { + observer.observe(targetRef.current); + } + + return () => { + observer.disconnect(); + }; + }, [targetRef, callback]); +} + +export { useIntersectionObserver }; diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx index 110e445..379c16d 100644 --- a/src/pages/messages-page.jsx +++ b/src/pages/messages-page.jsx @@ -4,7 +4,10 @@ import styled from "styled-components"; import { OutlinedButton, PrimaryButton } from "../components/button/button"; import BUTTON_SIZE from "../components/button/button-size"; import BACKGROUND_COLOR from "../components/color/background-color"; -import { getMessages } from "../features/message/api/messages"; +import { + getMessages, + getNextPageMessages, +} from "../features/message/api/messages"; import MessagesGrid from "../features/message/components/messages-grid"; import { getRecipient } from "../features/rolling-paper/api/recipients"; import RollingPaperHeader from "../features/rolling-paper/components/header/rolling-paper-header"; @@ -113,6 +116,22 @@ function MessagesPage() { console.log(`Delete Message ${messageId}`); }; + const handleInfiniteScroll = async () => { + const messages = await getNextPageMessages(); + if (!messages) return; + + setMessages((prev) => { + const newMessages = [...prev]; + + for (const message of messages) { + if (newMessages.find((value) => value.id === message.id)) continue; + newMessages.push(message); + } + + return newMessages; + }); + }; + useEffect(() => { async function fetchRollingPaper() { try { @@ -159,6 +178,7 @@ function MessagesPage() { isEditing={isEditing} messages={messages} onDelete={handleMessageDelete} + onInfiniteScroll={handleInfiniteScroll} />
From ca149677f3d1049a58791af3f1a55034a2bee97b Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Fri, 22 Aug 2025 19:42:02 +0900 Subject: [PATCH 226/253] =?UTF-8?q?feat=20[#52]=20=EB=A9=94=EC=8B=9C?= =?UTF-8?q?=EC=A7=80=20=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/message/api/messages.js | 9 ++++++++- src/features/message/components/messages-grid.jsx | 2 +- src/pages/messages-page.jsx | 14 ++++++++++---- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/features/message/api/messages.js b/src/features/message/api/messages.js index ea1890e..2b12e78 100644 --- a/src/features/message/api/messages.js +++ b/src/features/message/api/messages.js @@ -37,4 +37,11 @@ async function getNextPageMessages() { return data.results; } -export { getMessages, getNextPageMessages }; +async function deleteMessage({ id }) { + const response = await apiClient.delete(`messages/${id}/`); + if (response.status !== 204) { + throw new Error("Message를 삭제하는데 실패했습니다."); + } +} + +export { deleteMessage, getMessages, getNextPageMessages }; diff --git a/src/features/message/components/messages-grid.jsx b/src/features/message/components/messages-grid.jsx index 9dccf08..0e42b5e 100644 --- a/src/features/message/components/messages-grid.jsx +++ b/src/features/message/components/messages-grid.jsx @@ -48,7 +48,7 @@ function MessagesGrid({ isEditing, messages, onDelete, onInfiniteScroll }) { key={message.id} isEditing={isEditing} message={message} - onDelete={(event) => handleDeleteClick(event, message.id)} + onDelete={() => handleDeleteClick(message.id)} /> ); diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx index 379c16d..75f750b 100644 --- a/src/pages/messages-page.jsx +++ b/src/pages/messages-page.jsx @@ -5,6 +5,7 @@ import { OutlinedButton, PrimaryButton } from "../components/button/button"; import BUTTON_SIZE from "../components/button/button-size"; import BACKGROUND_COLOR from "../components/color/background-color"; import { + deleteMessage, getMessages, getNextPageMessages, } from "../features/message/api/messages"; @@ -77,7 +78,7 @@ function EditingButtons({ onDelete, onCancel }) { /> @@ -111,9 +112,14 @@ function MessagesPage() { navigate(-1); }; - const handleMessageDelete = (messageId) => { - // TODO: Message 삭제 - console.log(`Delete Message ${messageId}`); + const handleMessageDelete = async (messageId) => { + try { + await deleteMessage({ id: messageId }); + setMessages((prev) => prev.filter((message) => message.id !== messageId)); + } catch (error) { + // TODO: Error 처리 + console.log(error); + } }; const handleInfiniteScroll = async () => { From abf5300f0f13bda47323eb2e065735dd955983a2 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Fri, 22 Aug 2025 19:47:57 +0900 Subject: [PATCH 227/253] =?UTF-8?q?feat=20[#52]=20=EB=A1=A4=EB=A7=81?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=ED=8D=BC=20=EC=82=AD=EC=A0=9C=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20(`/list`=EB=A1=9C=20=EC=9D=B4=EB=8F=99)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/rolling-paper/api/recipients.js | 9 ++++++++- src/pages/messages-page.jsx | 17 ++++++++++++----- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/features/rolling-paper/api/recipients.js b/src/features/rolling-paper/api/recipients.js index 42a8bcd..3fccdc4 100644 --- a/src/features/rolling-paper/api/recipients.js +++ b/src/features/rolling-paper/api/recipients.js @@ -9,4 +9,11 @@ async function getRecipient({ id }) { return response.data; } -export { getRecipient }; +async function deleteRecipient({ id }) { + const response = await apiClient.delete(`recipients/${id}/`); + if (response.status !== 204) { + throw new Error("Recipient를 삭제하는데 실패했습니다."); + } +} + +export { deleteRecipient, getRecipient }; diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx index 75f750b..f4827b7 100644 --- a/src/pages/messages-page.jsx +++ b/src/pages/messages-page.jsx @@ -10,7 +10,10 @@ import { getNextPageMessages, } from "../features/message/api/messages"; import MessagesGrid from "../features/message/components/messages-grid"; -import { getRecipient } from "../features/rolling-paper/api/recipients"; +import { + deleteRecipient, + getRecipient, +} from "../features/rolling-paper/api/recipients"; import RollingPaperHeader from "../features/rolling-paper/components/header/rolling-paper-header"; import { useMedia } from "../hooks/use-media"; import ContentLayout from "../layouts/content-layout"; @@ -102,10 +105,14 @@ function MessagesPage() { navigate("edit"); }; - const handleRollingPaperDelete = () => { - // TODO: Rolling Paper 삭제 - console.log(`Delete Rolling Paper ${recipient.id}`); - navigate(-1); + const handleRollingPaperDelete = async () => { + try { + await deleteRecipient({ id: recipient.id }); + navigate(`/list`); + } catch (error) { + // TODO: Error 처리 + console.log(error); + } }; const handleEditCancel = () => { From 85da172ea39dc6d871db6d778c448a2dab998b45 Mon Sep 17 00:00:00 2001 From: luli Date: Tue, 19 Aug 2025 15:24:03 +0900 Subject: [PATCH 228/253] =?UTF-8?q?[#53]=20=EB=82=98=EB=8F=84=20=EB=A7=8C?= =?UTF-8?q?=EB=93=A4=EC=96=B4=EB=B3=B4=EA=B8=B0=EB=B2=84=ED=8A=BC=20url?= =?UTF-8?q?=EC=97=B0=EA=B2=B0,=20top-=20margin=EC=A1=B0=EA=B8=88=20?= =?UTF-8?q?=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 나도 만들어보기버튼 url연결, top- margin조금 조정 --- src/pages/rolling-paper-list-page.jsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pages/rolling-paper-list-page.jsx b/src/pages/rolling-paper-list-page.jsx index e7b410c..b823ded 100644 --- a/src/pages/rolling-paper-list-page.jsx +++ b/src/pages/rolling-paper-list-page.jsx @@ -70,6 +70,10 @@ function ShowMessageList() { const [cardCount, setCardCount] = useState(4); const { isDesktop } = useMedia(); + const handleMakingButton = () => { + navigate("/post"); + }; + useEffect(() => { isDesktop ? setCardCount(4) : setCardCount(null); }, [isDesktop]); From 1f1f5255560b618c85bd7a20cfb8b5777aa26eb5 Mon Sep 17 00:00:00 2001 From: luli Date: Wed, 20 Aug 2025 05:09:06 +0900 Subject: [PATCH 229/253] =?UTF-8?q?[#61]=20list=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EB=B0=98=EC=9D=91=ED=98=95=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 타블렛, 모바일 반응형 화면 구현 --- src/pages/rolling-paper-list-page.jsx | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/pages/rolling-paper-list-page.jsx b/src/pages/rolling-paper-list-page.jsx index b823ded..3a93f56 100644 --- a/src/pages/rolling-paper-list-page.jsx +++ b/src/pages/rolling-paper-list-page.jsx @@ -70,6 +70,21 @@ function ShowMessageList() { const [cardCount, setCardCount] = useState(4); const { isDesktop } = useMedia(); + useEffect(() => { + const mql = window.matchMedia("(max-width: 1199px)"); + const updateCardCount = (e) => { + if (e.matches) { + setCardCount(null); + } else { + setCardCount(4); + } + }; + + updateCardCount(mql); + mql.addEventListener("change", updateCardCount); + return () => mql.removeEventListener("change", updateCardCount); + }, []); + const handleMakingButton = () => { navigate("/post"); }; From 4725c5a065febbea3c0a06cbce679b03ef32ae82 Mon Sep 17 00:00:00 2001 From: luli Date: Thu, 21 Aug 2025 03:19:09 +0900 Subject: [PATCH 230/253] =?UTF-8?q?[#61]=20pr=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EB=B0=98=EC=98=81=20=EB=B0=8F=20=EB=A9=98?= =?UTF-8?q?=ED=86=A0=EB=A7=81=20=EC=BD=94=EB=93=9C=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EB=B0=98=EC=98=81=20(=EC=9D=B4=EB=AA=A8=EC=A7=80=EB=8F=84=20ho?= =?UTF-8?q?ver=ED=96=88=EC=9D=84=EB=95=8C=20=EC=88=AB=EC=9E=90=EB=A7=8C=20?= =?UTF-8?q?=EB=B3=B4=EC=9D=B4=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95,=20?= =?UTF-8?q?=EB=AA=A8=EB=B0=94=EC=9D=BC=ED=99=94=EB=A9=B4=EC=97=90=EC=84=9C?= =?UTF-8?q?=20padding=EB=93=B1=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=9D=BC?= =?UTF-8?q?=EB=B6=80=20=EC=88=98=EC=A0=95)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pr 수정사항 반영 및 멘토링 코드리뷰 반영 (이모지도 hover했을때 숫자만 보이도록 수정, 모바일화면에서 padding등 스타일 일부 수정) --- .../api/mock-rolling-paper-list.json | 2 +- src/pages/rolling-paper-list-page.jsx | 18 ++---------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/src/features/rolling-paper/api/mock-rolling-paper-list.json b/src/features/rolling-paper/api/mock-rolling-paper-list.json index c29b250..fe7ddaf 100644 --- a/src/features/rolling-paper/api/mock-rolling-paper-list.json +++ b/src/features/rolling-paper/api/mock-rolling-paper-list.json @@ -220,7 +220,7 @@ }, { "emoji": "👍", - "count": 33 + "count": 333 } ] }, diff --git a/src/pages/rolling-paper-list-page.jsx b/src/pages/rolling-paper-list-page.jsx index 3a93f56..ea91d6a 100644 --- a/src/pages/rolling-paper-list-page.jsx +++ b/src/pages/rolling-paper-list-page.jsx @@ -71,19 +71,8 @@ function ShowMessageList() { const { isDesktop } = useMedia(); useEffect(() => { - const mql = window.matchMedia("(max-width: 1199px)"); - const updateCardCount = (e) => { - if (e.matches) { - setCardCount(null); - } else { - setCardCount(4); - } - }; - - updateCardCount(mql); - mql.addEventListener("change", updateCardCount); - return () => mql.removeEventListener("change", updateCardCount); - }, []); + isDesktop ? setCardCount(4) : setCardCount(null); + }, [isDesktop]); const handleMakingButton = () => { navigate("/post"); @@ -93,9 +82,6 @@ function ShowMessageList() { isDesktop ? setCardCount(4) : setCardCount(null); }, [isDesktop]); - const handleMakingButton = () => { - navigate("/post"); - }; useEffect(() => { getRollingPaperList().then(setTestData); From c44c3d21e8d806af8ba6f454a76fb2e50f701fbf Mon Sep 17 00:00:00 2001 From: luli Date: Thu, 21 Aug 2025 13:41:53 +0900 Subject: [PATCH 231/253] =?UTF-8?q?[#61]=20=EB=88=84=EB=9D=BD=EB=90=9C?= =?UTF-8?q?=EB=B6=80=EB=B6=84=20=EC=88=98=EC=A0=95=20(api.jsx)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ㅎㅎ --- src/features/rolling-paper/api/mock-rolling-paper-list.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/rolling-paper/api/mock-rolling-paper-list.json b/src/features/rolling-paper/api/mock-rolling-paper-list.json index fe7ddaf..c29b250 100644 --- a/src/features/rolling-paper/api/mock-rolling-paper-list.json +++ b/src/features/rolling-paper/api/mock-rolling-paper-list.json @@ -220,7 +220,7 @@ }, { "emoji": "👍", - "count": 333 + "count": 33 } ] }, From 9a521b53b4226ba23bf0dbcbc009dd2031d75b6b Mon Sep 17 00:00:00 2001 From: luli Date: Fri, 22 Aug 2025 04:07:07 +0900 Subject: [PATCH 232/253] =?UTF-8?q?[#75]=20=EC=B9=B4=EB=93=9C=20=EB=B0=B0?= =?UTF-8?q?=EA=B2=BD=EC=9D=B4=EB=AF=B8=EC=A7=80,=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EB=93=B1=20=EB=A1=9C?= =?UTF-8?q?=EB=94=A9=20=EC=95=A0=EB=8B=88=EB=A9=94=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80,=20=EC=B9=B4=EB=93=9C=20=EC=8A=A4=ED=81=AC?= =?UTF-8?q?=EB=A1=A4=EC=8B=9C=20=EC=B9=B4=EB=93=9C=EB=8B=A8=EC=9C=84?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=B4=EC=9D=B4=EB=8F=84=EB=A1=9D=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 카드 배경이미지, 프로필 이미지 등 로딩 애니메이션 추가, 카드 스크롤시 카드단위로 보이도록 기능 추가 --- src/features/rolling-paper/components/rolling-paper-list.jsx | 1 - src/pages/rolling-paper-list-page.jsx | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/features/rolling-paper/components/rolling-paper-list.jsx b/src/features/rolling-paper/components/rolling-paper-list.jsx index 16e93b0..b826b4e 100644 --- a/src/features/rolling-paper/components/rolling-paper-list.jsx +++ b/src/features/rolling-paper/components/rolling-paper-list.jsx @@ -1,7 +1,6 @@ import ArrowButton from "../../../components/button/arrow-button"; import ARROW_BUTTON_DIRECTION from "../../../components/button/arrow-button-direction"; import { media } from "../../../utils/media"; - import styled, { css } from "styled-components"; const backgroundColors = { diff --git a/src/pages/rolling-paper-list-page.jsx b/src/pages/rolling-paper-list-page.jsx index ea91d6a..49b3f4c 100644 --- a/src/pages/rolling-paper-list-page.jsx +++ b/src/pages/rolling-paper-list-page.jsx @@ -1,10 +1,8 @@ import { PrimaryButton } from "../components/button/button"; import BUTTON_SIZE from "../components/button/button-size"; import { useNavigate } from "react-router"; - import React, { useEffect, useState, useMemo } from "react"; import { getRollingPaperList } from "../features/rolling-paper/api/rollingPaperList"; - import styled from "styled-components"; import RollingPaperList from "../features/rolling-paper/components/rolling-paper-list"; import { media } from "../utils/media"; From 90f61b0d6e4fcd9b44f286776bd6bdc2276dce9f Mon Sep 17 00:00:00 2001 From: luli Date: Fri, 22 Aug 2025 04:38:15 +0900 Subject: [PATCH 233/253] =?UTF-8?q?[#75]=20=EB=88=84=EB=9D=BD=EB=90=9C=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EB=8B=A4=EC=8B=9C=20=EC=BB=A4=EB=B0=8B=20?= =?UTF-8?q?->=20=EC=B9=B4=EB=93=9C=20=EB=B0=B0=EA=B2=BD=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80,=20=ED=94=84=EB=A1=9C=ED=95=84=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=20=EB=93=B1=20=EB=A1=9C=EB=94=A9=20=EC=95=A0=EB=8B=88?= =?UTF-8?q?=EB=A9=94=EC=9D=B4=EC=85=98=20=EC=B6=94=EA=B0=80,=20=EC=B9=B4?= =?UTF-8?q?=EB=93=9C=20=EC=8A=A4=ED=81=AC=EB=A1=A4=EC=8B=9C=20=EC=B9=B4?= =?UTF-8?q?=EB=93=9C=EB=8B=A8=EC=9C=84=EB=A1=9C=20=EB=B3=B4=EC=9D=B4?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 카드 배경이미지, 프로필 이미지 등 로딩 애니메이션 추가, 카드 스크롤시 카드단위로 보이도록 기능 추가 --- .../api/mock-rolling-paper-list.json | 398 +++++++++--------- .../components/rolling-paper-list.jsx | 191 +++++++-- src/pages/rolling-paper-list-page.jsx | 9 +- 3 files changed, 368 insertions(+), 230 deletions(-) diff --git a/src/features/rolling-paper/api/mock-rolling-paper-list.json b/src/features/rolling-paper/api/mock-rolling-paper-list.json index c29b250..8c3cd67 100644 --- a/src/features/rolling-paper/api/mock-rolling-paper-list.json +++ b/src/features/rolling-paper/api/mock-rolling-paper-list.json @@ -88,10 +88,10 @@ { "id": 30238, "recipientId": 43558, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/340/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 32", + "content": "차은우님의 메세지 내용 32", "font": "Nanum Gothic", "createdAt": "2023-06-17T00:31:29Z" }, @@ -171,7 +171,7 @@ }, { "id": 18499, - "name": "이병헌", + "name": "차은우 차은우 차은우 차은우 차은우 차은우 차은우", "backgroundColor": "beige", "backgroundImageURL": "https://picsum.photos/seed/18499/600/400", "createdAt": "2023-06-03T04:15:47Z", @@ -180,10 +180,10 @@ { "id": 48979, "recipientId": 18499, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/11/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 77", + "content": "차은우님의 메세지 내용 77", "font": "Nanum Gothic", "createdAt": "2023-08-25T00:15:25Z" }, @@ -200,10 +200,10 @@ { "id": 35753, "recipientId": 18499, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/173/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 67", + "content": "차은우님의 메세지 내용 67", "font": "Nanum Gothic", "createdAt": "2023-07-23T23:14:30Z" } @@ -332,7 +332,7 @@ }, { "id": 13425, - "name": "이병헌", + "name": "차은우", "backgroundColor": "beige", "backgroundImageURL": "https://picsum.photos/seed/13425/600/400", "createdAt": "2023-07-06T20:30:52Z", @@ -419,10 +419,10 @@ { "id": 34424, "recipientId": 97436, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/141/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 6", + "content": "차은우님의 메세지 내용 6", "font": "Nanum Gothic", "createdAt": "2023-06-01T12:35:35Z" }, @@ -465,7 +465,7 @@ }, { "id": 22932, - "name": "이병헌", + "name": "차은우", "backgroundColor": "blue", "backgroundImageURL": "https://picsum.photos/seed/22932/600/400", "createdAt": "2023-12-21T05:29:02Z", @@ -615,10 +615,10 @@ { "id": 88963, "recipientId": 2194, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/317/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 81", + "content": "차은우님의 메세지 내용 81", "font": "Nanum Gothic", "createdAt": "2023-03-12T08:38:10Z" } @@ -758,7 +758,7 @@ }, { "id": 45901, - "name": "이병헌", + "name": "차은우", "backgroundColor": "purple", "backgroundImageURL": null, "createdAt": "2023-06-14T15:34:31Z", @@ -898,10 +898,10 @@ { "id": 99518, "recipientId": 84532, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/2/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 83", + "content": "차은우님의 메세지 내용 83", "font": "Nanum Gothic", "createdAt": "2023-07-12T22:08:05Z" }, @@ -965,10 +965,10 @@ { "id": 72173, "recipientId": 85839, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/137/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 84", + "content": "차은우님의 메세지 내용 84", "font": "Pretendard", "createdAt": "2023-04-01T12:40:19Z" } @@ -1049,10 +1049,10 @@ { "id": 20559, "recipientId": 76172, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/315/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 53", + "content": "차은우님의 메세지 내용 53", "font": "Roboto", "createdAt": "2023-07-06T05:06:42Z" }, @@ -1151,10 +1151,10 @@ { "id": 26243, "recipientId": 525, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/470/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 36", + "content": "차은우님의 메세지 내용 36", "font": "Noto Sans", "createdAt": "2024-02-01T22:09:11Z" }, @@ -1313,10 +1313,10 @@ { "id": 8442, "recipientId": 76854, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/391/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 6", + "content": "차은우님의 메세지 내용 6", "font": "Pretendard", "createdAt": "2023-12-21T09:27:19Z" }, @@ -1360,10 +1360,10 @@ { "id": 3111, "recipientId": 50919, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/384/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 80", + "content": "차은우님의 메세지 내용 80", "font": "Pretendard", "createdAt": "2023-08-12T11:51:00Z" }, @@ -1586,7 +1586,7 @@ }, { "id": 5465, - "name": "이병헌", + "name": "차은우", "backgroundColor": "beige", "backgroundImageURL": null, "createdAt": "2023-01-10T18:10:25Z", @@ -1893,10 +1893,10 @@ { "id": 66552, "recipientId": 90385, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/498/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 36", + "content": "차은우님의 메세지 내용 36", "font": "Noto Sans", "createdAt": "2023-10-17T11:54:41Z" } @@ -2004,10 +2004,10 @@ { "id": 59673, "recipientId": 39122, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/467/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 15", + "content": "차은우님의 메세지 내용 15", "font": "Nanum Gothic", "createdAt": "2023-03-20T07:58:11Z" }, @@ -2075,10 +2075,10 @@ { "id": 87956, "recipientId": 36279, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/362/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 45", + "content": "차은우님의 메세지 내용 45", "font": "Pretendard", "createdAt": "2023-01-10T01:43:19Z" } @@ -2269,10 +2269,10 @@ { "id": 60985, "recipientId": 2640, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/440/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 52", + "content": "차은우님의 메세지 내용 52", "font": "Pretendard", "createdAt": "2023-05-11T23:03:58Z" }, @@ -2643,20 +2643,20 @@ { "id": 96788, "recipientId": 73648, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/249/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 54", + "content": "차은우님의 메세지 내용 54", "font": "Nanum Gothic", "createdAt": "2023-09-16T01:58:06Z" }, { "id": 20726, "recipientId": 73648, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/431/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 78", + "content": "차은우님의 메세지 내용 78", "font": "Pretendard", "createdAt": "2023-07-25T07:59:44Z" } @@ -2991,10 +2991,10 @@ { "id": 65998, "recipientId": 73391, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/117/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 7", + "content": "차은우님의 메세지 내용 7", "font": "Noto Sans", "createdAt": "2023-06-29T21:54:39Z" } @@ -3166,7 +3166,7 @@ }, { "id": 26744, - "name": "이병헌", + "name": "차은우", "backgroundColor": "beige", "backgroundImageURL": null, "createdAt": "2023-03-23T03:14:00Z", @@ -3277,10 +3277,10 @@ { "id": 35228, "recipientId": 90477, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/94/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 63", + "content": "차은우님의 메세지 내용 63", "font": "Roboto", "createdAt": "2023-05-25T06:02:55Z" }, @@ -3574,7 +3574,7 @@ }, { "id": 31714, - "name": "이병헌", + "name": "차은우", "backgroundColor": "beige", "backgroundImageURL": "https://picsum.photos/seed/31714/600/400", "createdAt": "2023-01-13T08:26:56Z", @@ -3630,10 +3630,10 @@ { "id": 88820, "recipientId": 24976, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/355/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 72", + "content": "차은우님의 메세지 내용 72", "font": "Pretendard", "createdAt": "2023-12-02T16:28:28Z" } @@ -3759,10 +3759,10 @@ { "id": 35658, "recipientId": 9191, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/62/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 27", + "content": "차은우님의 메세지 내용 27", "font": "Nanum Gothic", "createdAt": "2023-04-09T12:56:46Z" }, @@ -3779,10 +3779,10 @@ { "id": 20041, "recipientId": 9191, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/114/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 72", + "content": "차은우님의 메세지 내용 72", "font": "Pretendard", "createdAt": "2023-11-11T12:43:30Z" } @@ -3861,10 +3861,10 @@ { "id": 53736, "recipientId": 625, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/411/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 98", + "content": "차은우님의 메세지 내용 98", "font": "Nanum Gothic", "createdAt": "2023-06-06T17:47:12Z" }, @@ -3922,10 +3922,10 @@ { "id": 53607, "recipientId": 23417, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/402/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 96", + "content": "차은우님의 메세지 내용 96", "font": "Noto Sans", "createdAt": "2023-06-28T04:25:20Z" } @@ -4063,10 +4063,10 @@ { "id": 76625, "recipientId": 48647, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/256/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 98", + "content": "차은우님의 메세지 내용 98", "font": "Pretendard", "createdAt": "2023-03-21T02:42:08Z" }, @@ -4118,10 +4118,10 @@ { "id": 90888, "recipientId": 7110, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/19/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 42", + "content": "차은우님의 메세지 내용 42", "font": "Roboto", "createdAt": "2023-09-16T18:15:50Z" }, @@ -4219,7 +4219,7 @@ }, { "id": 75973, - "name": "이병헌", + "name": "차은우", "backgroundColor": "beige", "backgroundImageURL": "https://picsum.photos/seed/75973/600/400", "createdAt": "2023-04-29T23:14:33Z", @@ -4228,10 +4228,10 @@ { "id": 85401, "recipientId": 75973, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/269/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 90", + "content": "차은우님의 메세지 내용 90", "font": "Noto Sans", "createdAt": "2023-11-12T05:17:44Z" }, @@ -4631,7 +4631,7 @@ }, { "id": 32314, - "name": "이병헌", + "name": "차은우", "backgroundColor": "purple", "backgroundImageURL": null, "createdAt": "2023-06-09T07:16:23Z", @@ -4650,10 +4650,10 @@ { "id": 10034, "recipientId": 32314, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/288/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 22", + "content": "차은우님의 메세지 내용 22", "font": "Pretendard", "createdAt": "2023-09-14T13:27:24Z" }, @@ -4801,10 +4801,10 @@ { "id": 50489, "recipientId": 63219, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/11/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 77", + "content": "차은우님의 메세지 내용 77", "font": "Noto Sans", "createdAt": "2023-11-27T08:16:32Z" } @@ -4819,7 +4819,7 @@ }, { "id": 32218, - "name": "이병헌", + "name": "차은우", "backgroundColor": "beige", "backgroundImageURL": null, "createdAt": "2023-07-22T22:33:51Z", @@ -4946,10 +4946,10 @@ { "id": 24988, "recipientId": 1341, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/423/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 64", + "content": "차은우님의 메세지 내용 64", "font": "Roboto", "createdAt": "2023-01-06T05:53:05Z" } @@ -5011,7 +5011,7 @@ }, { "id": 93438, - "name": "이병헌", + "name": "차은우", "backgroundColor": "blue", "backgroundImageURL": "https://picsum.photos/seed/93438/600/400", "createdAt": "2023-04-02T11:00:53Z", @@ -5030,10 +5030,10 @@ { "id": 6156, "recipientId": 93438, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/109/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 59", + "content": "차은우님의 메세지 내용 59", "font": "Noto Sans", "createdAt": "2023-01-24T10:30:39Z" }, @@ -5058,7 +5058,7 @@ }, { "id": 44334, - "name": "이병헌", + "name": "차은우", "backgroundColor": "blue", "backgroundImageURL": "https://picsum.photos/seed/44334/600/400", "createdAt": "2023-12-30T01:42:47Z", @@ -5152,7 +5152,7 @@ }, { "id": 44928, - "name": "이병헌", + "name": "차은우", "backgroundColor": "beige", "backgroundImageURL": null, "createdAt": "2023-11-24T12:12:26Z", @@ -5192,10 +5192,10 @@ { "id": 31761, "recipientId": 94539, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/62/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 53", + "content": "차은우님의 메세지 내용 53", "font": "Pretendard", "createdAt": "2023-04-17T18:23:36Z" }, @@ -5666,10 +5666,10 @@ { "id": 41596, "recipientId": 43809, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/439/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 36", + "content": "차은우님의 메세지 내용 36", "font": "Roboto", "createdAt": "2023-02-12T07:13:07Z" }, @@ -5778,10 +5778,10 @@ { "id": 62162, "recipientId": 62125, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/293/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 93", + "content": "차은우님의 메세지 내용 93", "font": "Roboto", "createdAt": "2023-04-29T23:05:56Z" } @@ -5872,10 +5872,10 @@ { "id": 91516, "recipientId": 58844, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/108/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 82", + "content": "차은우님의 메세지 내용 82", "font": "Pretendard", "createdAt": "2023-08-27T12:05:46Z" } @@ -5909,10 +5909,10 @@ { "id": 29903, "recipientId": 72437, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/106/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 40", + "content": "차은우님의 메세지 내용 40", "font": "Roboto", "createdAt": "2023-04-29T16:49:48Z" } @@ -5956,10 +5956,10 @@ { "id": 91691, "recipientId": 31124, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/461/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 53", + "content": "차은우님의 메세지 내용 53", "font": "Roboto", "createdAt": "2023-05-21T09:55:42Z" } @@ -5978,7 +5978,7 @@ }, { "id": 73111, - "name": "이병헌", + "name": "차은우", "backgroundColor": "blue", "backgroundImageURL": null, "createdAt": "2023-12-29T11:24:51Z", @@ -6034,10 +6034,10 @@ { "id": 2974, "recipientId": 44599, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/46/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 13", + "content": "차은우님의 메세지 내용 13", "font": "Roboto", "createdAt": "2023-11-11T07:56:34Z" }, @@ -6256,7 +6256,7 @@ }, { "id": 72332, - "name": "이병헌", + "name": "차은우", "backgroundColor": "purple", "backgroundImageURL": "https://picsum.photos/seed/72332/600/400", "createdAt": "2023-10-08T20:12:12Z", @@ -6359,10 +6359,10 @@ { "id": 47612, "recipientId": 6048, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/97/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 72", + "content": "차은우님의 메세지 내용 72", "font": "Pretendard", "createdAt": "2023-12-11T12:42:57Z" }, @@ -6416,10 +6416,10 @@ { "id": 54283, "recipientId": 7768, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/368/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 8", + "content": "차은우님의 메세지 내용 8", "font": "Nanum Gothic", "createdAt": "2023-02-19T15:25:55Z" }, @@ -6473,10 +6473,10 @@ { "id": 66344, "recipientId": 60032, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/444/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 47", + "content": "차은우님의 메세지 내용 47", "font": "Pretendard", "createdAt": "2023-07-26T07:54:55Z" } @@ -6806,10 +6806,10 @@ { "id": 48175, "recipientId": 96506, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/145/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 86", + "content": "차은우님의 메세지 내용 86", "font": "Pretendard", "createdAt": "2023-03-13T10:17:35Z" }, @@ -6971,10 +6971,10 @@ { "id": 11805, "recipientId": 10732, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/76/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 48", + "content": "차은우님의 메세지 내용 48", "font": "Nanum Gothic", "createdAt": "2023-12-29T05:06:21Z" } @@ -7063,10 +7063,10 @@ { "id": 94450, "recipientId": 64061, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/353/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 61", + "content": "차은우님의 메세지 내용 61", "font": "Pretendard", "createdAt": "2023-12-02T06:48:01Z" }, @@ -7091,7 +7091,7 @@ }, { "id": 15549, - "name": "이병헌", + "name": "차은우", "backgroundColor": "blue", "backgroundImageURL": null, "createdAt": "2023-12-13T10:07:11Z", @@ -7161,10 +7161,10 @@ { "id": 67124, "recipientId": 84213, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/482/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 81", + "content": "차은우님의 메세지 내용 81", "font": "Pretendard", "createdAt": "2023-04-16T14:42:59Z" }, @@ -7245,10 +7245,10 @@ { "id": 91701, "recipientId": 83558, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/169/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 97", + "content": "차은우님의 메세지 내용 97", "font": "Noto Sans", "createdAt": "2023-11-22T09:50:03Z" }, @@ -7347,10 +7347,10 @@ { "id": 86215, "recipientId": 1220, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/419/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 25", + "content": "차은우님의 메세지 내용 25", "font": "Pretendard", "createdAt": "2023-05-10T21:59:12Z" } @@ -7369,7 +7369,7 @@ }, { "id": 53959, - "name": "이병헌", + "name": "차은우", "backgroundColor": "blue", "backgroundImageURL": "https://picsum.photos/seed/53959/600/400", "createdAt": "2023-08-24T05:22:48Z", @@ -7398,10 +7398,10 @@ { "id": 59151, "recipientId": 53959, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/10/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 4", + "content": "차은우님의 메세지 내용 4", "font": "Nanum Gothic", "createdAt": "2023-03-11T07:04:18Z" } @@ -7471,7 +7471,7 @@ }, { "id": 51432, - "name": "이병헌", + "name": "차은우", "backgroundColor": "beige", "backgroundImageURL": "https://picsum.photos/seed/51432/600/400", "createdAt": "2023-11-07T07:07:37Z", @@ -7490,10 +7490,10 @@ { "id": 33808, "recipientId": 51432, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/478/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 8", + "content": "차은우님의 메세지 내용 8", "font": "Pretendard", "createdAt": "2023-04-04T10:06:15Z" }, @@ -7891,10 +7891,10 @@ { "id": 93059, "recipientId": 73798, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/252/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 99", + "content": "차은우님의 메세지 내용 99", "font": "Roboto", "createdAt": "2023-11-21T09:01:45Z" }, @@ -7993,10 +7993,10 @@ { "id": 33941, "recipientId": 3992, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/364/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 93", + "content": "차은우님의 메세지 내용 93", "font": "Pretendard", "createdAt": "2023-02-13T23:03:26Z" }, @@ -8087,10 +8087,10 @@ { "id": 89359, "recipientId": 63758, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/401/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 53", + "content": "차은우님의 메세지 내용 53", "font": "Roboto", "createdAt": "2023-05-10T19:04:15Z" }, @@ -8193,7 +8193,7 @@ }, { "id": 63096, - "name": "이병헌", + "name": "차은우", "backgroundColor": "blue", "backgroundImageURL": "https://picsum.photos/seed/63096/600/400", "createdAt": "2023-08-25T09:30:08Z", @@ -8202,10 +8202,10 @@ { "id": 72995, "recipientId": 63096, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/368/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 44", + "content": "차은우님의 메세지 내용 44", "font": "Pretendard", "createdAt": "2023-10-07T18:41:59Z" }, @@ -8253,10 +8253,10 @@ { "id": 44494, "recipientId": 13289, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/118/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 64", + "content": "차은우님의 메세지 내용 64", "font": "Nanum Gothic", "createdAt": "2024-01-29T16:37:33Z" }, @@ -8541,10 +8541,10 @@ { "id": 33150, "recipientId": 66190, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/26/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 47", + "content": "차은우님의 메세지 내용 47", "font": "Roboto", "createdAt": "2024-01-22T00:03:15Z" } @@ -8563,7 +8563,7 @@ }, { "id": 68635, - "name": "이병헌", + "name": "차은우", "backgroundColor": "beige", "backgroundImageURL": null, "createdAt": "2023-10-22T10:14:45Z", @@ -8619,10 +8619,10 @@ { "id": 8378, "recipientId": 52236, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/383/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 53", + "content": "차은우님의 메세지 내용 53", "font": "Pretendard", "createdAt": "2023-12-03T19:03:51Z" } @@ -8656,10 +8656,10 @@ { "id": 14027, "recipientId": 81115, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/400/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 48", + "content": "차은우님의 메세지 내용 48", "font": "Noto Sans", "createdAt": "2023-09-18T14:09:01Z" }, @@ -8862,10 +8862,10 @@ { "id": 16314, "recipientId": 60, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/345/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 52", + "content": "차은우님의 메세지 내용 52", "font": "Roboto", "createdAt": "2023-03-07T04:55:33Z" } @@ -8903,10 +8903,10 @@ { "id": 81467, "recipientId": 66554, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/487/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 17", + "content": "차은우님의 메세지 내용 17", "font": "Nanum Gothic", "createdAt": "2023-03-16T05:19:39Z" }, @@ -9083,10 +9083,10 @@ { "id": 19962, "recipientId": 31459, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/80/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 11", + "content": "차은우님의 메세지 내용 11", "font": "Nanum Gothic", "createdAt": "2023-11-26T04:31:20Z" } @@ -9269,10 +9269,10 @@ { "id": 24156, "recipientId": 41885, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/360/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 14", + "content": "차은우님의 메세지 내용 14", "font": "Noto Sans", "createdAt": "2023-07-13T21:35:18Z" }, @@ -9599,20 +9599,20 @@ { "id": 86564, "recipientId": 46642, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/36/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 78", + "content": "차은우님의 메세지 내용 78", "font": "Noto Sans", "createdAt": "2023-09-23T23:48:17Z" }, { "id": 46880, "recipientId": 46642, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/453/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 92", + "content": "차은우님의 메세지 내용 92", "font": "Noto Sans", "createdAt": "2023-06-07T09:44:08Z" }, @@ -9688,7 +9688,7 @@ }, { "id": 93469, - "name": "이병헌", + "name": "차은우", "backgroundColor": "beige", "backgroundImageURL": "https://picsum.photos/seed/93469/600/400", "createdAt": "2023-08-05T08:37:01Z", @@ -9743,7 +9743,7 @@ }, { "id": 45950, - "name": "이병헌", + "name": "차은우", "backgroundColor": "green", "backgroundImageURL": "https://picsum.photos/seed/45950/600/400", "createdAt": "2023-04-24T21:39:46Z", @@ -10156,10 +10156,10 @@ { "id": 46241, "recipientId": 30047, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/397/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 64", + "content": "차은우님의 메세지 내용 64", "font": "Roboto", "createdAt": "2023-04-12T04:50:45Z" }, @@ -10433,7 +10433,7 @@ }, { "id": 44091, - "name": "이병헌", + "name": "차은우", "backgroundColor": "blue", "backgroundImageURL": "https://picsum.photos/seed/44091/600/400", "createdAt": "2023-06-17T19:51:45Z", @@ -10871,10 +10871,10 @@ { "id": 58525, "recipientId": 62965, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/103/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 1", + "content": "차은우님의 메세지 내용 1", "font": "Noto Sans", "createdAt": "2023-04-24T14:22:46Z" }, @@ -10908,10 +10908,10 @@ { "id": 86114, "recipientId": 61614, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/1/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 48", + "content": "차은우님의 메세지 내용 48", "font": "Noto Sans", "createdAt": "2023-11-16T04:24:55Z" }, @@ -10997,7 +10997,7 @@ }, { "id": 31146, - "name": "이병헌", + "name": "차은우", "backgroundColor": "green", "backgroundImageURL": null, "createdAt": "2023-09-27T13:42:38Z", @@ -11033,10 +11033,10 @@ { "id": 80875, "recipientId": 99123, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/42/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 14", + "content": "차은우님의 메세지 내용 14", "font": "Roboto", "createdAt": "2023-11-30T19:44:40Z" }, @@ -11159,10 +11159,10 @@ { "id": 9237, "recipientId": 16143, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/437/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 14", + "content": "차은우님의 메세지 내용 14", "font": "Pretendard", "createdAt": "2023-03-17T21:44:08Z" } @@ -11253,10 +11253,10 @@ { "id": 31892, "recipientId": 98422, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/8/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 43", + "content": "차은우님의 메세지 내용 43", "font": "Pretendard", "createdAt": "2023-09-02T03:23:20Z" } @@ -11294,10 +11294,10 @@ { "id": 85445, "recipientId": 53532, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/363/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 51", + "content": "차은우님의 메세지 내용 51", "font": "Noto Sans", "createdAt": "2023-09-23T11:29:56Z" }, @@ -11331,10 +11331,10 @@ { "id": 86518, "recipientId": 93792, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/204/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 9", + "content": "차은우님의 메세지 내용 9", "font": "Roboto", "createdAt": "2023-01-22T13:44:09Z" }, @@ -11351,10 +11351,10 @@ { "id": 9752, "recipientId": 93792, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/171/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 68", + "content": "차은우님의 메세지 내용 68", "font": "Roboto", "createdAt": "2023-02-15T23:39:35Z" } @@ -11406,10 +11406,10 @@ { "id": 84648, "recipientId": 12242, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/112/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 4", + "content": "차은우님의 메세지 내용 4", "font": "Pretendard", "createdAt": "2024-01-06T11:37:10Z" } @@ -11492,10 +11492,10 @@ { "id": 35816, "recipientId": 76148, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/488/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 96", + "content": "차은우님의 메세지 내용 96", "font": "Nanum Gothic", "createdAt": "2023-04-09T14:21:56Z" } @@ -11556,10 +11556,10 @@ { "id": 76780, "recipientId": 38642, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/253/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 24", + "content": "차은우님의 메세지 내용 24", "font": "Nanum Gothic", "createdAt": "2023-07-12T11:54:03Z" }, @@ -11728,10 +11728,10 @@ { "id": 78207, "recipientId": 55884, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/155/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 87", + "content": "차은우님의 메세지 내용 87", "font": "Pretendard", "createdAt": "2023-06-01T07:21:37Z" }, @@ -11783,10 +11783,10 @@ { "id": 2300, "recipientId": 65809, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/358/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 60", + "content": "차은우님의 메세지 내용 60", "font": "Roboto", "createdAt": "2023-05-12T09:25:19Z" }, @@ -11830,10 +11830,10 @@ { "id": 12155, "recipientId": 47549, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/247/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 80", + "content": "차은우님의 메세지 내용 80", "font": "Pretendard", "createdAt": "2023-03-09T22:19:14Z" }, @@ -11897,10 +11897,10 @@ { "id": 64811, "recipientId": 7135, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/184/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 9", + "content": "차은우님의 메세지 내용 9", "font": "Roboto", "createdAt": "2023-10-17T00:36:13Z" } @@ -12332,10 +12332,10 @@ { "id": 65322, "recipientId": 21977, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/156/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 79", + "content": "차은우님의 메세지 내용 79", "font": "Nanum Gothic", "createdAt": "2023-09-13T04:30:55Z" } @@ -12367,10 +12367,10 @@ { "id": 37649, "recipientId": 67245, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/160/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 84", + "content": "차은우님의 메세지 내용 84", "font": "Roboto", "createdAt": "2023-05-09T12:36:18Z" }, @@ -12741,10 +12741,10 @@ { "id": 7778, "recipientId": 37498, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/202/200/200", "relationship": "가족", - "content": "이병헌님의 메세지 내용 24", + "content": "차은우님의 메세지 내용 24", "font": "Pretendard", "createdAt": "2023-12-27T07:03:22Z" }, @@ -12910,7 +12910,7 @@ }, { "id": 12700, - "name": "이병헌", + "name": "차은우", "backgroundColor": "purple", "backgroundImageURL": null, "createdAt": "2023-08-18T22:43:12Z", @@ -12939,10 +12939,10 @@ { "id": 4746, "recipientId": 12700, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/260/200/200", "relationship": "친구", - "content": "이병헌님의 메세지 내용 44", + "content": "차은우님의 메세지 내용 44", "font": "Noto Sans", "createdAt": "2023-02-17T03:59:23Z" } @@ -13160,10 +13160,10 @@ { "id": 47661, "recipientId": 56031, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/395/200/200", "relationship": "동료", - "content": "이병헌님의 메세지 내용 62", + "content": "차은우님의 메세지 내용 62", "font": "Nanum Gothic", "createdAt": "2023-08-20T17:27:35Z" }, @@ -13925,7 +13925,7 @@ }, { "id": 31249, - "name": "이병헌", + "name": "차은우", "backgroundColor": "blue", "backgroundImageURL": null, "createdAt": "2023-05-16T17:41:45Z", @@ -13944,10 +13944,10 @@ { "id": 54855, "recipientId": 31249, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/188/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 84", + "content": "차은우님의 메세지 내용 84", "font": "Pretendard", "createdAt": "2023-07-01T14:34:04Z" } @@ -13966,7 +13966,7 @@ }, { "id": 87008, - "name": "이병헌", + "name": "차은우", "backgroundColor": "purple", "backgroundImageURL": null, "createdAt": "2023-05-31T18:24:49Z", @@ -13985,10 +13985,10 @@ { "id": 29069, "recipientId": 87008, - "sender": "이병헌", + "sender": "차은우", "profileImageURL": "https://picsum.photos/id/25/200/200", "relationship": "지인", - "content": "이병헌님의 메세지 내용 19", + "content": "차은우님의 메세지 내용 19", "font": "Roboto", "createdAt": "2024-01-14T03:59:30Z" }, diff --git a/src/features/rolling-paper/components/rolling-paper-list.jsx b/src/features/rolling-paper/components/rolling-paper-list.jsx index b826b4e..f411023 100644 --- a/src/features/rolling-paper/components/rolling-paper-list.jsx +++ b/src/features/rolling-paper/components/rolling-paper-list.jsx @@ -1,7 +1,10 @@ import ArrowButton from "../../../components/button/arrow-button"; import ARROW_BUTTON_DIRECTION from "../../../components/button/arrow-button-direction"; import { media } from "../../../utils/media"; -import styled, { css } from "styled-components"; +import React, { useEffect, useState } from "react"; +import styled, { keyframes, css } from "styled-components"; +import Avatar from "../../../components/avatar/avatar"; +import AVATAR_SIZE from "../../../components/avatar/avatar-size"; const backgroundColors = { beige: "#FFE2AD", @@ -16,14 +19,15 @@ const CardContainer = styled.div` gap: 20px; width: fit-content; font-family: Pretendard; - position: relative; + padding: 0; ${media.tablet} { display: flex; gap: 16px; overflow-x: auto; scroll-snap-type: x mandatory; + scroll-padding: 24px; scrollbar-width: none; -ms-overflow-style: none; @@ -42,6 +46,10 @@ const CardContainer = styled.div` max-width: 767px; width: 100%; padding: 0 20px; + + & > div { + flex: 0 0 208px; + } } `; @@ -53,21 +61,22 @@ const CardItem = styled.div` padding: 30px 24px 20px 24px; border: 1px solid rgba(0, 0, 0, 0.1); box-shadow: 0px 2px 12px 0px rgba(0, 0, 0, 0.08); - + z-index: 0; display: flex; gap: 12px; flex-direction: column; - - background: ${(props) => - props.$backgroundImageURL - ? `linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4)), url(${props.$backgroundImageURL}) center/cover no-repeat` - : backgroundColors[props.$backgroundColor] || "white"}; - position: relative; overflow: hidden; + background: ${(props) => { + if (props.$backgroundImageURL) { + return `linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4)), url(${props.$backgroundImageURL}) center/cover no-repeat`; + } + return backgroundColors[props.$backgroundColor] || "white"; + }}; ${media.tablet} { flex-shrink: 0; + scroll-snap-align: start; } ${media.mobile} { @@ -76,11 +85,9 @@ const CardItem = styled.div` padding: 30px 15px 20px 15px; } - /* 배경 도형 */ &::before { content: ""; position: absolute; - z-index: 0; ${({ $backgroundImageURL, $backgroundColor }) => { return $backgroundImageURL ? "" : polygonStyle[$backgroundColor]; }} @@ -88,7 +95,6 @@ const CardItem = styled.div` & > * { position: relative; - z-index: 1; } `; @@ -154,22 +160,26 @@ const CardTitle = styled.h2` font-size: 24px; font-weight: 700; color: ${(props) => props.$fontColor || "black"}; + width: 225px; + + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; + text-overflow: ellipsis; + + ${media.mobile} { + width: 175px; + font-size: 18px; + } `; const ProfileContainer = styled.div` display: flex; `; -const CardProfile = styled.img` - height: 28px; - width: 28px; - border-radius: 50%; - border: 1px solid #ffffff; - - margin-left: -12px; - &:first-child { - margin-left: 0; - } +const CardProfile = styled.div` + margin-left: ${($messageIndex) => ($messageIndex === 0 ? "0" : "-12px")}; `; const OverProfile = styled.div` @@ -268,7 +278,119 @@ const PreviewButtonWrapper = styled.div` z-index: 10; `; +const spin = keyframes` + 0% { + transform: rotate(0deg); + } + 100% { + transform: rotate(360deg); + } +`; + +const Spinner = styled.div` + width: ${(props) => props.size || "40px"}; + height: ${(props) => props.size || "40px"}; + border: ${(props) => props.thickness || "4px"} solid + ${(props) => props.trackColor || "#f3f3f313"}; + border-top: ${(props) => props.thickness || "4px"} solid + var(--color-purple-700); + border-radius: 50%; + animation: ${spin} 1s linear infinite; + + ${(props) => + props.centered && + css` + margin: 0 auto; + display: block; + `} + + position: absolute; + justify-self: anchor-center; + align-self: anchor-center; +`; + function RollingPaperList({ cardData, totalPages, currentPage, onTurnCards }) { + const [imageLoadStates, setImageLoadStates] = useState({}); + const [profileLoadStates, setProfileLoadStates] = useState({}); + + useEffect(() => { + const loadImages = async () => { + const loadStates = {}; + + cardData.forEach((card) => { + if (card.backgroundImageURL) { + loadStates[card.id] = false; + } + }); + + setImageLoadStates(loadStates); + + const imagePromises = cardData.map((card) => { + if (!card.backgroundImageURL) return Promise.resolve(); + + return new Promise((resolve) => { + const img = new Image(); + img.onload = () => { + setImageLoadStates((prev) => ({ + ...prev, + [card.id]: true, + })); + resolve(); + }; + img.onerror = () => { + setImageLoadStates((prev) => ({ + ...prev, + [card.id]: false, + })); + resolve(); + }; + img.src = card.backgroundImageURL; + }); + }); + + await Promise.all(imagePromises); + }; + + loadImages(); + }, [cardData]); + + useEffect(() => { + const loadProfileImages = async () => { + const initialStates = {}; + cardData.forEach((card) => { + card.recentMessages.slice(0, 3).forEach((msg) => { + initialStates[msg.id] = false; + }); + }); + setProfileLoadStates(initialStates); + + const promises = []; + cardData.forEach((card) => { + card.recentMessages.slice(0, 3).forEach((msg) => { + if (!msg.profileImageURL) return; + promises.push( + new Promise((resolve) => { + const img = new Image(); + img.src = msg.profileImageURL; + img.onload = () => { + setProfileLoadStates((prev) => ({ ...prev, [msg.id]: true })); + resolve(); + }; + img.onerror = () => { + setProfileLoadStates((prev) => ({ ...prev, [msg.id]: false })); + resolve(); + }; + }) + ); + }); + }); + + await Promise.all(promises); + }; + + loadProfileImages(); + }, [cardData]); + return ( {cardData.map((card) => ( @@ -277,19 +399,30 @@ function RollingPaperList({ cardData, totalPages, currentPage, onTurnCards }) { $backgroundColor={card.backgroundColor} $backgroundImageURL={card.backgroundImageURL} > + {card.backgroundImageURL && !imageLoadStates[card.id] && ( + + )} To. {card.name} - {card.recentMessages.slice(0, 3).map((messagecard, index) => ( - - ))} + {card.recentMessages + .slice(0, 3) + .map((messageCard, messageIndex) => ( + + + + ))} {card.messageCount > 3 && ( +{card.messageCount - 3} diff --git a/src/pages/rolling-paper-list-page.jsx b/src/pages/rolling-paper-list-page.jsx index 49b3f4c..8c1da0b 100644 --- a/src/pages/rolling-paper-list-page.jsx +++ b/src/pages/rolling-paper-list-page.jsx @@ -23,6 +23,8 @@ const CardSection = styled.section` const CardTitle = styled.h2` text-align: left; + font-size: 24px; + font-weight: 700; ${media.tablet} { margin-left: 24px; @@ -30,6 +32,8 @@ const CardTitle = styled.h2` ${media.mobile} { margin-left: 20px; + font-size: 20px; + font-weight: 600; } `; @@ -39,12 +43,13 @@ const MakingButton = styled(PrimaryButton)` padding: 14px 60px; ${media.tablet} { - position: absolute; - bottom: 24px; justify-self: anchor-center; margin-left: 24px; margin-right: 24px; width: calc(100% - 48px); + padding: 14px 20px; + position: relative; + bottom: 24px; } `; From 850356385cc46c6143e01bf8c85600f0c0f9f4ac Mon Sep 17 00:00:00 2001 From: luli Date: Sat, 23 Aug 2025 08:39:10 +0900 Subject: [PATCH 234/253] =?UTF-8?q?[#80]=20=EC=B9=B4=EB=93=9C=EB=B0=B0?= =?UTF-8?q?=EA=B2=BD=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EA=B3=B5=ED=86=B5=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8,=20=EC=8A=A4=ED=94=BC?= =?UTF-8?q?=EB=84=88=20=EA=B3=B5=ED=86=B5=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8,=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EB=A1=9C=EB=94=A9?= =?UTF-8?q?=EC=B2=B4=ED=81=AC=20custom=20hook?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 카드배경이미지 공통 컴포넌트, 스피너 공통 컴포넌트, 이미지 로딩체크 custom hook --- ...lingPaperList.js => rolling-paper-list.js} | 0 .../components/rolling-paper-list.jsx | 187 ++++-------------- src/pages/rolling-paper-list-page.jsx | 34 ++-- 3 files changed, 64 insertions(+), 157 deletions(-) rename src/features/rolling-paper/api/{rollingPaperList.js => rolling-paper-list.js} (100%) diff --git a/src/features/rolling-paper/api/rollingPaperList.js b/src/features/rolling-paper/api/rolling-paper-list.js similarity index 100% rename from src/features/rolling-paper/api/rollingPaperList.js rename to src/features/rolling-paper/api/rolling-paper-list.js diff --git a/src/features/rolling-paper/components/rolling-paper-list.jsx b/src/features/rolling-paper/components/rolling-paper-list.jsx index f411023..9bc6771 100644 --- a/src/features/rolling-paper/components/rolling-paper-list.jsx +++ b/src/features/rolling-paper/components/rolling-paper-list.jsx @@ -1,17 +1,12 @@ import ArrowButton from "../../../components/button/arrow-button"; import ARROW_BUTTON_DIRECTION from "../../../components/button/arrow-button-direction"; import { media } from "../../../utils/media"; -import React, { useEffect, useState } from "react"; -import styled, { keyframes, css } from "styled-components"; +import React, { useMemo } from "react"; +import styled, { css } from "styled-components"; import Avatar from "../../../components/avatar/avatar"; import AVATAR_SIZE from "../../../components/avatar/avatar-size"; - -const backgroundColors = { - beige: "#FFE2AD", - purple: "#ECD9FF", - green: "#D0F5C3", - blue: "#B1E4FF", -}; +import CardBackground from "../../../components/image/card-background"; +import { useImageListLodeChecker } from "../../../hooks/use-image-loader"; const CardContainer = styled.div` display: grid; @@ -53,9 +48,9 @@ const CardContainer = styled.div` } `; -const CardItem = styled.div` +const CardItem = styled(CardBackground)` width: 275px; - min-height: 260px; + height: 260px; border-radius: 16px; text-align: left; padding: 30px 24px 20px 24px; @@ -67,12 +62,8 @@ const CardItem = styled.div` flex-direction: column; position: relative; overflow: hidden; - background: ${(props) => { - if (props.$backgroundImageURL) { - return `linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4)), url(${props.$backgroundImageURL}) center/cover no-repeat`; - } - return backgroundColors[props.$backgroundColor] || "white"; - }}; + + justify-content: space-between; ${media.tablet} { flex-shrink: 0; @@ -82,28 +73,27 @@ const CardItem = styled.div` ${media.mobile} { width: 208px; height: 232px; - padding: 30px 15px 20px 15px; + padding: 25px 18px 15px 18px; + gap: 8px; } &::before { content: ""; position: absolute; - ${({ $backgroundImageURL, $backgroundColor }) => { - return $backgroundImageURL ? "" : polygonStyle[$backgroundColor]; + ${({ $backgroundImageURLForStyle, $backgroundColorForStyle }) => { + return $backgroundImageURLForStyle + ? "" + : polygonStyle[$backgroundColorForStyle]; }} } - - & > * { - position: relative; - } `; const ellipseStyle = css` width: 336px; height: 169px; - background-color: ${({ $backgroundColor }) => - $backgroundColor === "purple" - ? "rgba(220,185,255,0.4)" + background-color: ${({ $backgroundColorForStyle }) => + $backgroundColorForStyle === "purple" + ? "rgba(220, 185, 255, 0.4)" : "rgba(155, 226, 130, 0.3)"}; border-radius: 90.5px; top: 124px; @@ -179,7 +169,7 @@ const ProfileContainer = styled.div` `; const CardProfile = styled.div` - margin-left: ${($messageIndex) => ($messageIndex === 0 ? "0" : "-12px")}; + margin-left: ${({ $messageIndex }) => ($messageIndex === 0 ? "0" : "-12px")}; `; const OverProfile = styled.div` @@ -207,13 +197,17 @@ const MessageCountText = styled.span` const CardEmojiBox = styled.div` border-top: 1px solid rgba(0, 0, 0, 0.1); - padding-top: 17px; + padding-top: 13px; margin-top: auto; display: flex; flex-wrap: wrap; row-gap: 5px; z-index: 2; + + ${media.mobile} { + padding-top: 10px; + } `; const CardEmoji = styled.span` @@ -278,130 +272,31 @@ const PreviewButtonWrapper = styled.div` z-index: 10; `; -const spin = keyframes` - 0% { - transform: rotate(0deg); - } - 100% { - transform: rotate(360deg); - } -`; - -const Spinner = styled.div` - width: ${(props) => props.size || "40px"}; - height: ${(props) => props.size || "40px"}; - border: ${(props) => props.thickness || "4px"} solid - ${(props) => props.trackColor || "#f3f3f313"}; - border-top: ${(props) => props.thickness || "4px"} solid - var(--color-purple-700); - border-radius: 50%; - animation: ${spin} 1s linear infinite; - - ${(props) => - props.centered && - css` - margin: 0 auto; - display: block; - `} - - position: absolute; - justify-self: anchor-center; - align-self: anchor-center; -`; - function RollingPaperList({ cardData, totalPages, currentPage, onTurnCards }) { - const [imageLoadStates, setImageLoadStates] = useState({}); - const [profileLoadStates, setProfileLoadStates] = useState({}); - - useEffect(() => { - const loadImages = async () => { - const loadStates = {}; - - cardData.forEach((card) => { - if (card.backgroundImageURL) { - loadStates[card.id] = false; - } - }); - - setImageLoadStates(loadStates); - - const imagePromises = cardData.map((card) => { - if (!card.backgroundImageURL) return Promise.resolve(); - - return new Promise((resolve) => { - const img = new Image(); - img.onload = () => { - setImageLoadStates((prev) => ({ - ...prev, - [card.id]: true, - })); - resolve(); - }; - img.onerror = () => { - setImageLoadStates((prev) => ({ - ...prev, - [card.id]: false, - })); - resolve(); - }; - img.src = card.backgroundImageURL; - }); - }); - - await Promise.all(imagePromises); - }; - - loadImages(); - }, [cardData]); - - useEffect(() => { - const loadProfileImages = async () => { - const initialStates = {}; - cardData.forEach((card) => { - card.recentMessages.slice(0, 3).forEach((msg) => { - initialStates[msg.id] = false; - }); - }); - setProfileLoadStates(initialStates); - - const promises = []; - cardData.forEach((card) => { - card.recentMessages.slice(0, 3).forEach((msg) => { - if (!msg.profileImageURL) return; - promises.push( - new Promise((resolve) => { - const img = new Image(); - img.src = msg.profileImageURL; - img.onload = () => { - setProfileLoadStates((prev) => ({ ...prev, [msg.id]: true })); - resolve(); - }; - img.onerror = () => { - setProfileLoadStates((prev) => ({ ...prev, [msg.id]: false })); - resolve(); - }; - }) - ); - }); - }); - - await Promise.all(promises); - }; - - loadProfileImages(); - }, [cardData]); + const profileImages = useMemo( + () => + cardData.flatMap((card) => + card.recentMessages.slice(0, 3).map((msg) => ({ + id: msg.id, + backgroundImageURL: msg.profileImageURL, + })) + ), + [cardData] + ); + + const profileLoadStates = useImageListLodeChecker(profileImages); return ( {cardData.map((card) => ( - {card.backgroundImageURL && !imageLoadStates[card.id] && ( - - )} @@ -411,7 +306,7 @@ function RollingPaperList({ cardData, totalPages, currentPage, onTurnCards }) { {card.recentMessages .slice(0, 3) .map((messageCard, messageIndex) => ( - + -
+ 인기 롤링 페이퍼 🔥 handleTurnCards(direction, "recent")} /> -
- + + + + ); } From f521144e6c8792f95db07b89a1efdd68e6c6014a Mon Sep 17 00:00:00 2001 From: luli Date: Sat, 23 Aug 2025 15:14:46 +0900 Subject: [PATCH 235/253] =?UTF-8?q?[#80]=20=EC=BD=94=EB=93=9C=20=EC=98=A4?= =?UTF-8?q?=ED=83=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 코드 오타 수정 --- src/pages/rolling-paper-list-page.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/rolling-paper-list-page.jsx b/src/pages/rolling-paper-list-page.jsx index 2875493..c9c3a97 100644 --- a/src/pages/rolling-paper-list-page.jsx +++ b/src/pages/rolling-paper-list-page.jsx @@ -1,8 +1,8 @@ import { PrimaryButton } from "../components/button/button"; import BUTTON_SIZE from "../components/button/button-size"; -import { useNavigate } from "react-router"; +import { getRollingPaperList } from "../features/rolling-paper/api/rolling-paper-list"; import React, { useEffect, useState, useMemo } from "react"; -import { getRollingPaperList } from "../features/rolling-paper/api/rollingPaperList"; +import { useNavigate } from "react-router"; import styled from "styled-components"; import RollingPaperList from "../features/rolling-paper/components/rolling-paper-list"; import { media } from "../utils/media"; From 8d38a6bd3a9f5273cd260f3f0433cae40ec0ea84 Mon Sep 17 00:00:00 2001 From: luli Date: Sat, 23 Aug 2025 15:15:10 +0900 Subject: [PATCH 236/253] =?UTF-8?q?[#80]=20=EC=84=9C=EB=B2=84=20api=20?= =?UTF-8?q?=EC=97=B0=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit api 연동 --- .../components/rolling-paper-list.jsx | 8 +++-- src/pages/rolling-paper-list-page.jsx | 32 +++++++++++-------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/features/rolling-paper/components/rolling-paper-list.jsx b/src/features/rolling-paper/components/rolling-paper-list.jsx index 9bc6771..f0ede42 100644 --- a/src/features/rolling-paper/components/rolling-paper-list.jsx +++ b/src/features/rolling-paper/components/rolling-paper-list.jsx @@ -196,7 +196,11 @@ const MessageCountText = styled.span` `; const CardEmojiBox = styled.div` - border-top: 1px solid rgba(0, 0, 0, 0.1); + ${(props) => + props.$haveEmoji && + ` + border-top: 1px solid rgba(0, 0, 0, 0.1); + `} padding-top: 13px; margin-top: auto; @@ -329,7 +333,7 @@ function RollingPaperList({ cardData, totalPages, currentPage, onTurnCards }) { > {card.messageCount}명이 작성했어요! - + 0}> {card.topReactions.map((emoji, index) => { const countLength = emoji.count.toString().length; const isLongCount = countLength > 2; diff --git a/src/pages/rolling-paper-list-page.jsx b/src/pages/rolling-paper-list-page.jsx index c9c3a97..425f9cc 100644 --- a/src/pages/rolling-paper-list-page.jsx +++ b/src/pages/rolling-paper-list-page.jsx @@ -1,12 +1,12 @@ import { PrimaryButton } from "../components/button/button"; import BUTTON_SIZE from "../components/button/button-size"; -import { getRollingPaperList } from "../features/rolling-paper/api/rolling-paper-list"; import React, { useEffect, useState, useMemo } from "react"; import { useNavigate } from "react-router"; import styled from "styled-components"; import RollingPaperList from "../features/rolling-paper/components/rolling-paper-list"; import { media } from "../utils/media"; import { useMedia } from "../hooks/use-media"; +import { apiClient } from "../api/client"; const TopContainer = styled.div` text-align: center; @@ -75,7 +75,7 @@ function getCachedImage(url) { function ShowMessageList() { const navigate = useNavigate(); - const [testData, setTestData] = useState([]); + const [recipientsData, setRecipientsData] = useState([]); const [popularDataList, setPopularDataList] = useState([]); const [recentDataList, setRecentDataList] = useState([]); const [popularCurrentPage, setPopularCurrentPage] = useState(0); @@ -92,33 +92,37 @@ function ShowMessageList() { }; useEffect(() => { - isDesktop ? setCardCount(4) : setCardCount(null); - }, [isDesktop]); - - - useEffect(() => { - getRollingPaperList().then(setTestData); + apiClient + .get("/recipients/") + .then((res) => { + setRecipientsData(res.data.results); + }) + .catch((err) => { + console.error("오류:", err); + }); }, []); useEffect(() => { - testData.forEach((data) => { + recipientsData.forEach((data) => { getCachedImage(data.imageURL); }); - }, [testData]); + }, [recipientsData]); useEffect(() => { - const sortedPopular = testData + const sortedPopular = recipientsData .slice() .sort((a, b) => b.messageCount - a.messageCount); setPopularDataList(sortedPopular); - const sortedRecent = testData + const sortedRecent = recipientsData .slice() .sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt)); setRecentDataList(sortedRecent); - }, [testData]); + }, [recipientsData]); - const totalPages = cardCount ? Math.ceil(testData.length / cardCount) : 1; + const totalPages = cardCount + ? Math.ceil(recipientsData.length / cardCount) + : 1; const popularShowCards = useMemo(() => { if (!cardCount) return popularDataList; From 655cc2da4313fd7baa0d52bae9a83938d899dd7d Mon Sep 17 00:00:00 2001 From: luli Date: Sat, 23 Aug 2025 14:51:14 +0900 Subject: [PATCH 237/253] =?UTF-8?q?[#80]=20=EB=AA=A8=EB=B0=94=EC=9D=BC=20?= =?UTF-8?q?=EC=B9=B4=EB=93=9C=20padding=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 모바일 카드 padding수정 --- src/features/rolling-paper/components/rolling-paper-list.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/rolling-paper/components/rolling-paper-list.jsx b/src/features/rolling-paper/components/rolling-paper-list.jsx index f0ede42..d273e32 100644 --- a/src/features/rolling-paper/components/rolling-paper-list.jsx +++ b/src/features/rolling-paper/components/rolling-paper-list.jsx @@ -73,7 +73,7 @@ const CardItem = styled(CardBackground)` ${media.mobile} { width: 208px; height: 232px; - padding: 25px 18px 15px 18px; + padding: 25px 15px 15px 15px; gap: 8px; } From 23a60c812eaf7404e0c4e70d52c45b79d93bae5f Mon Sep 17 00:00:00 2001 From: luli Date: Sat, 23 Aug 2025 15:19:18 +0900 Subject: [PATCH 238/253] =?UTF-8?q?[#80]=20=EB=B3=91=ED=95=A9=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 병합오류 해결 --- src/app.jsx | 2 +- src/components/image/card-background.jsx | 55 +++++++++++++++++++ src/components/loading/loading.jsx | 29 ++++++++++ src/hooks/use-image-loader.jsx | 67 ++++++++++++++++++++++++ 4 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 src/components/image/card-background.jsx create mode 100644 src/components/loading/loading.jsx create mode 100644 src/hooks/use-image-loader.jsx diff --git a/src/app.jsx b/src/app.jsx index b0509de..e056436 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -57,7 +57,7 @@ function App() { /> - } /> + } /> } /> diff --git a/src/components/image/card-background.jsx b/src/components/image/card-background.jsx new file mode 100644 index 0000000..6f9cb15 --- /dev/null +++ b/src/components/image/card-background.jsx @@ -0,0 +1,55 @@ +import React from "react"; +import styled from "styled-components"; +import SpinnerOverlay from "../loading/loading"; +import { useImageLodeChecker } from "../../hooks/use-image-loader"; + +const backgroundColors = { + beige: "#FFE2AD", + purple: "#ECD9FF", + green: "#D0F5C3", + blue: "#B1E4FF", +}; + +const getBackground = ($imageURL, $color, $overlayOn) => { + return $imageURL + ? `${ + $overlayOn ? "linear-gradient(rgba(0,0,0,0.4), rgba(0,0,0,0.4)), " : "" + }url(${$imageURL}) center/cover no-repeat` + : backgroundColors[$color] || "white"; +}; + +const CardContainer = styled.div` + position: relative; + width: 100%; + height: 100%; +`; + +const CardImage = styled.div` + background: ${({ $imageURL, $color, $overlayOn }) => + getBackground($imageURL, $color, $overlayOn)}; + z-index: 0; +`; + +const CardBackground = ({ + backgroundImageURL, + backgroundColor, + overlayOn = false, + ...props +}) => { + const noNeedToLoad = !backgroundImageURL ? true : false; + const isImageLoaded = useImageLodeChecker(backgroundImageURL, noNeedToLoad); + + return ( + + {!isImageLoaded && } + + + ); +}; + +export default CardBackground; diff --git a/src/components/loading/loading.jsx b/src/components/loading/loading.jsx new file mode 100644 index 0000000..bca7802 --- /dev/null +++ b/src/components/loading/loading.jsx @@ -0,0 +1,29 @@ +import React from "react"; +import styled, { keyframes } from "styled-components"; + +const spin = keyframes` + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +`; + +const Spinner = styled.div` + width: ${({ size }) => size || "50px"}; + height: ${({ size }) => size || "50px"}; + border: ${({ thickness }) => thickness || "4px"} solid #f3f3f313; + border-top: ${({ thickness }) => thickness || "4px"} solid + var(--color-purple-700); + + border-radius: 50%; + animation: ${spin} 1s linear infinite; + position: absolute; + justify-self: anchor-center; + align-self: anchor-center; + transform: translate(-50%, -50%); + z-index: 9999; +`; + +const SpinnerOverlay = ({ size, thickness }) => { + return ; +}; + +export default SpinnerOverlay; diff --git a/src/hooks/use-image-loader.jsx b/src/hooks/use-image-loader.jsx new file mode 100644 index 0000000..8a58963 --- /dev/null +++ b/src/hooks/use-image-loader.jsx @@ -0,0 +1,67 @@ +import { useState, useEffect } from "react"; + +function useImageLodeChecker(imageURL, noNeedToLoad = false) { + const [isLode, setIsLode] = useState(!imageURL || noNeedToLoad); + + useEffect(() => { + if (noNeedToLoad || !imageURL) return; + const img = new Image(); + img.src = imageURL; + + const handleLoad = () => setIsLode(true); + const handleError = () => setIsLode(false); + + img.addEventListener("load", handleLoad); + img.addEventListener("error", handleError); + + return () => { + img.removeEventListener("load", handleLoad); + img.removeEventListener("error", handleError); + }; + }, [imageURL, noNeedToLoad]); + + return isLode; +} + +function useImageListLodeChecker(imageList = []) { + const [imageLoadStates, setImageLoadStates] = useState({}); + + useEffect(() => { + if (!imageList.length) return; + + setImageLoadStates((prev) => { + const nextStates = { ...prev }; + imageList.forEach(({ id }) => { + if (nextStates[id] === undefined) { + nextStates[id] = false; + } + }); + return nextStates; + }); + + imageList.forEach(({ id, backgroundImageURL }) => { + setImageLoadStates((prev) => { + if (prev[id]) return prev; + + if (!backgroundImageURL) { + return { ...prev, [id]: false }; + } + + const img = new Image(); + img.src = backgroundImageURL; + img.onload = () => { + setImageLoadStates((p) => ({ ...p, [id]: true })); + }; + img.onerror = () => { + setImageLoadStates((p) => ({ ...p, [id]: false })); + }; + + return prev; + }); + }); + }, [imageList]); + + return imageLoadStates; +} + +export { useImageLodeChecker, useImageListLodeChecker }; From 48633ce8d299029a9562e6fadc802252ef9c1f83 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 23 Aug 2025 12:45:25 +0900 Subject: [PATCH 239/253] =?UTF-8?q?feat=20[#83]=20Red=20=EC=83=89=EC=83=81?= =?UTF-8?q?=20palette=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 디자인 시안과 별개로 임의의 red color palette를 추가해서 사용합니다. --- src/components/color/colors.js | 3 +++ src/styles/colors.css | 20 +++++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/components/color/colors.js b/src/components/color/colors.js index 4c876bc..3560f9c 100644 --- a/src/components/color/colors.js +++ b/src/components/color/colors.js @@ -18,6 +18,9 @@ const Colors = { gray: function (value) { return `var(--color-gray-${shade({ value })})`; }, + red: function (value) { + return `var(--color-red-${shade({ value })})`; + }, error: "var(--color-error)", surface: "var(--color-surface)", }; diff --git a/src/styles/colors.css b/src/styles/colors.css index 608d4f9..91e7602 100644 --- a/src/styles/colors.css +++ b/src/styles/colors.css @@ -1,9 +1,4 @@ :root { - /* Semantics */ - - --color-error: #dc3a3a; - --color-surface: #f6f8ff; - /* Palette */ --color-purple-100: #f8f0ff; @@ -43,4 +38,19 @@ --color-gray-700: #3a3a3a; --color-gray-800: #2b2b2b; --color-gray-900: #181818; + + --color-red-100: #fef2f2; + --color-red-200: #fecaca; + --color-red-300: #fca5a5; + --color-red-400: #f87171; + --color-red-500: #dc3a3a; + --color-red-600: #dc2626; + --color-red-700: #b91c1c; + --color-red-800: #991b1b; + --color-red-900: #7f1d1d; + + /* Semantics */ + + --color-error: var(--color-red-500); + --color-surface: #f6f8ff; } From 070a0c9eff64a879c31fdb91cff062022752688f Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 23 Aug 2025 12:45:55 +0900 Subject: [PATCH 240/253] =?UTF-8?q?feat=20[#83]=20`DangerousButton`=20comp?= =?UTF-8?q?onent=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/button/button.jsx | 35 +++++++++++++++++++++++++++++- src/tests/test-components-page.jsx | 8 +++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/components/button/button.jsx b/src/components/button/button.jsx index e991737..51a75dd 100644 --- a/src/components/button/button.jsx +++ b/src/components/button/button.jsx @@ -215,4 +215,37 @@ function OutlinedButton({ className, title, icon, size, ...props }) { ); } -export { OutlinedButton, PrimaryButton, SecondaryButton }; +/* Dangerous Button */ + +const StyledDangerousButton = styled(BaseButton)` + padding: 0 24px; + background-color: ${Colors.red(600)}; + color: white; + + &:hover { + background-color: ${Colors.red(700)}; + } + + &:active { + background-color: ${Colors.red(800)}; + } + + &:focus { + background-color: ${Colors.red(800)}; + box-shadow: 0 0 0 1px ${Colors.red(900)} inset; + } + + &:disabled { + background-color: ${Colors.gray(300)}; + } +`; + +function DangerousButton({ title, size, ...props }) { + return ( + + {title} + + ); +} + +export { DangerousButton, OutlinedButton, PrimaryButton, SecondaryButton }; diff --git a/src/tests/test-components-page.jsx b/src/tests/test-components-page.jsx index 7e3cbb7..4fd191f 100644 --- a/src/tests/test-components-page.jsx +++ b/src/tests/test-components-page.jsx @@ -9,6 +9,7 @@ import EmojiBadge from "../components/badge/emoji-badge"; import ArrowButton from "../components/button/arrow-button"; import ARROW_BUTTON_DIRECTION from "../components/button/arrow-button-direction"; import { + DangerousButton, OutlinedButton, PrimaryButton, SecondaryButton, @@ -79,6 +80,13 @@ function TestComponentsPage() {
+
+ + + + + +
Date: Sat, 23 Aug 2025 12:47:05 +0900 Subject: [PATCH 241/253] =?UTF-8?q?feat=20[#83]=20API=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80=EC=9D=98=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EB=B2=84=ED=8A=BC=EC=9D=84=20`DangerousButton`=20?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EA=B5=90=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/tests/test-api-page.jsx | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/tests/test-api-page.jsx b/src/tests/test-api-page.jsx index 2ed9272..ef9c366 100644 --- a/src/tests/test-api-page.jsx +++ b/src/tests/test-api-page.jsx @@ -1,6 +1,6 @@ import { useCallback, useEffect, useState } from "react"; import styled from "styled-components"; -import { PrimaryButton } from "../components/button/button"; +import { DangerousButton, PrimaryButton } from "../components/button/button"; import BUTTON_SIZE from "../components/button/button-size"; import Colors from "../components/color/colors"; import { @@ -250,23 +250,13 @@ function TestApiPage() { /> - - Date: Sat, 23 Aug 2025 12:49:40 +0900 Subject: [PATCH 242/253] =?UTF-8?q?feat=20[#83]=20=EB=A1=A4=EB=A7=81=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=ED=8D=BC=20=EC=82=AD=EC=A0=9C=20=EB=B2=84?= =?UTF-8?q?=ED=8A=BC=EC=9D=84=20`DangerousButton`=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EA=B5=90=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/messages-page.jsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx index f4827b7..5584178 100644 --- a/src/pages/messages-page.jsx +++ b/src/pages/messages-page.jsx @@ -1,7 +1,11 @@ import { useEffect, useMemo, useState } from "react"; import { useLocation, useNavigate, useParams } from "react-router"; import styled from "styled-components"; -import { OutlinedButton, PrimaryButton } from "../components/button/button"; +import { + DangerousButton, + OutlinedButton, + PrimaryButton, +} from "../components/button/button"; import BUTTON_SIZE from "../components/button/button-size"; import BACKGROUND_COLOR from "../components/color/background-color"; import { @@ -74,14 +78,14 @@ function ViewerButtons({ onEdit }) { function EditingButtons({ onDelete, onCancel }) { return ( - From f3128e7cdf2468f72db83ab25fdd363182c4f03e Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 23 Aug 2025 13:54:32 +0900 Subject: [PATCH 243/253] =?UTF-8?q?feat=20[#78]=20Modal=20component?= =?UTF-8?q?=EA=B0=80=20content=EB=A5=BC=20=EB=B3=B4=EC=97=AC=EC=A3=BC?= =?UTF-8?q?=EB=8A=94=20=EC=B1=85=EC=9E=84=EB=A7=8C=20=EA=B0=96=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Modal 방식을 범용적으로 사용할 수 있도록 '확인' 버튼을 제거합니다. - MUI의 Modal component interface를 참고하였습니다. - 이 변경사항이 영향을 미치는 곳을 아직 수정하지 않았으므로, 이 commit에서는 error가 발생합니다. --- src/components/modal/modal.jsx | 29 +++-------------------------- src/hooks/use-modal.jsx | 3 +-- 2 files changed, 4 insertions(+), 28 deletions(-) diff --git a/src/components/modal/modal.jsx b/src/components/modal/modal.jsx index deb75b5..631f61a 100644 --- a/src/components/modal/modal.jsx +++ b/src/components/modal/modal.jsx @@ -1,7 +1,4 @@ import styled from "styled-components"; -import { useModal } from "../../hooks/use-modal"; -import { PrimaryButton } from "../button/button"; -import BUTTON_SIZE from "../button/button-size"; import Portal from "../portal/portal"; const Content = styled.div` @@ -34,34 +31,14 @@ const ModalContainer = styled.div` align-items: center; `; -const ActionButton = styled.div` - cursor: pointer; -`; - -function Modal({ id, action, children }) { - const { showsModal, setShowsModal } = useModal({ - id: id, - type: "modal", - }); - - const handleClick = () => setShowsModal(true); - const handleConfirmClick = () => setShowsModal(false); - +function Modal({ shows, children }) { return ( <> - {action} - {showsModal && ( + {shows && ( - - {children} - - + {children} diff --git a/src/hooks/use-modal.jsx b/src/hooks/use-modal.jsx index 9a3a1ad..964b050 100644 --- a/src/hooks/use-modal.jsx +++ b/src/hooks/use-modal.jsx @@ -1,7 +1,6 @@ import { usePortal } from "./use-portal"; -function useModal({ id, type }) { - const key = `${type}_${id}`; +function useModal({ key }) { const { isOpen, setIsOpen } = usePortal({ key }); return { showsModal: isOpen, setShowsModal: setIsOpen }; } From bdf71670a48bd6d1ba1de99aa40a9755d9593de7 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 23 Aug 2025 13:55:06 +0900 Subject: [PATCH 244/253] =?UTF-8?q?refactor=20[#78]=20`TestComponentsPage`?= =?UTF-8?q?=EC=97=90=20`Modal`=20=EB=B3=80=EA=B2=BD=EC=82=AC=ED=95=AD=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/tests/test-components-page.jsx | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/tests/test-components-page.jsx b/src/tests/test-components-page.jsx index 4fd191f..2a5444f 100644 --- a/src/tests/test-components-page.jsx +++ b/src/tests/test-components-page.jsx @@ -23,6 +23,7 @@ import POPOVER_ALIGNMENT from "../components/popover/popover-alignment"; import TextField from "../components/text-field/text-field"; import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; import Toast from "../components/toast/toast"; +import { useModal } from "../hooks/use-modal"; import { useToast } from "../hooks/use-toast"; const OutlinedHeader = styled(Header)` @@ -49,6 +50,13 @@ function TestComponentsPage() { const handleToastClick = () => setShowsToast(true); const handleToastDismiss = () => setShowsToast(false); + /* Modal */ + const { showsModal, setShowsModal } = useModal({ + key: "test-modal", + }); + const handleModalOpen = () => setShowsModal(true); + const handleModalClose = () => setShowsModal(false); + return (
- } - > + +

This is Modal.

+
From 7e28955c511da2620268ba7dbb1c013555706f1f Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 23 Aug 2025 13:55:29 +0900 Subject: [PATCH 245/253] =?UTF-8?q?refactor=20[#78]=20`MessagesGrid`?= =?UTF-8?q?=EC=97=90=20`Modal`=20=EB=B3=80=EA=B2=BD=EC=82=AC=ED=95=AD=20?= =?UTF-8?q?=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/message-card-detail.jsx | 23 +++++++- .../message/components/message-card.jsx | 17 +++++- .../message/components/messages-grid.jsx | 58 ++++++++++++------- 3 files changed, 71 insertions(+), 27 deletions(-) diff --git a/src/features/message/components/message-card-detail.jsx b/src/features/message/components/message-card-detail.jsx index 2f90ae9..68f8ad0 100644 --- a/src/features/message/components/message-card-detail.jsx +++ b/src/features/message/components/message-card-detail.jsx @@ -1,9 +1,12 @@ import styled from "styled-components"; +import { PrimaryButton } from "../../../components/button/button"; +import BUTTON_SIZE from "../../../components/button/button-size"; import Colors from "../../../components/color/colors"; import { formatDate } from "../../../utils/formatter"; import MessageSender from "./message-sender"; const Header = styled.header` + width: 100%; display: flex; justify-content: space-between; align-items: center; @@ -12,6 +15,7 @@ const Header = styled.header` `; const Content = styled.div` + width: 100%; margin-top: 16px; font-size: 18px; font-weight: 400; @@ -34,6 +38,10 @@ const Content = styled.div` } `; +const Action = styled.div` + padding-top: 24px; +`; + const CreatedDate = styled.span` font-size: 14px; font-weight: 400; @@ -41,9 +49,13 @@ const CreatedDate = styled.span` color: ${Colors.gray(400)}; `; -const StyledMessageCardDetail = styled.div``; +const StyledMessageCardDetail = styled.div` + display: flex; + flex-direction: column; + align-items: center; +`; -function MessageCardDetail({ message }) { +function MessageCardDetail({ message, onConfirm }) { return (
@@ -55,6 +67,13 @@ function MessageCardDetail({ message }) { {formatDate(message.createdAt, ".")}
{message.content} + + +
); } diff --git a/src/features/message/components/message-card.jsx b/src/features/message/components/message-card.jsx index d20a7cd..f1db29b 100644 --- a/src/features/message/components/message-card.jsx +++ b/src/features/message/components/message-card.jsx @@ -50,11 +50,22 @@ const StyledMessageCard = styled.article` border-radius: 16px; background-color: white; box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08); + cursor: ${({ $isEditing }) => ($isEditing ? "default" : "pointer")}; `; -function MessageCard({ isEditing, message, onDelete }) { +function MessageCard({ isEditing, message, onClick, onDelete }) { + const handleClick = () => { + if (isEditing) return; + onClick(message); + }; + + const handleDeleteClick = (event) => { + event.stopPropagation(); + onDelete(message.id); + }; + return ( - +
)}
diff --git a/src/features/message/components/messages-grid.jsx b/src/features/message/components/messages-grid.jsx index 0e42b5e..47f7729 100644 --- a/src/features/message/components/messages-grid.jsx +++ b/src/features/message/components/messages-grid.jsx @@ -1,8 +1,9 @@ -import { useRef } from "react"; +import { useRef, useState } from "react"; import { useNavigate, useParams } from "react-router"; import styled from "styled-components"; import Modal from "../../../components/modal/modal.jsx"; import { useIntersectionObserver } from "../../../hooks/use-intersection-observer.jsx"; +import { useModal } from "../../../hooks/use-modal.jsx"; import { media } from "../../../utils/media.js"; import MessageCardAdd from "./message-card-add.jsx"; import MessageCardDetail from "./message-card-detail.jsx"; @@ -28,6 +29,10 @@ function MessagesGrid({ isEditing, messages, onDelete, onInfiniteScroll }) { const navigate = useNavigate(); const { id } = useParams(); const infiniteScrollTargetRef = useRef(); + const { showsModal, setShowsModal } = useModal({ + key: "message-modal", + }); + const [modalMessage, setModalMessage] = useState(null); const observerCallback = (entry) => { if (!entry.isIntersecting) return; @@ -39,33 +44,42 @@ function MessagesGrid({ isEditing, messages, onDelete, onInfiniteScroll }) { navigate(`/post/${id}/message`); }; + const handleMessageClick = (message) => { + setShowsModal(true); + setModalMessage(message); + }; + const handleDeleteClick = (messageId) => { onDelete(messageId); }; - const messageCard = (message) => ( - handleDeleteClick(message.id)} - /> - ); + const handleModalConfirm = () => { + setShowsModal(false); + setModalMessage(null); + }; return ( - - - {messages.map((message) => - isEditing ? ( - messageCard(message) - ) : ( - - - - ) - )} -
-
+ <> + + + {messages.map((message) => ( + + ))} +
+
+ + + + ); } From 34c1947086a88ea074a2fc3fcde6a83278409e68 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 23 Aug 2025 21:17:33 +0900 Subject: [PATCH 246/253] =?UTF-8?q?refactor=20[]=20'=EC=99=84=EB=A3=8C?= =?UTF-8?q?=ED=95=98=EA=B8=B0'=20=EB=B2=84=ED=8A=BC=EC=9D=98=20event=20han?= =?UTF-8?q?dler=20=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/messages-page.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx index 5584178..61d6ac8 100644 --- a/src/pages/messages-page.jsx +++ b/src/pages/messages-page.jsx @@ -75,7 +75,7 @@ function ViewerButtons({ onEdit }) { ); } -function EditingButtons({ onDelete, onCancel }) { +function EditingButtons({ onDelete, onDone }) { return ( ); @@ -119,7 +119,7 @@ function MessagesPage() { } }; - const handleEditCancel = () => { + const handleEditDone = () => { navigate(-1); }; @@ -186,7 +186,7 @@ function MessagesPage() { {isEditing ? ( ) : ( From 0442b5a6912aea48c70e155c740e31e547ea476a Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 23 Aug 2025 22:52:29 +0900 Subject: [PATCH 247/253] =?UTF-8?q?feat=20[#84]=20`ModalDialog`=20componen?= =?UTF-8?q?t=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/modal/modal-dialog.jsx | 40 +++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 src/components/modal/modal-dialog.jsx diff --git a/src/components/modal/modal-dialog.jsx b/src/components/modal/modal-dialog.jsx new file mode 100644 index 0000000..45a9ddc --- /dev/null +++ b/src/components/modal/modal-dialog.jsx @@ -0,0 +1,40 @@ +import styled from "styled-components"; +import { PrimaryButton } from "../button/button"; +import BUTTON_SIZE from "../button/button-size"; +import Colors from "../color/colors"; + +const Title = styled.h2` + margin: 0; + color: ${Colors.gray(600)}; +`; + +const Content = styled.p` + margin: 0; + color: ${Colors.gray(600)}; +`; + +const Action = styled.div` + display: flex; + justify-content: flex-end; + gap: 16px; +`; + +const StyledAlertDialog = styled.div` + display: flex; + flex-direction: column; + gap: 24px; +`; + +function ModalDialog({ title, content, action }) { + return ( + + {title} + {content && {content}} + + {action ?? } + + + ); +} + +export default ModalDialog; From b370abb2e557491733bb819e28f0b314850385fb Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 23 Aug 2025 23:18:17 +0900 Subject: [PATCH 248/253] =?UTF-8?q?feat=20[#84]=20Modal=20dialog=EB=A5=BC?= =?UTF-8?q?=20=EC=82=AC=EC=9A=A9=ED=95=98=EA=B8=B0=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?custom=20hook=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/use-modal-dialog.jsx | 41 ++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/hooks/use-modal-dialog.jsx diff --git a/src/hooks/use-modal-dialog.jsx b/src/hooks/use-modal-dialog.jsx new file mode 100644 index 0000000..5bde450 --- /dev/null +++ b/src/hooks/use-modal-dialog.jsx @@ -0,0 +1,41 @@ +import { useState } from "react"; +import { useModal } from "./use-modal"; + +function useModalDialog() { + const { showsModal, setShowsModal } = useModal({ + key: "delete-modal", + }); + const [title, setTitle] = useState(""); + const [content, setContent] = useState(""); + const [primaryAction, setPrimaryAction] = useState(null); + + const openDialog = ({ title, content, primaryAction }) => { + setShowsModal(true); + setTitle(title); + setContent(content); + setPrimaryAction(() => primaryAction); + }; + + const closeDialog = () => { + setShowsModal(false); + setTitle(""); + setContent(""); + setPrimaryAction(null); + }; + + const onPrimaryAction = () => { + primaryAction(); + closeDialog(); + }; + + return { + showsDialog: showsModal, + dialogTitle: title, + dialogContent: content, + openDialog, + closeDialog, + onPrimaryAction, + }; +} + +export { useModalDialog }; From 66a5e9ae610c49ffd36c325182190c8d004d7c76 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 23 Aug 2025 23:18:39 +0900 Subject: [PATCH 249/253] =?UTF-8?q?feat=20[#84]=20=EB=A1=A4=EB=A7=81=20?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=ED=8D=BC=20=EB=B0=8F=20=EB=A9=94=EC=8B=9C?= =?UTF-8?q?=EC=A7=80=EB=A5=BC=20=EC=82=AD=EC=A0=9C=ED=95=98=EA=B8=B0=20?= =?UTF-8?q?=EC=A0=84=EC=97=90=20dialog=EB=A1=9C=20=ED=99=95=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../message/components/message-card.jsx | 2 +- .../message/components/messages-grid.jsx | 4 +- src/pages/messages-page.jsx | 100 ++++++++++++++---- 3 files changed, 81 insertions(+), 25 deletions(-) diff --git a/src/features/message/components/message-card.jsx b/src/features/message/components/message-card.jsx index f1db29b..1400b3c 100644 --- a/src/features/message/components/message-card.jsx +++ b/src/features/message/components/message-card.jsx @@ -61,7 +61,7 @@ function MessageCard({ isEditing, message, onClick, onDelete }) { const handleDeleteClick = (event) => { event.stopPropagation(); - onDelete(message.id); + onDelete(message); }; return ( diff --git a/src/features/message/components/messages-grid.jsx b/src/features/message/components/messages-grid.jsx index 47f7729..7aae610 100644 --- a/src/features/message/components/messages-grid.jsx +++ b/src/features/message/components/messages-grid.jsx @@ -49,8 +49,8 @@ function MessagesGrid({ isEditing, messages, onDelete, onInfiniteScroll }) { setModalMessage(message); }; - const handleDeleteClick = (messageId) => { - onDelete(messageId); + const handleDeleteClick = (message) => { + onDelete(message); }; const handleModalConfirm = () => { diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx index 61d6ac8..8574a9d 100644 --- a/src/pages/messages-page.jsx +++ b/src/pages/messages-page.jsx @@ -5,9 +5,12 @@ import { DangerousButton, OutlinedButton, PrimaryButton, + SecondaryButton, } from "../components/button/button"; import BUTTON_SIZE from "../components/button/button-size"; import BACKGROUND_COLOR from "../components/color/background-color"; +import Modal from "../components/modal/modal"; +import ModalDialog from "../components/modal/modal-dialog"; import { deleteMessage, getMessages, @@ -20,6 +23,7 @@ import { } from "../features/rolling-paper/api/recipients"; import RollingPaperHeader from "../features/rolling-paper/components/header/rolling-paper-header"; import { useMedia } from "../hooks/use-media"; +import { useModalDialog } from "../hooks/use-modal-dialog"; import ContentLayout from "../layouts/content-layout"; import { media } from "../utils/media"; @@ -83,11 +87,7 @@ function EditingButtons({ onDelete, onDone }) { title="삭제하기" onClick={onDelete} /> - + ); } @@ -99,6 +99,14 @@ function MessagesPage() { const location = useLocation(); const navigate = useNavigate(); const { id } = useParams(); + const { + showsDialog, + dialogTitle, + dialogContent, + openDialog, + closeDialog, + onPrimaryAction, + } = useModalDialog(); const isEditing = useMemo( () => location.pathname.includes("edit"), @@ -109,28 +117,50 @@ function MessagesPage() { navigate("edit"); }; - const handleRollingPaperDelete = async () => { - try { - await deleteRecipient({ id: recipient.id }); - navigate(`/list`); - } catch (error) { - // TODO: Error 처리 - console.log(error); - } + const handleRollingPaperDelete = () => { + openDialog({ + title: `${recipient.name} 님의 롤링 페이퍼를 삭제할까요?`, + content: "삭제한 롤링 페이퍼는 복원할 수 없어요.", + primaryAction: async () => { + try { + await deleteRecipient({ id: recipient.id }); + navigate(`/list`); + } catch (error) { + // TODO: Error 처리 + console.log(error); + } + }, + }); }; const handleEditDone = () => { navigate(-1); }; - const handleMessageDelete = async (messageId) => { - try { - await deleteMessage({ id: messageId }); - setMessages((prev) => prev.filter((message) => message.id !== messageId)); - } catch (error) { - // TODO: Error 처리 - console.log(error); - } + const handleMessageDelete = (message) => { + openDialog({ + title: `${message.sender} 님의 메시지를 삭제할까요?`, + content: "삭제한 메시지는 복원할 수 없어요.", + primaryAction: async () => { + try { + await deleteMessage({ id: message.id }); + setMessages((prev) => + prev.filter((prevMessage) => prevMessage.id !== message.id) + ); + } catch (error) { + // TODO: Error 처리 + console.log(error); + } + }, + }); + }; + + const handleDelete = () => { + onPrimaryAction(); + }; + + const handleDeleteCancel = () => { + closeDialog(); }; const handleInfiniteScroll = async () => { @@ -204,7 +234,33 @@ function MessagesPage() { ); - return isMobile ? content : {content}; + return isMobile ? ( + content + ) : ( + + {content} + + + + + + } + /> + + + ); } export default MessagesPage; From c15879f82388e9b7c7180a0e0d27636c3d976051 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sat, 23 Aug 2025 23:22:24 +0900 Subject: [PATCH 250/253] =?UTF-8?q?refactor=20[#84]=20=EC=8B=A4=EC=A0=9C?= =?UTF-8?q?=EB=A1=9C=20=EB=8D=B0=EC=9D=B4=ED=84=B0=EB=A5=BC=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=ED=95=98=EB=8A=94=20=EB=B2=84=ED=8A=BC=EC=97=90?= =?UTF-8?q?=EB=A7=8C=20`DangerousButton`=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/messages-page.jsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/pages/messages-page.jsx b/src/pages/messages-page.jsx index 8574a9d..41030f0 100644 --- a/src/pages/messages-page.jsx +++ b/src/pages/messages-page.jsx @@ -5,7 +5,6 @@ import { DangerousButton, OutlinedButton, PrimaryButton, - SecondaryButton, } from "../components/button/button"; import BUTTON_SIZE from "../components/button/button-size"; import BACKGROUND_COLOR from "../components/color/background-color"; @@ -82,7 +81,7 @@ function ViewerButtons({ onEdit }) { function EditingButtons({ onDelete, onDone }) { return ( - - - Date: Sun, 24 Aug 2025 10:11:25 +0900 Subject: [PATCH 251/253] =?UTF-8?q?feat=20[#95]=20`ToggleButton`=20compone?= =?UTF-8?q?nt=EC=97=90=20onChange=20event=20handler=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/button/toggle-button.jsx | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/components/button/toggle-button.jsx b/src/components/button/toggle-button.jsx index 03a6643..cf805d2 100644 --- a/src/components/button/toggle-button.jsx +++ b/src/components/button/toggle-button.jsx @@ -27,22 +27,28 @@ const ToggleItem = styled.button` } `; -function ToggleButton({ value, options = [] }) { +function ToggleButton({ value, options = [], onChange }) { const [selected, setSelected] = useState(value); - const handleOptionClick = (event) => { - setSelected(event.target.textContent); + const handleOptionClick = (option, index) => { + setSelected(option); + + if (onChange) { + onChange(option, index); + } }; return ( - {options.map((title, index) => ( + {options.map((option, index) => ( + handleOptionClick(event.target.textContent, index) + } > - {title} + {option} ))} From 65488211383439e993244129db5ee5244453d6fc Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sun, 24 Aug 2025 10:11:56 +0900 Subject: [PATCH 252/253] =?UTF-8?q?refactor=20[#95]=20`TestComponentsPage`?= =?UTF-8?q?=EC=9D=98=20`ToggleButton`=EC=97=90=20`onChange`=20event=20?= =?UTF-8?q?=EC=98=88=EC=8B=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/tests/test-components-page.jsx | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/tests/test-components-page.jsx b/src/tests/test-components-page.jsx index 2a5444f..96bbb2a 100644 --- a/src/tests/test-components-page.jsx +++ b/src/tests/test-components-page.jsx @@ -31,6 +31,11 @@ const OutlinedHeader = styled(Header)` `; function TestComponentsPage() { + /* Toggle Button */ + const handleToggleChange = (option, index) => { + console.log(option, index); + }; + /* Dropdown type TextField */ const [option1, setOption1] = useState(); const [option2, setOption2] = useState(); @@ -140,8 +145,15 @@ function TestComponentsPage() { gap: 16, }} > - - + +
From f730b4c15536226589ec120dc60df3e8da550cd9 Mon Sep 17 00:00:00 2001 From: Chamsol Kim Date: Sun, 24 Aug 2025 10:24:37 +0900 Subject: [PATCH 253/253] =?UTF-8?q?feat=20[#95]=20`CreatePostPage`?= =?UTF-8?q?=EC=9D=98=20`ToggleButton`=EC=97=90=20`onChange`=20event=20hand?= =?UTF-8?q?ler=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/create-post-page.jsx | 45 +++++++++++++++++----------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/src/pages/create-post-page.jsx b/src/pages/create-post-page.jsx index b5f15cb..e78bcc7 100644 --- a/src/pages/create-post-page.jsx +++ b/src/pages/create-post-page.jsx @@ -1,13 +1,12 @@ import { useState } from "react"; -import TextField from "../components/text-field/text-field"; -import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; -import Colors from "../components/color/colors"; -import ToggleButton from "../components/button/toggle-button"; +import { useNavigate } from "react-router"; import styled from "styled-components"; import { PrimaryButton } from "../components/button/button"; -import BackgroundSelect from "../components/option/background-select"; -import { useNavigate } from "react-router"; import BUTTON_SIZE from "../components/button/button-size"; +import ToggleButton from "../components/button/toggle-button"; +import BackgroundSelect from "../components/option/background-select"; +import TextField from "../components/text-field/text-field"; +import TEXT_FIELD_TYPE from "../components/text-field/text-field-type"; import { media } from "../utils/media"; const PostContainer = styled.div` @@ -61,10 +60,17 @@ const CreateButton = styled(PrimaryButton)` width: 100%; `; +const TOGGLE_OPTIONS = ["컬러", "이미지"]; + +const SELECT_TYPE = { + 컬러: "color", + 이미지: "image", +}; + function CreatePostPage() { const [name, setName] = useState(""); const [nameError, setNameError] = useState(""); - const [backgroundType, setBackgroundType] = useState("컬러"); + const [backgroundType, setBackgroundType] = useState(TOGGLE_OPTIONS[0]); const [selected, setSelected] = useState(0); const navigate = useNavigate(); @@ -83,15 +89,6 @@ function CreatePostPage() { } }; - const handleBackgroundSelect = (e) => { - let typeSelect = e.target.textContent; - - if (typeSelect === "컬러" || typeSelect === "이미지") { - setBackgroundType(typeSelect); - setSelected(0); - } - }; - const handleCreate = () => { const randomID = Math.floor(Math.random() * 10000); navigate(`/post/${randomID}`); @@ -99,6 +96,11 @@ function CreatePostPage() { const canCreate = trimmed !== ""; + const handleToggleChange = (option) => { + setBackgroundType(option); + setSelected(0); + }; + return ( @@ -117,19 +119,16 @@ function CreatePostPage() { 컬러를 선택하거나, 이미지를 선택할 수 있습니다. - + { - handleBackgroundSelect(type); - setSelected(0); - }} + options={TOGGLE_OPTIONS} + onChange={handleToggleChange} />