From 3bdf498332a869e2a7e7340fe8e3c5accb5d321a Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Fri, 15 Nov 2024 23:29:53 +0900 Subject: [PATCH 01/25] =?UTF-8?q?feat:=20=ED=99=94=EC=82=B4=ED=91=9C=20?= =?UTF-8?q?=EC=95=84=EC=9D=B4=EC=BD=98=20size=20prop=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/diary/calendar/CalendarArrow.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/diary/calendar/CalendarArrow.tsx b/src/components/diary/calendar/CalendarArrow.tsx index e3cc203..3706ef6 100644 --- a/src/components/diary/calendar/CalendarArrow.tsx +++ b/src/components/diary/calendar/CalendarArrow.tsx @@ -7,15 +7,16 @@ export type Direction = 'left' | 'right'; interface CalendarArrowProps { direction: Direction; + size?: number; } -const CalendarArrow = ({ direction }: CalendarArrowProps) => { +const CalendarArrow = ({ direction, size = 24 }: CalendarArrowProps) => { return ( {direction === 'left' ? ( - + ) : ( - + )} ); From 42b59376e133fab8b0970db21485d12f82f0f3bb Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Sat, 16 Nov 2024 01:33:23 +0900 Subject: [PATCH 02/25] =?UTF-8?q?design:=20=EB=A6=AC=ED=8F=AC=ED=8A=B8=20?= =?UTF-8?q?=EC=B0=BD=20=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../diary/calendar/CalendarArrow.tsx | 11 ++- src/screens/report/NewReportView.tsx | 88 +++++++++++++++++++ 2 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 src/screens/report/NewReportView.tsx diff --git a/src/components/diary/calendar/CalendarArrow.tsx b/src/components/diary/calendar/CalendarArrow.tsx index 3706ef6..ecd60e8 100644 --- a/src/components/diary/calendar/CalendarArrow.tsx +++ b/src/components/diary/calendar/CalendarArrow.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { View } from 'react-native'; +import { StyleProp, View, ViewStyle } from 'react-native'; import Left from '@assets/svg/icons/entypo--chevron-small-left.svg'; import Right from '@assets/svg/icons/entypo--chevron-small-right.svg'; @@ -8,11 +8,16 @@ export type Direction = 'left' | 'right'; interface CalendarArrowProps { direction: Direction; size?: number; + style?: StyleProp; } -const CalendarArrow = ({ direction, size = 24 }: CalendarArrowProps) => { +const CalendarArrow = ({ + direction, + size = 24, + style = { marginRight: 20 }, +}: CalendarArrowProps) => { return ( - + {direction === 'left' ? ( ) : ( diff --git a/src/screens/report/NewReportView.tsx b/src/screens/report/NewReportView.tsx new file mode 100644 index 0000000..40b14f9 --- /dev/null +++ b/src/screens/report/NewReportView.tsx @@ -0,0 +1,88 @@ +import React, { useState } from 'react'; +import { View, StyleSheet, Pressable, ScrollView, SafeAreaView } from 'react-native'; +import { fontMedium, fontLarge } from '@utils/Sizing'; +import CalendarArrow from '@components/diary/calendar/CalendarArrow'; +import MyText from '@components/common/MyText'; +import { appColor1, appColor2, appColor3, appColor4, appColor5 } from '@utils/colors'; + +function NewReportView() { + const [targetMonth, setTargetMonth] = useState(new Date().getMonth() + 1); + + const onLeftPress = () => { + targetMonth === 1 ? setTargetMonth(12) : setTargetMonth(targetMonth - 1); + }; + + const onRightPress = () => { + targetMonth === 12 ? setTargetMonth(1) : setTargetMonth(targetMonth + 1); + }; + + const keyword = '건강'; + const content = `날씨가 추워질수록 건강에 대한 언급이 많아졌어요. 다음주부터는 더 춥다고 하니, 따뜻하게 입는다면 건강에 대한 걱정이 덜 할 것 같아요. + 목을 따뜻하게 감싸면 체온이 3도 이상 올라가는 효과가 있다고 해요. 저번에 지수에게 선물받은 부드러운 앙고라 목도리를 해보는건 어떤가요?`; + + const keywords = ['건강', '요리', '영화', '운동', '책']; + + return ( + + + + + + + + {targetMonth}월의 기억 조각 + + + + + + + 차트 + + + {targetMonth}월에 가장 많이 언급한 단어를 모아봤어요. + + + + {keyword} + + + {content} + + + + + ); +} + +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: 'transparent', + alignItems: 'center', + paddingHorizontal: 16, + }, + header: { + alignItems: 'center', + paddingVertical: 20, + flexDirection: 'row', + justifyContent: 'space-between', + }, + title: { + marginHorizontal: 56, + }, + chart: {}, + cardContainer: { + backgroundColor: appColor1, + borderWidth: 1, + borderRadius: 12, + alignItems: 'flex-start', + flexDirection: 'column', + padding: 16, + width: '100%', + marginBottom: 16, + flexGrow: 1, + }, +}); + +export default NewReportView; From 6b7ce50a8229612665cb980d1aa24cc3a019d237 Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Sat, 16 Nov 2024 01:37:46 +0900 Subject: [PATCH 03/25] build: installed react-native-gifted-charts --- package-lock.json | 35 +++++++++++++++++++++++++++++++++++ package.json | 1 + yarn.lock | 14 +++++++++++++- 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index c8726e0..95996c7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,6 +41,7 @@ "react-native-element-dropdown": "^2.12.1", "react-native-encrypted-storage": "^4.0.3", "react-native-gesture-handler": "^2.16.2", + "react-native-gifted-charts": "^1.4.47", "react-native-markdown-display": "^7.0.2", "react-native-paper": "^5.12.3", "react-native-reanimated": "^3.12.1", @@ -10703,6 +10704,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gifted-charts-core": { + "version": "0.1.47", + "resolved": "https://registry.npmjs.org/gifted-charts-core/-/gifted-charts-core-0.1.47.tgz", + "integrity": "sha512-mVwJKwje7O3zjNatNEb6cPr+Cs8G+2l7oWcyL6BuqUz1NDDavWf6dYivDTfV4Q5oPPJS7FrlCALr43kCIvQFNg==", + "license": "MIT", + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -16435,6 +16446,30 @@ "react-native": "*" } }, + "node_modules/react-native-gifted-charts": { + "version": "1.4.47", + "resolved": "https://registry.npmjs.org/react-native-gifted-charts/-/react-native-gifted-charts-1.4.47.tgz", + "integrity": "sha512-eSCAnAD2CNmg4jPGHl8CyN05L97piqAp5aMhlk04B4IYYxt8DHQXKu0cmOpt8pUFmQ6T++iw/liySY4AH2W3gQ==", + "license": "MIT", + "dependencies": { + "gifted-charts-core": "0.1.47" + }, + "peerDependencies": { + "expo-linear-gradient": "*", + "react": "*", + "react-native": "*", + "react-native-linear-gradient": "*", + "react-native-svg": "*" + }, + "peerDependenciesMeta": { + "expo-linear-gradient": { + "optional": true + }, + "react-native-linear-gradient": { + "optional": true + } + } + }, "node_modules/react-native-markdown-display": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/react-native-markdown-display/-/react-native-markdown-display-7.0.2.tgz", diff --git a/package.json b/package.json index fd56ff9..961f7e2 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "react-native-element-dropdown": "^2.12.1", "react-native-encrypted-storage": "^4.0.3", "react-native-gesture-handler": "^2.16.2", + "react-native-gifted-charts": "^1.4.47", "react-native-markdown-display": "^7.0.2", "react-native-paper": "^5.12.3", "react-native-reanimated": "^3.12.1", diff --git a/yarn.lock b/yarn.lock index a81bee6..a799366 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5277,6 +5277,11 @@ get-symbol-description@^1.0.2: es-errors "^1.3.0" get-intrinsic "^1.2.4" +gifted-charts-core@0.1.47: + version "0.1.47" + resolved "https://registry.npmjs.org/gifted-charts-core/-/gifted-charts-core-0.1.47.tgz" + integrity sha512-mVwJKwje7O3zjNatNEb6cPr+Cs8G+2l7oWcyL6BuqUz1NDDavWf6dYivDTfV4Q5oPPJS7FrlCALr43kCIvQFNg== + glob-parent@^5.1.2: version "5.1.2" resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" @@ -8167,6 +8172,13 @@ react-native-gesture-handler@^2.16.2, "react-native-gesture-handler@>= 1.0.0": lodash "^4.17.21" prop-types "^15.7.2" +react-native-gifted-charts@^1.4.47: + version "1.4.47" + resolved "https://registry.npmjs.org/react-native-gifted-charts/-/react-native-gifted-charts-1.4.47.tgz" + integrity sha512-eSCAnAD2CNmg4jPGHl8CyN05L97piqAp5aMhlk04B4IYYxt8DHQXKu0cmOpt8pUFmQ6T++iw/liySY4AH2W3gQ== + dependencies: + gifted-charts-core "0.1.47" + react-native-markdown-display@^7.0.2: version "7.0.2" resolved "https://registry.npmjs.org/react-native-markdown-display/-/react-native-markdown-display-7.0.2.tgz" @@ -8223,7 +8235,7 @@ react-native-svg-transformer@^1.4.0: "@svgr/plugin-svgo" "^8.1.0" path-dirname "^1.0.2" -react-native-svg@^15.3.0, "react-native-svg@> 6.4.1", react-native-svg@>=12.0.0: +react-native-svg@*, react-native-svg@^15.3.0, "react-native-svg@> 6.4.1", react-native-svg@>=12.0.0: version "15.3.0" resolved "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.3.0.tgz" integrity sha512-mBHu/fdlzUbpGX8SZFxgbKvK/sgqLfDLP8uh8G7Us+zJgdjO8OSEeqHQs+kPRdQmdLJQiqPJX2WXgCl7ToTWqw== From 9983f9f5e7d25a7ae5e1e74aaffc40540f9f19d5 Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Sat, 16 Nov 2024 01:45:55 +0900 Subject: [PATCH 04/25] =?UTF-8?q?build:=20react=20native=20=EC=B0=A8?= =?UTF-8?q?=ED=8A=B8=20=EB=9D=BC=EC=9D=B4=EB=B8=8C=EB=9F=AC=EB=A6=AC=20?= =?UTF-8?q?=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 | 3 ++- yarn.lock | 16 +++++++++++----- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/package-lock.json b/package-lock.json index 95996c7..6449104 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,12 +42,13 @@ "react-native-encrypted-storage": "^4.0.3", "react-native-gesture-handler": "^2.16.2", "react-native-gifted-charts": "^1.4.47", + "react-native-linear-gradient": "^2.8.3", "react-native-markdown-display": "^7.0.2", "react-native-paper": "^5.12.3", "react-native-reanimated": "^3.12.1", "react-native-safe-area-context": "^4.10.5", "react-native-screens": "^3.31.1", - "react-native-svg": "^15.3.0", + "react-native-svg": "^15.9.0", "react-native-web": "^0.19.12", "recoil": "^0.7.7", "sha256": "^0.2.0" @@ -16470,6 +16471,16 @@ } } }, + "node_modules/react-native-linear-gradient": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/react-native-linear-gradient/-/react-native-linear-gradient-2.8.3.tgz", + "integrity": "sha512-KflAXZcEg54PXkLyflaSZQ3PJp4uC4whM7nT/Uot9m0e/qxFV3p6uor1983D1YOBJbJN7rrWdqIjq0T42jOJyA==", + "license": "MIT", + "peerDependencies": { + "react": "*", + "react-native": "*" + } + }, "node_modules/react-native-markdown-display": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/react-native-markdown-display/-/react-native-markdown-display-7.0.2.tgz", @@ -16559,13 +16570,14 @@ } }, "node_modules/react-native-svg": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.3.0.tgz", - "integrity": "sha512-mBHu/fdlzUbpGX8SZFxgbKvK/sgqLfDLP8uh8G7Us+zJgdjO8OSEeqHQs+kPRdQmdLJQiqPJX2WXgCl7ToTWqw==", + "version": "15.9.0", + "resolved": "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.9.0.tgz", + "integrity": "sha512-pwo7hteAM0P8jNpPGQtiSd0SnbBhE8tNd94LT8AcZcbnH5AJdXBIcXU4+tWYYeGUjiNAH2E5d0T5XIfnvaz1gA==", "license": "MIT", "dependencies": { "css-select": "^5.1.0", - "css-tree": "^1.1.3" + "css-tree": "^1.1.3", + "warn-once": "0.1.1" }, "peerDependencies": { "react": "*", diff --git a/package.json b/package.json index 961f7e2..ec4f38d 100644 --- a/package.json +++ b/package.json @@ -48,12 +48,13 @@ "react-native-encrypted-storage": "^4.0.3", "react-native-gesture-handler": "^2.16.2", "react-native-gifted-charts": "^1.4.47", + "react-native-linear-gradient": "^2.8.3", "react-native-markdown-display": "^7.0.2", "react-native-paper": "^5.12.3", "react-native-reanimated": "^3.12.1", "react-native-safe-area-context": "^4.10.5", "react-native-screens": "^3.31.1", - "react-native-svg": "^15.3.0", + "react-native-svg": "^15.9.0", "react-native-web": "^0.19.12", "recoil": "^0.7.7", "sha256": "^0.2.0" diff --git a/yarn.lock b/yarn.lock index a799366..9af97d6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8179,6 +8179,11 @@ react-native-gifted-charts@^1.4.47: dependencies: gifted-charts-core "0.1.47" +react-native-linear-gradient@*, react-native-linear-gradient@^2.8.3: + version "2.8.3" + resolved "https://registry.npmjs.org/react-native-linear-gradient/-/react-native-linear-gradient-2.8.3.tgz" + integrity sha512-KflAXZcEg54PXkLyflaSZQ3PJp4uC4whM7nT/Uot9m0e/qxFV3p6uor1983D1YOBJbJN7rrWdqIjq0T42jOJyA== + react-native-markdown-display@^7.0.2: version "7.0.2" resolved "https://registry.npmjs.org/react-native-markdown-display/-/react-native-markdown-display-7.0.2.tgz" @@ -8235,13 +8240,14 @@ react-native-svg-transformer@^1.4.0: "@svgr/plugin-svgo" "^8.1.0" path-dirname "^1.0.2" -react-native-svg@*, react-native-svg@^15.3.0, "react-native-svg@> 6.4.1", react-native-svg@>=12.0.0: - version "15.3.0" - resolved "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.3.0.tgz" - integrity sha512-mBHu/fdlzUbpGX8SZFxgbKvK/sgqLfDLP8uh8G7Us+zJgdjO8OSEeqHQs+kPRdQmdLJQiqPJX2WXgCl7ToTWqw== +react-native-svg@*, react-native-svg@^15.9.0, "react-native-svg@> 6.4.1", react-native-svg@>=12.0.0: + version "15.9.0" + resolved "https://registry.npmjs.org/react-native-svg/-/react-native-svg-15.9.0.tgz" + integrity sha512-pwo7hteAM0P8jNpPGQtiSd0SnbBhE8tNd94LT8AcZcbnH5AJdXBIcXU4+tWYYeGUjiNAH2E5d0T5XIfnvaz1gA== dependencies: css-select "^5.1.0" css-tree "^1.1.3" + warn-once "0.1.1" react-native-swipe-gestures@^1.0.5: version "1.0.5" @@ -9738,7 +9744,7 @@ walker@^1.0.7, walker@^1.0.8: dependencies: makeerror "1.0.12" -warn-once@^0.1.0: +warn-once@^0.1.0, warn-once@0.1.1: version "0.1.1" resolved "https://registry.npmjs.org/warn-once/-/warn-once-0.1.1.tgz" integrity sha512-VkQZJbO8zVImzYFteBXvBOZEl1qL175WH8VmZcxF2fZAoudNhNDvHi+doCaAEdU2l2vtcIwa2zn0QK5+I1HQ3Q== From 11ff4fb140941183943d0d0da18aeb3f7acb0db3 Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Sat, 16 Nov 2024 04:17:16 +0900 Subject: [PATCH 05/25] =?UTF-8?q?design:=20web=20=EB=A6=AC=ED=8F=AC?= =?UTF-8?q?=ED=8A=B8=20=EB=8F=84=EB=84=9B=20=EC=B0=A8=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/screens/report/NewChartView.native.tsx | 39 +++++++ src/screens/report/NewChartView.web.tsx | 117 +++++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 src/screens/report/NewChartView.native.tsx create mode 100644 src/screens/report/NewChartView.web.tsx diff --git a/src/screens/report/NewChartView.native.tsx b/src/screens/report/NewChartView.native.tsx new file mode 100644 index 0000000..b43f87e --- /dev/null +++ b/src/screens/report/NewChartView.native.tsx @@ -0,0 +1,39 @@ +import React from 'react'; +import { View, StyleSheet } from 'react-native'; + +import { PieChart } from 'react-native-gifted-charts'; +import { pieColors } from '@utils/colors'; + +function NewChartView() { + const keywords = ['건강', '요리', '영화', '운동', '책']; + + const pieData = [ + { value: 5, color: pieColors[5], text: '책' }, + { value: 15, color: pieColors[4], text: '운동' }, + { value: 20, color: pieColors[3], text: '영화' }, + { value: 24, color: pieColors[2], text: '요리' }, + { value: 26, color: pieColors[1], text: '건강' }, + ]; + + return ( + + + + ); +} + +const styles = StyleSheet.create({ + chart: {}, +}); + +export default NewChartView; diff --git a/src/screens/report/NewChartView.web.tsx b/src/screens/report/NewChartView.web.tsx new file mode 100644 index 0000000..34bbe7b --- /dev/null +++ b/src/screens/report/NewChartView.web.tsx @@ -0,0 +1,117 @@ +import React from 'react'; +import { View, StyleSheet } from 'react-native'; +import { + Chart as ChartJS, + RadialLinearScale, + PointElement, + LineElement, + Filler, + Tooltip, + Legend, + ArcElement, +} from 'chart.js'; +import ChartDataLabels, { Context } from 'chartjs-plugin-datalabels'; +import { Doughnut } from 'react-chartjs-2'; +import { pieColors } from '@utils/colors'; +import MyText from '@components/common/MyText'; +import { fontBasic } from '@utils/Sizing'; + +ChartJS.register( + RadialLinearScale, + PointElement, + LineElement, + Filler, + Tooltip, + Legend, + ArcElement, + ChartDataLabels, +); + +function NewChartView() { + const data = { + labels: ['날씨', '영화', '엄청나게 긴 단어라고 합니다', '요리하다', '독서', '기타'], + datasets: [ + { + data: [30, 20, 15, 10, 20, 5], + backgroundColor: pieColors, + borderWidth: 0, + }, + ], + }; + + const otherDetails = { + 잠: 3, + 여행: 2, + 음악: 1.5, + 게임: 1.3, + 쇼핑: 0.2, + }; + + const options = { + responsive: true, + cutout: '40%', + plugins: { + datalabels: { + display: true, + formatter: (value: any, ctx: any) => { + const label = ctx.chart.data.labels[ctx.dataIndex]; + if (value < 5) { + return ''; + } + return label.length > 4 ? label.slice(0, 4) + '..' : label; + }, + color: function (ctx: Context) { + var index = ctx.dataIndex; + return index > 2 ? 'white' : 'black'; + }, + borderRadius: 4, + font: { + family: 'GowunBatang-Regular', + size: fontBasic, + }, + padding: { + top: 6, + bottom: 6, + }, + }, + tooltip: { + titleFont: { + family: 'GowunBatang-Bold', + }, + bodyFont: { + family: 'GowunBatang-Regular', + }, + displayColors: false, + padding: 10, + callbacks: { + label: function (tooltipItem: any) { + const label = tooltipItem.label || ''; + if (label === '기타') { + let res = ''; + Object.entries(otherDetails).forEach(([key, value]) => { + res += `${key}: ${value}번 `; + }); + return res; + } + return `${label}: ${tooltipItem.raw}번`; + }, + }, + }, + legend: { + display: false, + }, + }, + }; + + return ( + + + + ); +} + +const styles = StyleSheet.create({ + chart: {}, +}); + +export default NewChartView; From 16380728084ce73582c33e98d1d48b789968daa5 Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Sat, 16 Nov 2024 04:17:40 +0900 Subject: [PATCH 06/25] =?UTF-8?q?design:=20pie=20chart=20color=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/utils/colors.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/utils/colors.ts b/src/utils/colors.ts index ef82618..25a55ed 100644 --- a/src/utils/colors.ts +++ b/src/utils/colors.ts @@ -16,3 +16,5 @@ export const dotColors: { [key: number]: string } = { 2: '#BA9348', 3: '#7A5F3F', }; + +export const pieColors = [appColor1, '#F3D9B4', appColor2, appColor3, appColor4, appColor5]; From a2e4ad7e885f8b00e153202f1d46f1e02e3e32c4 Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Sat, 16 Nov 2024 04:18:08 +0900 Subject: [PATCH 07/25] =?UTF-8?q?feat:=20=ED=97=A4=EB=8D=94=20=EB=8B=AC?= =?UTF-8?q?=EB=A0=A5=20=EB=AA=A8=EB=8B=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/screens/report/NewReportView.tsx | 63 ++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/src/screens/report/NewReportView.tsx b/src/screens/report/NewReportView.tsx index 40b14f9..9779032 100644 --- a/src/screens/report/NewReportView.tsx +++ b/src/screens/report/NewReportView.tsx @@ -3,44 +3,76 @@ import { View, StyleSheet, Pressable, ScrollView, SafeAreaView } from 'react-nat import { fontMedium, fontLarge } from '@utils/Sizing'; import CalendarArrow from '@components/diary/calendar/CalendarArrow'; import MyText from '@components/common/MyText'; -import { appColor1, appColor2, appColor3, appColor4, appColor5 } from '@utils/colors'; +import NewChartView from '@screens/report/NewChartView'; +import { appColor1 } from '@utils/colors'; +import CalendarSelectModal from '@components/diary/calendar/CalendarSelectModal'; +import { kMonth } from '@utils/localeConfig'; function NewReportView() { - const [targetMonth, setTargetMonth] = useState(new Date().getMonth() + 1); + const [isModalVisible, setModalVisible] = useState(false); + const [selectedDate, setSelectedDate] = useState(new Date().toISOString().slice(0, 10)); + const [selectedMonth, setSelectedMonth] = useState( + parseInt(selectedDate.slice(5, 7), 10), + ); + const [selectedYear, setSelectedYear] = useState(parseInt(selectedDate.slice(0, 4), 10)); + + const handleModalDismiss = () => { + const day = selectedDate.slice(8, 10); + const lastDay = new Date(selectedYear, selectedMonth, 0).getDate(); + const month = selectedMonth.toString().padStart(2, '0'); + if (parseInt(day, 10) > lastDay) { + setSelectedDate(`${selectedYear}-${month}-${lastDay}`); + } else { + setSelectedDate(`${selectedYear}-${month}-${day}`); + } + setModalVisible(false); + }; + + const onHeaderPress = () => { + setModalVisible(true); + }; const onLeftPress = () => { - targetMonth === 1 ? setTargetMonth(12) : setTargetMonth(targetMonth - 1); + selectedMonth === 1 ? setSelectedMonth(12) : setSelectedMonth(selectedMonth - 1); }; const onRightPress = () => { - targetMonth === 12 ? setTargetMonth(1) : setTargetMonth(targetMonth + 1); + selectedMonth === 11 ? setSelectedMonth(1) : setSelectedMonth(selectedMonth + 1); }; const keyword = '건강'; const content = `날씨가 추워질수록 건강에 대한 언급이 많아졌어요. 다음주부터는 더 춥다고 하니, 따뜻하게 입는다면 건강에 대한 걱정이 덜 할 것 같아요. 목을 따뜻하게 감싸면 체온이 3도 이상 올라가는 효과가 있다고 해요. 저번에 지수에게 선물받은 부드러운 앙고라 목도리를 해보는건 어떤가요?`; - const keywords = ['건강', '요리', '영화', '운동', '책']; - return ( - + - - {targetMonth}월의 기억 조각 - + + + {kMonth[selectedMonth - 1]}의 기억 조각 + + + - - 차트 + + - {targetMonth}월에 가장 많이 언급한 단어를 모아봤어요. + {kMonth[selectedMonth - 1]}에 가장 많이 언급한 단어를 모아봤어요. @@ -67,11 +99,8 @@ const styles = StyleSheet.create({ paddingVertical: 20, flexDirection: 'row', justifyContent: 'space-between', + minWidth: '80%', }, - title: { - marginHorizontal: 56, - }, - chart: {}, cardContainer: { backgroundColor: appColor1, borderWidth: 1, From 77209e8ac655e4178257465954e9c4c3075f8658 Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Sat, 16 Nov 2024 15:39:26 +0900 Subject: [PATCH 08/25] =?UTF-8?q?design:=20=EB=8F=84=EB=84=9B=20=EC=B0=A8?= =?UTF-8?q?=ED=8A=B8=20=EC=8A=A4=ED=83=80=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/screens/report/NewChartView.web.tsx | 36 ++++++------------------- src/utils/colors.ts | 2 +- 2 files changed, 9 insertions(+), 29 deletions(-) diff --git a/src/screens/report/NewChartView.web.tsx b/src/screens/report/NewChartView.web.tsx index 34bbe7b..a12f798 100644 --- a/src/screens/report/NewChartView.web.tsx +++ b/src/screens/report/NewChartView.web.tsx @@ -10,10 +10,9 @@ import { Legend, ArcElement, } from 'chart.js'; -import ChartDataLabels, { Context } from 'chartjs-plugin-datalabels'; +import ChartDataLabels from 'chartjs-plugin-datalabels'; import { Doughnut } from 'react-chartjs-2'; import { pieColors } from '@utils/colors'; -import MyText from '@components/common/MyText'; import { fontBasic } from '@utils/Sizing'; ChartJS.register( @@ -29,24 +28,15 @@ ChartJS.register( function NewChartView() { const data = { - labels: ['날씨', '영화', '엄청나게 긴 단어라고 합니다', '요리하다', '독서', '기타'], + labels: ['엄청나게 긴 단어라고 합니다', '영화', '날씨', '요리하다', '독서'], datasets: [ { - data: [30, 20, 15, 10, 20, 5], + data: [30, 20, 20, 15, 15], backgroundColor: pieColors, - borderWidth: 0, }, ], }; - const otherDetails = { - 잠: 3, - 여행: 2, - 음악: 1.5, - 게임: 1.3, - 쇼핑: 0.2, - }; - const options = { responsive: true, cutout: '40%', @@ -55,18 +45,15 @@ function NewChartView() { display: true, formatter: (value: any, ctx: any) => { const label = ctx.chart.data.labels[ctx.dataIndex]; - if (value < 5) { - return ''; - } + // if (value < 5) { + // return ''; + // } return label.length > 4 ? label.slice(0, 4) + '..' : label; }, - color: function (ctx: Context) { - var index = ctx.dataIndex; - return index > 2 ? 'white' : 'black'; - }, + color: 'white', borderRadius: 4, font: { - family: 'GowunBatang-Regular', + family: 'GowunBatang-Bold', size: fontBasic, }, padding: { @@ -86,13 +73,6 @@ function NewChartView() { callbacks: { label: function (tooltipItem: any) { const label = tooltipItem.label || ''; - if (label === '기타') { - let res = ''; - Object.entries(otherDetails).forEach(([key, value]) => { - res += `${key}: ${value}번 `; - }); - return res; - } return `${label}: ${tooltipItem.raw}번`; }, }, diff --git a/src/utils/colors.ts b/src/utils/colors.ts index 25a55ed..e2d71e9 100644 --- a/src/utils/colors.ts +++ b/src/utils/colors.ts @@ -17,4 +17,4 @@ export const dotColors: { [key: number]: string } = { 3: '#7A5F3F', }; -export const pieColors = [appColor1, '#F3D9B4', appColor2, appColor3, appColor4, appColor5]; +export const pieColors = [appColor2, '#dcb15c', appColor3, appColor4, '#856017']; From aa8e88a4ce00f48b6e422565c084d40e95977011 Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Sat, 16 Nov 2024 16:04:25 +0900 Subject: [PATCH 09/25] =?UTF-8?q?design:=20report=20layout=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/screens/report/NewChartView.web.tsx | 9 ++++++++- src/screens/report/NewReportView.tsx | 12 +++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/screens/report/NewChartView.web.tsx b/src/screens/report/NewChartView.web.tsx index a12f798..fae82a5 100644 --- a/src/screens/report/NewChartView.web.tsx +++ b/src/screens/report/NewChartView.web.tsx @@ -91,7 +91,14 @@ function NewChartView() { } const styles = StyleSheet.create({ - chart: {}, + chart: { + flex: 1, + marginTop: 16, + width: '100%', + justifyContent: 'center', + alignItems: 'center', + minHeight: 200, + }, }); export default NewChartView; diff --git a/src/screens/report/NewReportView.tsx b/src/screens/report/NewReportView.tsx index 9779032..99f4800 100644 --- a/src/screens/report/NewReportView.tsx +++ b/src/screens/report/NewReportView.tsx @@ -46,7 +46,7 @@ function NewReportView() { return ( - + @@ -68,9 +68,7 @@ function NewReportView() { - - - + {kMonth[selectedMonth - 1]}에 가장 많이 언급한 단어를 모아봤어요. @@ -78,11 +76,11 @@ function NewReportView() { {keyword} - + {content} - + ); } @@ -102,6 +100,7 @@ const styles = StyleSheet.create({ minWidth: '80%', }, cardContainer: { + flex: 1, backgroundColor: appColor1, borderWidth: 1, borderRadius: 12, @@ -109,7 +108,6 @@ const styles = StyleSheet.create({ flexDirection: 'column', padding: 16, width: '100%', - marginBottom: 16, flexGrow: 1, }, }); From 27daf33d6b1162d4493540b12162b04c8d87e1f8 Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Sat, 16 Nov 2024 16:18:54 +0900 Subject: [PATCH 10/25] =?UTF-8?q?design:=20=EB=A9=94=EC=9D=B8=20=EC=BB=A8?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EB=84=88=20=EB=B6=80=EB=B6=84=20scrollview?= =?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 --- src/screens/report/NewReportView.tsx | 34 +++++++++++++++++----------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/screens/report/NewReportView.tsx b/src/screens/report/NewReportView.tsx index 99f4800..8d8d079 100644 --- a/src/screens/report/NewReportView.tsx +++ b/src/screens/report/NewReportView.tsx @@ -68,18 +68,23 @@ function NewReportView() { - - - {kMonth[selectedMonth - 1]}에 가장 많이 언급한 단어를 모아봤어요. - - - - {keyword} - - - {content} - - + + + + {kMonth[selectedMonth - 1]}에 가장 많이 언급한 단어를 모아봤어요. + + + + {keyword} + + + {content} + + + ); @@ -99,8 +104,11 @@ const styles = StyleSheet.create({ justifyContent: 'space-between', minWidth: '80%', }, + mainContainer: { + flexGrow: 1, + alignItems: 'center', + }, cardContainer: { - flex: 1, backgroundColor: appColor1, borderWidth: 1, borderRadius: 12, From 13b8c8e248f9f9d6377100aa2f2a1f787adae655 Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Sat, 16 Nov 2024 22:35:54 +0900 Subject: [PATCH 11/25] =?UTF-8?q?chore:=20=EB=AA=A8=EB=8B=AC=20=EC=84=A0?= =?UTF-8?q?=ED=83=9D=20=EB=82=A0=EC=A7=9C=20ICalendarModalDate=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/screens/ai/AiLetterCalendar.tsx | 4 ++-- src/types/Diary.ts | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/screens/ai/AiLetterCalendar.tsx b/src/screens/ai/AiLetterCalendar.tsx index df832d4..2a78f9b 100644 --- a/src/screens/ai/AiLetterCalendar.tsx +++ b/src/screens/ai/AiLetterCalendar.tsx @@ -1,7 +1,7 @@ import React, { useState, useCallback, useEffect, useRef } from 'react'; import { View, StyleSheet } from 'react-native'; import { format } from 'date-fns'; -import { IDate, IDay } from '@type/Diary'; +import { ICalendarModalDate, IDate, IDay } from '@type/Diary'; import { CalendarProvider } from 'react-native-calendars'; import AiLetterCalendarHeader from '@screens/ai/AiLetterCalendarHeader'; @@ -46,7 +46,7 @@ const AiLetterCalendar = ({ children, targetDateStr, onMonthChange }) => { [onMonthChange], ); - const handleMonthYearSelect = (month: number, year: number) => { + const handleMonthYearSelect = ({ month, year }: ICalendarModalDate) => { const formattedMonth = month.toString().padStart(2, '0') as IDate['month']; setSelectedDate((prevState) => ({ ...prevState, diff --git a/src/types/Diary.ts b/src/types/Diary.ts index be0ad48..d7a41b6 100644 --- a/src/types/Diary.ts +++ b/src/types/Diary.ts @@ -42,6 +42,11 @@ export interface IDay extends IDate { day: string; } +export interface ICalendarModalDate { + year: number; + month: number; +} + export interface IMarkedDates { [key: string]: { selected: boolean; From b39946c8d1b03def7d721cb329e6d9da4c834f76 Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Sat, 16 Nov 2024 22:37:16 +0900 Subject: [PATCH 12/25] =?UTF-8?q?refactor:=20=EB=82=A0=EC=A7=9C=20?= =?UTF-8?q?=EC=84=A0=ED=83=9D=20=EB=AA=A8=EB=8B=AC=20=EB=82=A0=EC=A7=9C=20?= =?UTF-8?q?prop=20=ED=95=A9=EC=B9=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../diary/calendar/CalendarHeader.tsx | 4 +- .../diary/calendar/CalendarSelectModal.tsx | 64 ++++++++++++------- src/screens/ai/AiLetterCalendarHeader.tsx | 38 +++++++---- 3 files changed, 68 insertions(+), 38 deletions(-) diff --git a/src/components/diary/calendar/CalendarHeader.tsx b/src/components/diary/calendar/CalendarHeader.tsx index 37396e0..8308e82 100644 --- a/src/components/diary/calendar/CalendarHeader.tsx +++ b/src/components/diary/calendar/CalendarHeader.tsx @@ -49,14 +49,14 @@ const CalendarHeader = ({ date }: { date: string }) => { {getDisplayDate(new Date(date))} {dateState !== 'TODAY' && } - + /> */} ); }; diff --git a/src/components/diary/calendar/CalendarSelectModal.tsx b/src/components/diary/calendar/CalendarSelectModal.tsx index 8810454..14924f3 100644 --- a/src/components/diary/calendar/CalendarSelectModal.tsx +++ b/src/components/diary/calendar/CalendarSelectModal.tsx @@ -11,28 +11,33 @@ import { StyleSheet, ScrollView, } from 'react-native'; +import { ICalendarModalDate } from '@type/Diary'; interface IMonthItem { - month: string; - index: number; + displayedMonth: string; + month: number; } interface ICalendarSelectModalProps { isModalVisible: boolean; handleModalDismiss: () => void; - selectedMonth: number; - selectedYear: number; - setSelectedMonth: (month: number) => void; - setSelectedYear: (year: number) => void; + // selectedMonth: number; + // selectedYear: number; + // setSelectedMonth: (month: number) => void; + // setSelectedYear: (year: number) => void; + selectedModalDate: ICalendarModalDate; + setSelectedModalDate: (date: ICalendarModalDate) => void; } const CalendarSelectModal = ({ isModalVisible, handleModalDismiss, - selectedMonth, - selectedYear, - setSelectedMonth, - setSelectedYear, + // selectedMonth, + // selectedYear, + // setSelectedMonth, + // setSelectedYear, + selectedModalDate, + setSelectedModalDate, }: ICalendarSelectModalProps) => { const monthScrollRef = useRef(null); const yearScrollRef = useRef(null); @@ -40,20 +45,33 @@ const CalendarSelectModal = ({ const monthItemHeight = 49; const yearItemHeight = 49; - const renderMonthItem = ({ month, index }: IMonthItem) => ( - setSelectedMonth(index + 1)}> - - - {month} + const renderMonthItem = ({ displayedMonth, month }: IMonthItem) => ( + setSelectedModalDate({ ...selectedModalDate, month })} + > + + + {displayedMonth} ); const renderYearItem = (year: number) => ( - setSelectedYear(year)}> - - + + setSelectedModalDate({ + ...selectedModalDate, + year, + }) + } + > + + {year} @@ -62,12 +80,12 @@ const CalendarSelectModal = ({ useEffect(() => { if (isModalVisible) { - const monthOffset = (selectedMonth - 1) * monthItemHeight - 120; - const yearOffset = (selectedYear - 2000) * yearItemHeight - 120; + const monthOffset = (selectedModalDate.month - 1) * monthItemHeight - 120; + const yearOffset = (selectedModalDate.year - 2000) * yearItemHeight - 120; monthScrollRef.current?.scrollTo({ y: monthOffset, animated: true }); yearScrollRef.current?.scrollTo({ y: yearOffset, animated: true }); } - }, [isModalVisible, selectedMonth, selectedYear]); + }, [isModalVisible, selectedModalDate]); return ( @@ -80,7 +98,9 @@ const CalendarSelectModal = ({ style={styles.modalMonth} showsVerticalScrollIndicator={false} > - {kMonth.map((month, index) => renderMonthItem({ month, index }))} + {kMonth.map((displayedMonth, index) => + renderMonthItem({ displayedMonth, month: index + 1 }), + )} void; onRightPress: () => void; - onMonthYearSelect: (month: number, year: number) => void; + onMonthYearSelect: (date: ICalendarModalDate) => void; onPressToday: () => void; isToday: boolean; } @@ -25,16 +25,24 @@ const AiLetterCalendarHeader = ({ onPressToday, }: AiLetterCalendarHeaderProps) => { const [isModalVisible, setModalVisible] = useState(false); - const [selectedMonth, setSelectedMonth] = useState(parseInt(selectedDate.month, 10)); - const [selectedYear, setSelectedYear] = useState(parseInt(selectedDate.year, 10)); + // const [selectedMonth, setSelectedMonth] = useState(parseInt(selectedDate.month, 10)); + // const [selectedYear, setSelectedYear] = useState(parseInt(selectedDate.year, 10)); + const [selectedModalDate, setSelectedModalDate] = useState({ + month: parseInt(selectedDate.month, 10), + year: parseInt(selectedDate.year, 10), + }); useEffect(() => { - setSelectedMonth(parseInt(selectedDate.month, 10)); - setSelectedYear(parseInt(selectedDate.year, 10)); + // setSelectedMonth(parseInt(selectedDate.month, 10)); + // setSelectedYear(parseInt(selectedDate.year, 10)); + const year = parseInt(selectedDate.year, 10); + const month = parseInt(selectedDate.month, 10); + setSelectedModalDate({ year, month }); }, [selectedDate]); const handleModalDismiss = () => { - onMonthYearSelect(selectedMonth, selectedYear); + // onMonthYearSelect(selectedMonth, selectedYear); + onMonthYearSelect(selectedModalDate); setModalVisible(false); }; @@ -42,9 +50,9 @@ const AiLetterCalendarHeader = ({ setModalVisible(true)}> - {`${ - kMonth[selectedMonth - 1] - } ${selectedYear}`} + {`${kMonth[selectedModalDate.month - 1]} ${ + selectedModalDate.year + }`} {!isToday && } @@ -60,10 +68,12 @@ const AiLetterCalendarHeader = ({ ); From dca16235a0f6a8e7567c7f7d0bbf503eac67051b Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Sat, 16 Nov 2024 22:56:53 +0900 Subject: [PATCH 13/25] =?UTF-8?q?refactor:=20calendar=20modal=20hook=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 --- .../diary/calendar/CalendarSelectModal.tsx | 8 ------- src/hooks/common/useCalendarModal.ts | 16 +++++++++++++ src/screens/ai/AiLetterCalendar.tsx | 2 +- src/screens/ai/AiLetterCalendarHeader.tsx | 23 ++++++------------- 4 files changed, 24 insertions(+), 25 deletions(-) create mode 100644 src/hooks/common/useCalendarModal.ts diff --git a/src/components/diary/calendar/CalendarSelectModal.tsx b/src/components/diary/calendar/CalendarSelectModal.tsx index 14924f3..6a6b3e6 100644 --- a/src/components/diary/calendar/CalendarSelectModal.tsx +++ b/src/components/diary/calendar/CalendarSelectModal.tsx @@ -21,10 +21,6 @@ interface IMonthItem { interface ICalendarSelectModalProps { isModalVisible: boolean; handleModalDismiss: () => void; - // selectedMonth: number; - // selectedYear: number; - // setSelectedMonth: (month: number) => void; - // setSelectedYear: (year: number) => void; selectedModalDate: ICalendarModalDate; setSelectedModalDate: (date: ICalendarModalDate) => void; } @@ -32,10 +28,6 @@ interface ICalendarSelectModalProps { const CalendarSelectModal = ({ isModalVisible, handleModalDismiss, - // selectedMonth, - // selectedYear, - // setSelectedMonth, - // setSelectedYear, selectedModalDate, setSelectedModalDate, }: ICalendarSelectModalProps) => { diff --git a/src/hooks/common/useCalendarModal.ts b/src/hooks/common/useCalendarModal.ts new file mode 100644 index 0000000..408fd84 --- /dev/null +++ b/src/hooks/common/useCalendarModal.ts @@ -0,0 +1,16 @@ +import React, { useState } from 'react'; +import { ICalendarModalDate } from '@type/Diary'; + +const useCalendarModal = ({ month, year }: ICalendarModalDate) => { + const [isModalVisible, setModalVisible] = useState(false); + const [selectedModalDate, setSelectedModalDate] = useState({ month, year }); + + return { + isModalVisible, + setModalVisible, + selectedModalDate, + setSelectedModalDate, + }; +}; + +export default useCalendarModal; diff --git a/src/screens/ai/AiLetterCalendar.tsx b/src/screens/ai/AiLetterCalendar.tsx index 2a78f9b..bd07b55 100644 --- a/src/screens/ai/AiLetterCalendar.tsx +++ b/src/screens/ai/AiLetterCalendar.tsx @@ -1,4 +1,4 @@ -import React, { useState, useCallback, useEffect, useRef } from 'react'; +import React, { useState, useCallback, useEffect } from 'react'; import { View, StyleSheet } from 'react-native'; import { format } from 'date-fns'; import { ICalendarModalDate, IDate, IDay } from '@type/Diary'; diff --git a/src/screens/ai/AiLetterCalendarHeader.tsx b/src/screens/ai/AiLetterCalendarHeader.tsx index 829b038..7b2181a 100644 --- a/src/screens/ai/AiLetterCalendarHeader.tsx +++ b/src/screens/ai/AiLetterCalendarHeader.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect } from 'react'; +import React, { useEffect } from 'react'; import { View, StyleSheet, Pressable } from 'react-native'; import CalendarArrow from '@components/diary/calendar/CalendarArrow'; import { ICalendarModalDate, IDay } from '@type/Diary'; @@ -6,6 +6,7 @@ import MyText from '@components/common/MyText'; import TodayButton from '@components/common/TodayButton'; import CalendarSelectModal from '@components/diary/calendar/CalendarSelectModal'; import { kMonth } from '@utils/localeConfig'; +import useCalendarModal from '@hooks/common/useCalendarModal'; interface AiLetterCalendarHeaderProps { selectedDate: IDay; @@ -24,24 +25,19 @@ const AiLetterCalendarHeader = ({ isToday, onPressToday, }: AiLetterCalendarHeaderProps) => { - const [isModalVisible, setModalVisible] = useState(false); - // const [selectedMonth, setSelectedMonth] = useState(parseInt(selectedDate.month, 10)); - // const [selectedYear, setSelectedYear] = useState(parseInt(selectedDate.year, 10)); - const [selectedModalDate, setSelectedModalDate] = useState({ - month: parseInt(selectedDate.month, 10), - year: parseInt(selectedDate.year, 10), - }); + const { isModalVisible, setModalVisible, selectedModalDate, setSelectedModalDate } = + useCalendarModal({ + month: parseInt(selectedDate.month, 10), + year: parseInt(selectedDate.year, 10), + }); useEffect(() => { - // setSelectedMonth(parseInt(selectedDate.month, 10)); - // setSelectedYear(parseInt(selectedDate.year, 10)); const year = parseInt(selectedDate.year, 10); const month = parseInt(selectedDate.month, 10); setSelectedModalDate({ year, month }); }, [selectedDate]); const handleModalDismiss = () => { - // onMonthYearSelect(selectedMonth, selectedYear); onMonthYearSelect(selectedModalDate); setModalVisible(false); }; @@ -64,14 +60,9 @@ const AiLetterCalendarHeader = ({ - {/* Month and Year Modal */} From 91a896b71ff79cd898fb311cb10a58d5f5961a2b Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Sat, 16 Nov 2024 23:32:56 +0900 Subject: [PATCH 14/25] =?UTF-8?q?feat:=20=EC=A1=B0=EA=B0=81=EC=B0=BD=20?= =?UTF-8?q?=ED=97=A4=EB=8D=94=20=EB=AA=A8=EB=8B=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../diary/calendar/CalendarHeader.tsx | 22 ++++---- src/hooks/common/useCalendarModal.ts | 2 +- src/screens/report/NewReportView.tsx | 52 +++++++++++-------- 3 files changed, 42 insertions(+), 34 deletions(-) diff --git a/src/components/diary/calendar/CalendarHeader.tsx b/src/components/diary/calendar/CalendarHeader.tsx index 8308e82..dcc817a 100644 --- a/src/components/diary/calendar/CalendarHeader.tsx +++ b/src/components/diary/calendar/CalendarHeader.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React from 'react'; import { View, StyleSheet } from 'react-native'; import MyText from '@components/common/MyText'; import TextButton from '@components/common/TextButton'; @@ -9,16 +9,20 @@ import { selectedDateStatus, tense } from '@stores/tense'; import { fontLarge } from '@utils/Sizing'; import TodayButton from '@components/common/TodayButton'; import { getToday } from '@utils/dateUtils'; +import useCalendarModal from '@hooks/common/useCalendarModal'; const CalendarHeader = ({ date }: { date: string }) => { const dateState = useRecoilValue(tense); - const [isModalVisible, setModalVisible] = useState(false); const [selectedDate, setSelectedDate] = useRecoilState(selectedDateStatus); - const [selectedMonth, setSelectedMonth] = useState(parseInt(selectedDate.slice(5, 7), 10)); - const [selectedYear, setSelectedYear] = useState(parseInt(selectedDate.slice(0, 4), 10)); + const { isModalVisible, setModalVisible, selectedModalDate, setSelectedModalDate } = + useCalendarModal({ + month: parseInt(selectedDate.slice(5, 7), 10), + year: parseInt(selectedDate.slice(0, 4), 10), + }); const handleModalDismiss = () => { const day = selectedDate.slice(8, 10); + const { year: selectedYear, month: selectedMonth } = selectedModalDate; const lastDay = new Date(selectedYear, selectedMonth, 0).getDate(); const month = selectedMonth.toString().padStart(2, '0'); if (parseInt(day, 10) > lastDay) { @@ -49,14 +53,12 @@ const CalendarHeader = ({ date }: { date: string }) => { {getDisplayDate(new Date(date))} {dateState !== 'TODAY' && } - {/* */} + selectedModalDate={selectedModalDate} + setSelectedModalDate={setSelectedModalDate} + /> ); }; diff --git a/src/hooks/common/useCalendarModal.ts b/src/hooks/common/useCalendarModal.ts index 408fd84..4a288bb 100644 --- a/src/hooks/common/useCalendarModal.ts +++ b/src/hooks/common/useCalendarModal.ts @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import { useState } from 'react'; import { ICalendarModalDate } from '@type/Diary'; const useCalendarModal = ({ month, year }: ICalendarModalDate) => { diff --git a/src/screens/report/NewReportView.tsx b/src/screens/report/NewReportView.tsx index 8d8d079..eeb81eb 100644 --- a/src/screens/report/NewReportView.tsx +++ b/src/screens/report/NewReportView.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { View, StyleSheet, Pressable, ScrollView, SafeAreaView } from 'react-native'; import { fontMedium, fontLarge } from '@utils/Sizing'; import CalendarArrow from '@components/diary/calendar/CalendarArrow'; @@ -7,24 +7,26 @@ import NewChartView from '@screens/report/NewChartView'; import { appColor1 } from '@utils/colors'; import CalendarSelectModal from '@components/diary/calendar/CalendarSelectModal'; import { kMonth } from '@utils/localeConfig'; +import useCalendarModal from '@hooks/common/useCalendarModal'; +import { ICalendarModalDate } from '@type/Diary'; function NewReportView() { - const [isModalVisible, setModalVisible] = useState(false); - const [selectedDate, setSelectedDate] = useState(new Date().toISOString().slice(0, 10)); - const [selectedMonth, setSelectedMonth] = useState( - parseInt(selectedDate.slice(5, 7), 10), - ); - const [selectedYear, setSelectedYear] = useState(parseInt(selectedDate.slice(0, 4), 10)); + const [selectedDate, setSelectedDate] = useState({ + month: new Date().getMonth() + 1, + year: new Date().getFullYear(), + }); + const { isModalVisible, setModalVisible, selectedModalDate, setSelectedModalDate } = + useCalendarModal({ + month: selectedDate.month, + year: selectedDate.year, + }); + + useEffect(() => { + setSelectedModalDate(selectedDate); + }, [selectedDate]); const handleModalDismiss = () => { - const day = selectedDate.slice(8, 10); - const lastDay = new Date(selectedYear, selectedMonth, 0).getDate(); - const month = selectedMonth.toString().padStart(2, '0'); - if (parseInt(day, 10) > lastDay) { - setSelectedDate(`${selectedYear}-${month}-${lastDay}`); - } else { - setSelectedDate(`${selectedYear}-${month}-${day}`); - } + setSelectedDate(selectedModalDate); setModalVisible(false); }; @@ -33,11 +35,17 @@ function NewReportView() { }; const onLeftPress = () => { - selectedMonth === 1 ? setSelectedMonth(12) : setSelectedMonth(selectedMonth - 1); + const { month, year } = selectedDate; + month === 1 + ? setSelectedDate({ month: 12, year: year - 1 }) + : setSelectedDate({ month: month - 1, year }); }; const onRightPress = () => { - selectedMonth === 11 ? setSelectedMonth(1) : setSelectedMonth(selectedMonth + 1); + const { month, year } = selectedDate; + month === 12 + ? setSelectedDate({ month: 1, year: year + 1 }) + : setSelectedDate({ month: month + 1, year }); }; const keyword = '건강'; @@ -53,16 +61,14 @@ function NewReportView() { - {kMonth[selectedMonth - 1]}의 기억 조각 + {kMonth[selectedDate.month - 1]}의 기억 조각 @@ -74,7 +80,7 @@ function NewReportView() { > - {kMonth[selectedMonth - 1]}에 가장 많이 언급한 단어를 모아봤어요. + {kMonth[selectedDate.month - 1]}에 가장 많이 언급한 단어를 모아봤어요. From aada49d212e179291a577148f7aa88b6042f77c1 Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Sun, 17 Nov 2024 00:00:31 +0900 Subject: [PATCH 15/25] =?UTF-8?q?refactor:=20report=20header=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/screens/report/NewReportView.tsx | 62 ++------------------- src/screens/report/ReportHeader.tsx | 83 ++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 57 deletions(-) create mode 100644 src/screens/report/ReportHeader.tsx diff --git a/src/screens/report/NewReportView.tsx b/src/screens/report/NewReportView.tsx index eeb81eb..87dcbc5 100644 --- a/src/screens/report/NewReportView.tsx +++ b/src/screens/report/NewReportView.tsx @@ -1,52 +1,18 @@ -import React, { useEffect, useState } from 'react'; -import { View, StyleSheet, Pressable, ScrollView, SafeAreaView } from 'react-native'; -import { fontMedium, fontLarge } from '@utils/Sizing'; -import CalendarArrow from '@components/diary/calendar/CalendarArrow'; +import React, { useState } from 'react'; +import { View, StyleSheet, ScrollView, SafeAreaView } from 'react-native'; +import { fontMedium } from '@utils/Sizing'; import MyText from '@components/common/MyText'; import NewChartView from '@screens/report/NewChartView'; import { appColor1 } from '@utils/colors'; -import CalendarSelectModal from '@components/diary/calendar/CalendarSelectModal'; import { kMonth } from '@utils/localeConfig'; -import useCalendarModal from '@hooks/common/useCalendarModal'; import { ICalendarModalDate } from '@type/Diary'; +import ReportHeader from './ReportHeader'; function NewReportView() { const [selectedDate, setSelectedDate] = useState({ month: new Date().getMonth() + 1, year: new Date().getFullYear(), }); - const { isModalVisible, setModalVisible, selectedModalDate, setSelectedModalDate } = - useCalendarModal({ - month: selectedDate.month, - year: selectedDate.year, - }); - - useEffect(() => { - setSelectedModalDate(selectedDate); - }, [selectedDate]); - - const handleModalDismiss = () => { - setSelectedDate(selectedModalDate); - setModalVisible(false); - }; - - const onHeaderPress = () => { - setModalVisible(true); - }; - - const onLeftPress = () => { - const { month, year } = selectedDate; - month === 1 - ? setSelectedDate({ month: 12, year: year - 1 }) - : setSelectedDate({ month: month - 1, year }); - }; - - const onRightPress = () => { - const { month, year } = selectedDate; - month === 12 - ? setSelectedDate({ month: 1, year: year + 1 }) - : setSelectedDate({ month: month + 1, year }); - }; const keyword = '건강'; const content = `날씨가 추워질수록 건강에 대한 언급이 많아졌어요. 다음주부터는 더 춥다고 하니, 따뜻하게 입는다면 건강에 대한 걱정이 덜 할 것 같아요. @@ -55,25 +21,7 @@ function NewReportView() { return ( - - - - - - - {kMonth[selectedDate.month - 1]}의 기억 조각 - - - - - - - + >; +} + +function ReportHeader({ selectedDate, setSelectedDate }: IReportHeaderProps) { + const { isModalVisible, setModalVisible, selectedModalDate, setSelectedModalDate } = + useCalendarModal({ + month: selectedDate.month, + year: selectedDate.year, + }); + + useEffect(() => { + setSelectedModalDate(selectedDate); + }, [selectedDate]); + + const handleModalDismiss = () => { + setSelectedDate(selectedModalDate); + setModalVisible(false); + }; + + const onHeaderPress = () => { + setModalVisible(true); + }; + + const onLeftPress = () => { + const { month, year } = selectedDate; + month === 1 + ? setSelectedDate({ month: 12, year: year - 1 }) + : setSelectedDate({ month: month - 1, year }); + }; + + const onRightPress = () => { + const { month, year } = selectedDate; + month === 12 + ? setSelectedDate({ month: 1, year: year + 1 }) + : setSelectedDate({ month: month + 1, year }); + }; + + return ( + + + + + + + {kMonth[selectedDate.month - 1]}의 기억 조각 + + + + + + + + ); +} + +const styles = StyleSheet.create({ + container: { + alignItems: 'center', + paddingVertical: 20, + flexDirection: 'row', + justifyContent: 'space-between', + minWidth: '80%', + }, +}); + +export default ReportHeader; From 659405f1297c1a78ad23a7a4b91ad831e261f2f9 Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Fri, 22 Nov 2024 18:40:20 +0900 Subject: [PATCH 16/25] =?UTF-8?q?refacor:=20=ED=82=A4=EC=9B=8C=EB=93=9C=20?= =?UTF-8?q?=EB=82=B4=EC=9A=A9=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=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 --- src/screens/report/NewReportContent.tsx | 33 +++++++++++++++++++++++++ src/screens/report/NewReportView.tsx | 20 +++------------ 2 files changed, 36 insertions(+), 17 deletions(-) create mode 100644 src/screens/report/NewReportContent.tsx diff --git a/src/screens/report/NewReportContent.tsx b/src/screens/report/NewReportContent.tsx new file mode 100644 index 0000000..2f1c0d8 --- /dev/null +++ b/src/screens/report/NewReportContent.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import { View, StyleSheet, ScrollView } from 'react-native'; +import MyText from '@components/common/MyText'; +import { fontMedium } from '@utils/Sizing'; +import { appColor1 } from '@utils/colors'; + +const NewReportContent = ({ keyword, content }) => { + return ( + + + {keyword} + + + {content} + + + ); +}; + +const styles = StyleSheet.create({ + container: { + backgroundColor: appColor1, + borderWidth: 1, + borderRadius: 12, + alignItems: 'flex-start', + flexDirection: 'column', + padding: 16, + width: '100%', + flexGrow: 1, + }, +}); + +export default NewReportContent; diff --git a/src/screens/report/NewReportView.tsx b/src/screens/report/NewReportView.tsx index 87dcbc5..7dd49f0 100644 --- a/src/screens/report/NewReportView.tsx +++ b/src/screens/report/NewReportView.tsx @@ -1,12 +1,12 @@ import React, { useState } from 'react'; import { View, StyleSheet, ScrollView, SafeAreaView } from 'react-native'; -import { fontMedium } from '@utils/Sizing'; import MyText from '@components/common/MyText'; import NewChartView from '@screens/report/NewChartView'; import { appColor1 } from '@utils/colors'; import { kMonth } from '@utils/localeConfig'; import { ICalendarModalDate } from '@type/Diary'; import ReportHeader from './ReportHeader'; +import NewReportContent from './NewReportContent'; function NewReportView() { const [selectedDate, setSelectedDate] = useState({ @@ -16,7 +16,7 @@ function NewReportView() { const keyword = '건강'; const content = `날씨가 추워질수록 건강에 대한 언급이 많아졌어요. 다음주부터는 더 춥다고 하니, 따뜻하게 입는다면 건강에 대한 걱정이 덜 할 것 같아요. - 목을 따뜻하게 감싸면 체온이 3도 이상 올라가는 효과가 있다고 해요. 저번에 지수에게 선물받은 부드러운 앙고라 목도리를 해보는건 어떤가요?`; + 목을 따뜻하게 감싸면 체온이 3도 이상 올라가는 효과가 있다고 해요. 저번에 지수에게 선물받은 부드러운 앙고라 목도리를 해보는건 어떤가요?`; return ( @@ -30,14 +30,7 @@ function NewReportView() { {kMonth[selectedDate.month - 1]}에 가장 많이 언급한 단어를 모아봤어요. - - - {keyword} - - - {content} - - + @@ -51,13 +44,6 @@ const styles = StyleSheet.create({ alignItems: 'center', paddingHorizontal: 16, }, - header: { - alignItems: 'center', - paddingVertical: 20, - flexDirection: 'row', - justifyContent: 'space-between', - minWidth: '80%', - }, mainContainer: { flexGrow: 1, alignItems: 'center', From edebc78fad509172cfcc88b5cb7d3ef289b63efa Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Fri, 22 Nov 2024 19:35:10 +0900 Subject: [PATCH 17/25] test: report mock data fetch --- src/api/report/get.ts | 35 ++++++++++++++++++++++++++++++- src/hooks/report/useReportData.ts | 13 ++++++++++++ src/types/IReport.ts | 9 ++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/hooks/report/useReportData.ts diff --git a/src/api/report/get.ts b/src/api/report/get.ts index d2682f8..a1d1ab6 100644 --- a/src/api/report/get.ts +++ b/src/api/report/get.ts @@ -1,5 +1,5 @@ import instance from '@api/axios'; -import { DayEmotionData, EmotionData } from '@type/IReport'; +import { DayEmotionData, EmotionData, IReportData } from '@type/IReport'; export const fetchWeekReport = async (targetDate: string): Promise => { const response = await instance.get(`/report/week?targetDate=${targetDate}`); @@ -10,3 +10,36 @@ export const fetchReportPNN = async (targetDate: string): Promise => { + console.log(`fetchMockReportData: ${targetDate}`); + return [ + { + rate: 0.3, + keyword: '건강', + content: + '날씨가 추워질수록 건강에 대한 언급이 많아졌어요. 다음주부터는 더 춥다고 하니, 따뜻하게 입는다면 건강에 대한 걱정이 덜 할 것 같아요.', + }, + { + rate: 0.2, + keyword: '영화', + content: '영화를 보는 것은 영화를 보는 것이 아니라 영화를 보는 것입니다.', + }, + { + rate: 0.15, + keyword: '날씨', + content: + '날씨가 추워질수록 건강에 대한 언급이 많아졌어요. 다음주부터는 더 춥다고 하니, 따뜻하게 입는다면 건강에 대한 걱정이 덜 할 것 같아요.', + }, + { + rate: 0.15, + keyword: '요리하다', + content: '요리하다는 것은 요리하는 것이 아니라 요리하는 것입니다.', + }, + { + rate: 0.1, + keyword: '독서', + content: '독서는 독서하는 것이 아니라 독서하는 것입니다.', + }, + ]; +}; diff --git a/src/hooks/report/useReportData.ts b/src/hooks/report/useReportData.ts new file mode 100644 index 0000000..af0835c --- /dev/null +++ b/src/hooks/report/useReportData.ts @@ -0,0 +1,13 @@ +import { useQuery } from '@tanstack/react-query'; +import { fetchMockReportData } from '@api/report/get'; +import { ICalendarModalDate } from '@type/Diary'; + +const useReportData = (selectedDate: ICalendarModalDate) => { + return useQuery({ + queryKey: ['report', selectedDate], + queryFn: () => + fetchMockReportData(`${selectedDate.year}${selectedDate.month.toString().padStart(2, '0')}`), + }); +}; + +export default useReportData; diff --git a/src/types/IReport.ts b/src/types/IReport.ts index 03427e4..b8fd67e 100644 --- a/src/types/IReport.ts +++ b/src/types/IReport.ts @@ -25,3 +25,12 @@ export interface DayEmotionData { negativeTotalCnt: number; negativeSummary: string; } + +export interface IReportContent { + keyword: string; + content: string; +} + +export interface IReportData extends IReportContent { + rate: number; +} From eb634678aaa365ee3c3492ae1da3f51a8a95d402 Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Fri, 22 Nov 2024 19:45:30 +0900 Subject: [PATCH 18/25] =?UTF-8?q?test:=20keyword=20=EB=82=B4=EC=9A=A9=20fe?= =?UTF-8?q?tch?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/report/get.ts | 76 +++++++++++++++++++------------ src/hooks/report/useReportData.ts | 21 +++++++-- 2 files changed, 64 insertions(+), 33 deletions(-) diff --git a/src/api/report/get.ts b/src/api/report/get.ts index a1d1ab6..ffe1c0a 100644 --- a/src/api/report/get.ts +++ b/src/api/report/get.ts @@ -1,5 +1,5 @@ import instance from '@api/axios'; -import { DayEmotionData, EmotionData, IReportData } from '@type/IReport'; +import { DayEmotionData, EmotionData, IReportContent, IReportData } from '@type/IReport'; export const fetchWeekReport = async (targetDate: string): Promise => { const response = await instance.get(`/report/week?targetDate=${targetDate}`); @@ -11,35 +11,51 @@ export const fetchReportPNN = async (targetDate: string): Promise => { console.log(`fetchMockReportData: ${targetDate}`); - return [ - { - rate: 0.3, - keyword: '건강', - content: - '날씨가 추워질수록 건강에 대한 언급이 많아졌어요. 다음주부터는 더 춥다고 하니, 따뜻하게 입는다면 건강에 대한 걱정이 덜 할 것 같아요.', - }, - { - rate: 0.2, - keyword: '영화', - content: '영화를 보는 것은 영화를 보는 것이 아니라 영화를 보는 것입니다.', - }, - { - rate: 0.15, - keyword: '날씨', - content: - '날씨가 추워질수록 건강에 대한 언급이 많아졌어요. 다음주부터는 더 춥다고 하니, 따뜻하게 입는다면 건강에 대한 걱정이 덜 할 것 같아요.', - }, - { - rate: 0.15, - keyword: '요리하다', - content: '요리하다는 것은 요리하는 것이 아니라 요리하는 것입니다.', - }, - { - rate: 0.1, - keyword: '독서', - content: '독서는 독서하는 것이 아니라 독서하는 것입니다.', - }, - ]; + return mockReportData; +}; + +export const fetchMockReportKeyword = async ({ + targetDate, + rank, +}: { + targetDate: string; + rank: number; +}): Promise => { + console.log(`fetchMockReportKeyword: ${targetDate}, ${rank}`); + return { + keyword: mockReportData[rank].keyword, + content: mockReportData[rank].content, + }; }; diff --git a/src/hooks/report/useReportData.ts b/src/hooks/report/useReportData.ts index af0835c..1fd874f 100644 --- a/src/hooks/report/useReportData.ts +++ b/src/hooks/report/useReportData.ts @@ -1,8 +1,8 @@ import { useQuery } from '@tanstack/react-query'; -import { fetchMockReportData } from '@api/report/get'; +import { fetchMockReportData, fetchMockReportKeyword } from '@api/report/get'; import { ICalendarModalDate } from '@type/Diary'; -const useReportData = (selectedDate: ICalendarModalDate) => { +export const useReportData = (selectedDate: ICalendarModalDate) => { return useQuery({ queryKey: ['report', selectedDate], queryFn: () => @@ -10,4 +10,19 @@ const useReportData = (selectedDate: ICalendarModalDate) => { }); }; -export default useReportData; +export const useReportKeyword = ({ + selectedDate, + rank, +}: { + selectedDate: ICalendarModalDate; + rank: number; +}) => { + return useQuery({ + queryKey: ['report', selectedDate], + queryFn: () => + fetchMockReportKeyword({ + targetDate: `${selectedDate.year}${selectedDate.month.toString().padStart(2, '0')}`, + rank: rank, + }), + }); +}; From 806b751e581c6ff9865480d6d61c6614fec15645 Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Fri, 22 Nov 2024 21:15:08 +0900 Subject: [PATCH 19/25] =?UTF-8?q?feat:=20hover=20style=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9=20pressablae=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8?= =?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/common/MyPressable.tsx | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/components/common/MyPressable.tsx diff --git a/src/components/common/MyPressable.tsx b/src/components/common/MyPressable.tsx new file mode 100644 index 0000000..7e72d19 --- /dev/null +++ b/src/components/common/MyPressable.tsx @@ -0,0 +1,25 @@ +import React, { ReactNode } from 'react'; +import { Pressable, PressableProps, ViewStyle } from 'react-native'; + +interface IMyPressableProps extends PressableProps { + children: ReactNode; + containerStyle?: ViewStyle; +} + +function MyPressable({ children, containerStyle, ...pressableProps }: IMyPressableProps) { + return ( + [ + state.pressed && { opacity: 0.5 }, + state.hovered && { backgroundColor: 'rgba(31, 27, 21, 0.06)' }, + !pressableProps.onPress && { cursor: 'default' }, + containerStyle, + ]} + > + {children} + + ); +} + +export default MyPressable; From 57bd38162925d08ef2e68c35d555f79ad237601e Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Fri, 22 Nov 2024 21:21:47 +0900 Subject: [PATCH 20/25] =?UTF-8?q?fix:=20queryKey=20=EB=B0=8F=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/report/get.ts | 4 ++-- src/hooks/report/useReportData.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/api/report/get.ts b/src/api/report/get.ts index ffe1c0a..304c5f1 100644 --- a/src/api/report/get.ts +++ b/src/api/report/get.ts @@ -55,7 +55,7 @@ export const fetchMockReportKeyword = async ({ }): Promise => { console.log(`fetchMockReportKeyword: ${targetDate}, ${rank}`); return { - keyword: mockReportData[rank].keyword, - content: mockReportData[rank].content, + keyword: mockReportData[rank - 1].keyword, + content: mockReportData[rank - 1].content, }; }; diff --git a/src/hooks/report/useReportData.ts b/src/hooks/report/useReportData.ts index 1fd874f..f52d437 100644 --- a/src/hooks/report/useReportData.ts +++ b/src/hooks/report/useReportData.ts @@ -4,7 +4,7 @@ import { ICalendarModalDate } from '@type/Diary'; export const useReportData = (selectedDate: ICalendarModalDate) => { return useQuery({ - queryKey: ['report', selectedDate], + queryKey: ['reportList', selectedDate], queryFn: () => fetchMockReportData(`${selectedDate.year}${selectedDate.month.toString().padStart(2, '0')}`), }); @@ -18,7 +18,7 @@ export const useReportKeyword = ({ rank: number; }) => { return useQuery({ - queryKey: ['report', selectedDate], + queryKey: ['reportKeyword', selectedDate, rank], queryFn: () => fetchMockReportKeyword({ targetDate: `${selectedDate.year}${selectedDate.month.toString().padStart(2, '0')}`, From d0f947c94c2bef1525b817d6edd68dba30d6d4ff Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Fri, 22 Nov 2024 21:22:28 +0900 Subject: [PATCH 21/25] =?UTF-8?q?feat:=20=ED=82=A4=EC=9B=8C=EB=93=9C=20?= =?UTF-8?q?=EC=88=9C=EC=9C=84=20=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/screens/report/KeywordRank.tsx | 42 ++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/screens/report/KeywordRank.tsx diff --git a/src/screens/report/KeywordRank.tsx b/src/screens/report/KeywordRank.tsx new file mode 100644 index 0000000..950431e --- /dev/null +++ b/src/screens/report/KeywordRank.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import { StyleSheet, View } from 'react-native'; +import MyText from '@components/common/MyText'; +import MyPressable from '@components/common/MyPressable'; +import { fontMedium } from '@utils/Sizing'; + +interface IKeywordRankProps { + keywords: string[]; + onKeywordPress: (rank: number) => void; +} + +function KeywordRank({ keywords, onKeywordPress }: IKeywordRankProps) { + return ( + + {keywords.map((keyword, index) => ( + onKeywordPress(index + 1)} + containerStyle={styles.item} + > + {`${index + 1}. ${keyword}`} + + ))} + + ); +} + +const styles = StyleSheet.create({ + container: { + alignItems: 'flex-start', + flexDirection: 'column', + flexGrow: 1, + paddingHorizontal: 16, + width: '100%', + }, + item: { + padding: 8, + width: '100%', + }, +}); + +export default KeywordRank; From 19fccba98729cfba5cb2fd32819a09f8d03edad5 Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Fri, 22 Nov 2024 21:23:39 +0900 Subject: [PATCH 22/25] =?UTF-8?q?feat:=20=ED=82=A4=EC=9B=8C=EB=93=9C=20?= =?UTF-8?q?=EB=88=84=EB=A5=B4=EB=A9=B4=20=ED=95=B4=EB=8B=B9=20=EB=82=B4?= =?UTF-8?q?=EC=9A=A9=20=EB=A0=8C=EB=8D=94=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/screens/report/NewChartView.web.tsx | 25 ++++++--- src/screens/report/NewReportContent.tsx | 42 ++++++++++++--- src/screens/report/NewReportView.tsx | 27 ++-------- src/screens/report/ReportMain.tsx | 71 +++++++++++++++++++++++++ 4 files changed, 127 insertions(+), 38 deletions(-) create mode 100644 src/screens/report/ReportMain.tsx diff --git a/src/screens/report/NewChartView.web.tsx b/src/screens/report/NewChartView.web.tsx index fae82a5..69a7afc 100644 --- a/src/screens/report/NewChartView.web.tsx +++ b/src/screens/report/NewChartView.web.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { Dispatch, SetStateAction } from 'react'; import { View, StyleSheet } from 'react-native'; import { Chart as ChartJS, @@ -14,6 +14,7 @@ import ChartDataLabels from 'chartjs-plugin-datalabels'; import { Doughnut } from 'react-chartjs-2'; import { pieColors } from '@utils/colors'; import { fontBasic } from '@utils/Sizing'; +import { IReportData } from '@type/IReport'; ChartJS.register( RadialLinearScale, @@ -26,12 +27,17 @@ ChartJS.register( ChartDataLabels, ); -function NewChartView() { +interface INewChartViewProps { + chartData: IReportData[]; + setSelectedRank: Dispatch>; +} + +function NewChartView({ chartData, setSelectedRank }: INewChartViewProps) { const data = { - labels: ['엄청나게 긴 단어라고 합니다', '영화', '날씨', '요리하다', '독서'], + labels: chartData.map((item) => item.keyword), datasets: [ { - data: [30, 20, 20, 15, 15], + data: chartData.map((item) => item.rate), backgroundColor: pieColors, }, ], @@ -40,6 +46,12 @@ function NewChartView() { const options = { responsive: true, cutout: '40%', + onClick: (event: any, elements: any[]) => { + if (elements.length > 0) { + const clickedIndex = elements[0].index; + setSelectedRank(clickedIndex + 1); + } + }, plugins: { datalabels: { display: true, @@ -73,7 +85,7 @@ function NewChartView() { callbacks: { label: function (tooltipItem: any) { const label = tooltipItem.label || ''; - return `${label}: ${tooltipItem.raw}번`; + return `${label}: ${tooltipItem.raw * 100}%`; }, }, }, @@ -93,11 +105,10 @@ function NewChartView() { const styles = StyleSheet.create({ chart: { flex: 1, - marginTop: 16, + marginVertical: 16, width: '100%', justifyContent: 'center', alignItems: 'center', - minHeight: 200, }, }); diff --git a/src/screens/report/NewReportContent.tsx b/src/screens/report/NewReportContent.tsx index 2f1c0d8..3b58bf7 100644 --- a/src/screens/report/NewReportContent.tsx +++ b/src/screens/report/NewReportContent.tsx @@ -1,19 +1,47 @@ -import React from 'react'; -import { View, StyleSheet, ScrollView } from 'react-native'; +import React, { Dispatch, SetStateAction, useEffect } from 'react'; +import { StyleSheet, ScrollView, Pressable } from 'react-native'; import MyText from '@components/common/MyText'; import { fontMedium } from '@utils/Sizing'; import { appColor1 } from '@utils/colors'; +import { ICalendarModalDate } from '@type/Diary'; +import { useReportKeyword } from '@hooks/report/useReportData'; +import ReportLoadingView from './ReportLoadingView'; +import ReportErrorView from './ReportErrorView'; + +interface INewReportContentProps { + selectedDate: ICalendarModalDate; + rank: number; + setSelectedRank: Dispatch>; +} + +const NewReportContent = ({ selectedDate, rank, setSelectedRank }: INewReportContentProps) => { + const { data, isPending, isError } = useReportKeyword({ selectedDate, rank }); + + useEffect(() => { + console.log(`rank: ${rank}`); + console.log(data); + }, [rank, data]); + + const onPress = () => { + setSelectedRank(null); + }; + + if (isPending) { + return ; + } + if (isError || !data) { + return ; + } -const NewReportContent = ({ keyword, content }) => { return ( - + - {keyword} + {data?.keyword} - {content} + {data?.content} - + ); }; diff --git a/src/screens/report/NewReportView.tsx b/src/screens/report/NewReportView.tsx index 7dd49f0..d97f3de 100644 --- a/src/screens/report/NewReportView.tsx +++ b/src/screens/report/NewReportView.tsx @@ -1,12 +1,8 @@ import React, { useState } from 'react'; import { View, StyleSheet, ScrollView, SafeAreaView } from 'react-native'; -import MyText from '@components/common/MyText'; -import NewChartView from '@screens/report/NewChartView'; -import { appColor1 } from '@utils/colors'; -import { kMonth } from '@utils/localeConfig'; import { ICalendarModalDate } from '@type/Diary'; import ReportHeader from './ReportHeader'; -import NewReportContent from './NewReportContent'; +import ReportMain from './ReportMain'; function NewReportView() { const [selectedDate, setSelectedDate] = useState({ @@ -14,10 +10,6 @@ function NewReportView() { year: new Date().getFullYear(), }); - const keyword = '건강'; - const content = `날씨가 추워질수록 건강에 대한 언급이 많아졌어요. 다음주부터는 더 춥다고 하니, 따뜻하게 입는다면 건강에 대한 걱정이 덜 할 것 같아요. - 목을 따뜻하게 감싸면 체온이 3도 이상 올라가는 효과가 있다고 해요. 저번에 지수에게 선물받은 부드러운 앙고라 목도리를 해보는건 어떤가요?`; - return ( @@ -25,12 +17,9 @@ function NewReportView() { - - - {kMonth[selectedDate.month - 1]}에 가장 많이 언급한 단어를 모아봤어요. - - + @@ -48,16 +37,6 @@ const styles = StyleSheet.create({ flexGrow: 1, alignItems: 'center', }, - cardContainer: { - backgroundColor: appColor1, - borderWidth: 1, - borderRadius: 12, - alignItems: 'flex-start', - flexDirection: 'column', - padding: 16, - width: '100%', - flexGrow: 1, - }, }); export default NewReportView; diff --git a/src/screens/report/ReportMain.tsx b/src/screens/report/ReportMain.tsx new file mode 100644 index 0000000..37049ad --- /dev/null +++ b/src/screens/report/ReportMain.tsx @@ -0,0 +1,71 @@ +import React, { useState, useEffect } from 'react'; +import { StyleSheet, View } from 'react-native'; +import MyText from '@components/common/MyText'; +import NewChartView from '@screens/report/NewChartView'; +import { kMonth } from '@utils/localeConfig'; +import { ICalendarModalDate } from '@type/Diary'; +import NewReportContent from './NewReportContent'; +import { useReportData } from '@hooks/report/useReportData'; +import ReportLoadingView from './ReportLoadingView'; +import ReportErrorView from './ReportErrorView'; +import KeywordRank from './KeywordRank'; + +function ReportMain({ selectedDate }: { selectedDate: ICalendarModalDate }) { + const { data, isPending, isError } = useReportData(selectedDate); + const [selectedRank, setSelectedRank] = useState(null); + + useEffect(() => { + setSelectedRank(null); + }, [selectedDate]); + + if (isPending) { + return ; + } + if (isError || !data) { + return ; + } + + const onKeywordPress = (rank: number) => { + setSelectedRank(rank); + }; + + return ( + <> + + + + {kMonth[selectedDate.month - 1]}에 가장 많이 언급한 단어를 모아봤어요. + + + + {selectedRank ? ( + + ) : ( + item.keyword)} + onKeywordPress={onKeywordPress} + /> + )} + + + ); +} + +const styles = StyleSheet.create({ + container: { + width: '100%', + alignItems: 'center', + marginBottom: 16, + flex: 1, + }, + cardContainer: { + flex: 1, + width: '100%', + }, +}); + +export default ReportMain; From 8b8969a63a1700796211897ef0f78e89787f6067 Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Fri, 22 Nov 2024 21:34:22 +0900 Subject: [PATCH 23/25] =?UTF-8?q?feat:=20background=20=ED=81=B4=EB=A6=AD?= =?UTF-8?q?=20=EC=8B=9C=20=ED=82=A4=EC=9B=8C=EB=93=9C=20=EB=B3=B4=EC=97=AC?= =?UTF-8?q?=EC=A4=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/screens/report/ReportMain.tsx | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/screens/report/ReportMain.tsx b/src/screens/report/ReportMain.tsx index 37049ad..7569a45 100644 --- a/src/screens/report/ReportMain.tsx +++ b/src/screens/report/ReportMain.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from 'react'; -import { StyleSheet, View } from 'react-native'; +import { StyleSheet, View, Pressable } from 'react-native'; import MyText from '@components/common/MyText'; import NewChartView from '@screens/report/NewChartView'; import { kMonth } from '@utils/localeConfig'; @@ -29,8 +29,15 @@ function ReportMain({ selectedDate }: { selectedDate: ICalendarModalDate }) { setSelectedRank(rank); }; + const onPressBackground = () => { + setSelectedRank(null); + }; + return ( - <> + [styles.container, hovered && { cursor: 'default' }]} + > @@ -51,11 +58,15 @@ function ReportMain({ selectedDate }: { selectedDate: ICalendarModalDate }) { /> )} - + ); } const styles = StyleSheet.create({ + outerContainer: { + flex: 1, + width: '100%', + }, container: { width: '100%', alignItems: 'center', From 5298420ecb09f8a713487feb55f6837672e41ea3 Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Fri, 22 Nov 2024 22:21:30 +0900 Subject: [PATCH 24/25] =?UTF-8?q?feat:=20=ED=99=94=EB=A9=B4=EC=A0=84?= =?UTF-8?q?=ED=99=98=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?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/screens/report/NewChartView.web.tsx | 18 +++--- src/screens/report/NewReportContent.tsx | 12 ++-- src/screens/report/ReportMain.tsx | 77 ++++++++++++++++--------- 3 files changed, 65 insertions(+), 42 deletions(-) diff --git a/src/screens/report/NewChartView.web.tsx b/src/screens/report/NewChartView.web.tsx index 69a7afc..fe54237 100644 --- a/src/screens/report/NewChartView.web.tsx +++ b/src/screens/report/NewChartView.web.tsx @@ -1,5 +1,5 @@ -import React, { Dispatch, SetStateAction } from 'react'; -import { View, StyleSheet } from 'react-native'; +import React from 'react'; +import { StyleSheet, Pressable } from 'react-native'; import { Chart as ChartJS, RadialLinearScale, @@ -29,10 +29,10 @@ ChartJS.register( interface INewChartViewProps { chartData: IReportData[]; - setSelectedRank: Dispatch>; + onLabelPress: (rank: number) => void; } -function NewChartView({ chartData, setSelectedRank }: INewChartViewProps) { +function NewChartView({ chartData, onLabelPress }: INewChartViewProps) { const data = { labels: chartData.map((item) => item.keyword), datasets: [ @@ -49,7 +49,7 @@ function NewChartView({ chartData, setSelectedRank }: INewChartViewProps) { onClick: (event: any, elements: any[]) => { if (elements.length > 0) { const clickedIndex = elements[0].index; - setSelectedRank(clickedIndex + 1); + onLabelPress(clickedIndex + 1); } }, plugins: { @@ -96,17 +96,15 @@ function NewChartView({ chartData, setSelectedRank }: INewChartViewProps) { }; return ( - + {}} style={styles.container}> - + ); } const styles = StyleSheet.create({ - chart: { + container: { flex: 1, - marginVertical: 16, - width: '100%', justifyContent: 'center', alignItems: 'center', }, diff --git a/src/screens/report/NewReportContent.tsx b/src/screens/report/NewReportContent.tsx index 3b58bf7..3c465e7 100644 --- a/src/screens/report/NewReportContent.tsx +++ b/src/screens/report/NewReportContent.tsx @@ -1,4 +1,4 @@ -import React, { Dispatch, SetStateAction, useEffect } from 'react'; +import React, { useEffect } from 'react'; import { StyleSheet, ScrollView, Pressable } from 'react-native'; import MyText from '@components/common/MyText'; import { fontMedium } from '@utils/Sizing'; @@ -11,10 +11,10 @@ import ReportErrorView from './ReportErrorView'; interface INewReportContentProps { selectedDate: ICalendarModalDate; rank: number; - setSelectedRank: Dispatch>; + onPress: () => void; } -const NewReportContent = ({ selectedDate, rank, setSelectedRank }: INewReportContentProps) => { +const NewReportContent = ({ selectedDate, rank, onPress }: INewReportContentProps) => { const { data, isPending, isError } = useReportKeyword({ selectedDate, rank }); useEffect(() => { @@ -22,9 +22,9 @@ const NewReportContent = ({ selectedDate, rank, setSelectedRank }: INewReportCon console.log(data); }, [rank, data]); - const onPress = () => { - setSelectedRank(null); - }; + // const onPress = () => { + // setSelectedRank(null); + // }; if (isPending) { return ; diff --git a/src/screens/report/ReportMain.tsx b/src/screens/report/ReportMain.tsx index 7569a45..9d3415e 100644 --- a/src/screens/report/ReportMain.tsx +++ b/src/screens/report/ReportMain.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from 'react'; -import { StyleSheet, View, Pressable } from 'react-native'; +import { StyleSheet, View, Pressable, Animated } from 'react-native'; import MyText from '@components/common/MyText'; import NewChartView from '@screens/report/NewChartView'; import { kMonth } from '@utils/localeConfig'; @@ -13,66 +13,91 @@ import KeywordRank from './KeywordRank'; function ReportMain({ selectedDate }: { selectedDate: ICalendarModalDate }) { const { data, isPending, isError } = useReportData(selectedDate); const [selectedRank, setSelectedRank] = useState(null); + const [fadeAnim] = useState(new Animated.Value(1)); useEffect(() => { setSelectedRank(null); }, [selectedDate]); - if (isPending) { - return ; - } - if (isError || !data) { - return ; - } + const fadeOut = () => { + Animated.timing(fadeAnim, { + toValue: 0, + duration: 200, + useNativeDriver: true, + }).start(() => { + setSelectedRank(null); + fadeIn(); + }); + }; + + const fadeIn = () => { + Animated.timing(fadeAnim, { + toValue: 1, + duration: 200, + useNativeDriver: true, + }).start(); + }; const onKeywordPress = (rank: number) => { - setSelectedRank(rank); + Animated.timing(fadeAnim, { + toValue: 0, + duration: 200, + useNativeDriver: true, + }).start(() => { + setSelectedRank(rank); + fadeIn(); + }); }; const onPressBackground = () => { - setSelectedRank(null); + if (selectedRank) { + fadeOut(); + } }; + if (isPending) { + return ; + } + if (isError || !data) { + return ; + } + return ( [styles.container, hovered && { cursor: 'default' }]} > - - - - {kMonth[selectedDate.month - 1]}에 가장 많이 언급한 단어를 모아봤어요. - + + + {kMonth[selectedDate.month - 1]}에 가장 많이 언급한 단어를 모아봤어요. - + {selectedRank ? ( - + ) : ( item.keyword)} onKeywordPress={onKeywordPress} /> )} - + ); } const styles = StyleSheet.create({ - outerContainer: { - flex: 1, - width: '100%', - }, container: { width: '100%', alignItems: 'center', - marginBottom: 16, flex: 1, }, + descriptionContainer: { + marginVertical: 16, + }, cardContainer: { flex: 1, width: '100%', From e2ccbf5878fdf172964575daee5df8b78dc242fa Mon Sep 17 00:00:00 2001 From: hyobb109 Date: Fri, 22 Nov 2024 22:22:09 +0900 Subject: [PATCH 25/25] =?UTF-8?q?comment:=20NewReportView=20=EC=A3=BC?= =?UTF-8?q?=EC=84=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/navigators/PieceStackNavigator.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/navigators/PieceStackNavigator.tsx b/src/navigators/PieceStackNavigator.tsx index aa19b99..4ae9fab 100644 --- a/src/navigators/PieceStackNavigator.tsx +++ b/src/navigators/PieceStackNavigator.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { createStackNavigator, TransitionPresets } from '@react-navigation/stack'; import Piece from '@screens/piece/Piece'; import useUserSetup from '@hooks/user/useUserSetup'; +import NewReportView from '@screens/report/NewReportView'; const Stack = createStackNavigator(); const PieceStackNavigator = () => { @@ -42,6 +43,7 @@ const PieceStackNavigator = () => { }} name="Piece" component={Piece} + // component={NewReportView} /> );