From 2ab8edc64582e498751a18c17eabd05fe40e94de Mon Sep 17 00:00:00 2001 From: bacpactech Date: Mon, 23 Dec 2024 17:40:56 +0530 Subject: [PATCH] fix: text-formatting --- package-lock.json | 190 +++++++++++++- package.json | 6 + src/app/(withLayout)/timeline/page.tsx | 8 +- src/app/login/page.tsx | 2 +- src/assets/bold.svg | 3 + src/assets/bulletList.svg | 8 + src/assets/centerAlign.svg | 5 + src/assets/code.svg | 3 + src/assets/italic.svg | 3 + src/assets/leftAlign.svg | 5 + src/assets/numList.svg | 8 + src/assets/rightAlign.svg | 5 + src/assets/strikeThrough.svg | 4 + src/components/molecules/PostCard/index.tsx | 9 +- src/components/organism/Login/LoginBox.tsx | 2 +- .../organisms/UserPostContainer/index.tsx | 30 +-- .../organisms/userPostForm/index.css | 28 ++ .../organisms/userPostForm/index.tsx | 239 ++++++++++++++++++ 18 files changed, 530 insertions(+), 28 deletions(-) create mode 100644 src/assets/bold.svg create mode 100644 src/assets/bulletList.svg create mode 100644 src/assets/centerAlign.svg create mode 100644 src/assets/code.svg create mode 100644 src/assets/italic.svg create mode 100644 src/assets/leftAlign.svg create mode 100644 src/assets/numList.svg create mode 100644 src/assets/rightAlign.svg create mode 100644 src/assets/strikeThrough.svg create mode 100644 src/components/organisms/userPostForm/index.css create mode 100644 src/components/organisms/userPostForm/index.tsx diff --git a/package-lock.json b/package-lock.json index f2d55d4..e6a55c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,8 @@ "date-fns": "^4.1.0", "dayjs": "^1.11.11", "dotenv": "^16.3.1", + "draft-js": "^0.11.7", + "draftjs-to-html": "^0.9.1", "emoji-picker-react": "^4.9.3", "esbuild": "^0.20.2", "framer-motion": "^11.0.25", @@ -47,6 +49,7 @@ "react": "18.2.0", "react-date-range": "^2.0.1", "react-dom": "^18.2.0", + "react-draft-wysiwyg": "^1.15.0", "react-hook-form": "^7.51.2", "react-hot-toast": "^2.4.1", "react-icons": "^4.11.0", @@ -80,8 +83,11 @@ "@types/aos": "^3.0.7", "@types/cookie": "^0.6.0", "@types/crypto-js": "^4.2.2", + "@types/draft-js": "^0.11.18", + "@types/draftjs-to-html": "^0.8.4", "@types/jest": "^29.5.11", "@types/react-date-range": "^1.4.9", + "@types/react-draft-wysiwyg": "^1.13.8", "@types/react-slick": "^0.23.13", "@typescript-eslint/eslint-plugin": "^6.15.0", "@typescript-eslint/parser": "^6.15.0", @@ -7062,6 +7068,25 @@ "integrity": "sha512-w5jZ0ee+HaPOaX25X2/2oGR/7rgAQSYII7X7pp0m9KgBfMP7uKfMfTvcpl5Dj+eDBbpxKGiqE+flqDr6XTd2RA==", "dev": true }, + "node_modules/@types/draft-js": { + "version": "0.11.18", + "resolved": "https://registry.npmjs.org/@types/draft-js/-/draft-js-0.11.18.tgz", + "integrity": "sha512-lP6yJ+EKv5tcG1dflWgDKeezdwBa8wJ7KkiNrrHqXuXhl/VGes1SKjEfKHDZqOz19KQbrAhFvNhDPWwnQXYZGQ==", + "dev": true, + "dependencies": { + "@types/react": "*", + "immutable": "~3.7.4" + } + }, + "node_modules/@types/draftjs-to-html": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/@types/draftjs-to-html/-/draftjs-to-html-0.8.4.tgz", + "integrity": "sha512-5FZcjFoJL57N/IttLCTCNI0krX+181oCl5hf76u3TqPkqBAphHrJAO9ReYesx9138kcObaYmpnWC2Yrqxoqd2Q==", + "dev": true, + "dependencies": { + "@types/draft-js": "*" + } + }, "node_modules/@types/ejs": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.3.tgz", @@ -7382,6 +7407,16 @@ "@types/react": "*" } }, + "node_modules/@types/react-draft-wysiwyg": { + "version": "1.13.8", + "resolved": "https://registry.npmjs.org/@types/react-draft-wysiwyg/-/react-draft-wysiwyg-1.13.8.tgz", + "integrity": "sha512-qo0vIHjqAYq3Hz93Td3ecNodgVjKsvrWkBJ6mZXJSUmQzrQ5Fu7NS9oV5PXnVbnuqPoJLALbCSiz8UCksLribg==", + "dev": true, + "dependencies": { + "@types/draft-js": "*", + "@types/react": "*" + } + }, "node_modules/@types/react-slick": { "version": "0.23.13", "resolved": "https://registry.npmjs.org/@types/react-slick/-/react-slick-0.23.13.tgz", @@ -8558,6 +8593,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==" + }, "node_modules/asn1.js": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", @@ -10284,6 +10324,16 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "dev": true }, + "node_modules/core-js": { + "version": "3.39.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.39.0.tgz", + "integrity": "sha512-raM0ew0/jJUqkJ0E6e8UDtl+y/7ktFivgWvqw8dNSQeNWoSDLvQ1H/RN3aPXB9tBd4/FhyR4RDPGhsNIMsAn7g==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/core-js-compat": { "version": "3.32.2", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.32.2.tgz", @@ -11151,6 +11201,34 @@ "node": ">=12" } }, + "node_modules/draft-js": { + "version": "0.11.7", + "resolved": "https://registry.npmjs.org/draft-js/-/draft-js-0.11.7.tgz", + "integrity": "sha512-ne7yFfN4sEL82QPQEn80xnADR8/Q6ALVworbC5UOSzOvjffmYfFsr3xSZtxbIirti14R7Y33EZC5rivpLgIbsg==", + "dependencies": { + "fbjs": "^2.0.0", + "immutable": "~3.7.4", + "object-assign": "^4.1.1" + }, + "peerDependencies": { + "react": ">=0.14.0", + "react-dom": ">=0.14.0" + } + }, + "node_modules/draftjs-to-html": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/draftjs-to-html/-/draftjs-to-html-0.9.1.tgz", + "integrity": "sha512-fFstE6+IayaVFBEvaFt/wN8vdj8FsTRzij7dy7LI9QIwf5LgfHFi9zSpvCg+feJ2tbYVqHxUkjcibwpsTpgFVQ==" + }, + "node_modules/draftjs-utils": { + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/draftjs-utils/-/draftjs-utils-0.10.2.tgz", + "integrity": "sha512-EstHqr3R3JVcilJrBaO/A+01GvwwKmC7e4TCjC7S94ZeMh4IVmf60OuQXtHHpwItK8C2JCi3iljgN5KHkJboUg==", + "peerDependencies": { + "draft-js": "^0.11.x", + "immutable": "3.x.x || 4.x.x" + } + }, "node_modules/duplexify": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", @@ -12462,6 +12540,34 @@ "bser": "2.1.1" } }, + "node_modules/fbjs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-2.0.0.tgz", + "integrity": "sha512-8XA8ny9ifxrAWlyhAbexXcs3rRMtxWcs3M0lctLfB49jRDHiaxj+Mo0XxbwE7nKZYzgCFoq64FS+WFd4IycPPQ==", + "dependencies": { + "core-js": "^3.6.4", + "cross-fetch": "^3.0.4", + "fbjs-css-vars": "^1.0.0", + "loose-envify": "^1.0.0", + "object-assign": "^4.1.0", + "promise": "^7.1.1", + "setimmediate": "^1.0.5", + "ua-parser-js": "^0.7.18" + } + }, + "node_modules/fbjs-css-vars": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", + "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==" + }, + "node_modules/fbjs/node_modules/cross-fetch": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz", + "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, "node_modules/fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", @@ -13554,6 +13660,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/html-to-draftjs": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/html-to-draftjs/-/html-to-draftjs-1.5.0.tgz", + "integrity": "sha512-kggLXBNciKDwKf+KYsuE+V5gw4dZ7nHyGMX9m0wy7urzWjKGWyNFetmArRLvRV0VrxKN70WylFsJvMTJx02OBQ==", + "peerDependencies": { + "draft-js": "^0.10.x || ^0.11.x", + "immutable": "3.x.x || 4.x.x" + } + }, "node_modules/html-webpack-plugin": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.3.tgz", @@ -13741,6 +13856,14 @@ "node": ">=14.0.0" } }, + "node_modules/immutable": { + "version": "3.7.6", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz", + "integrity": "sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw==", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -16099,6 +16222,14 @@ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, + "node_modules/linkify-it": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "dependencies": { + "uc.micro": "^1.0.1" + } + }, "node_modules/lint-staged": { "version": "15.2.2", "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.2.tgz", @@ -18552,6 +18683,14 @@ "node": ">=0.4.0" } }, + "node_modules/promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "dependencies": { + "asap": "~2.0.3" + } + }, "node_modules/promises": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/promises/-/promises-0.2.5.tgz", @@ -18970,6 +19109,24 @@ "react": "^18.2.0" } }, + "node_modules/react-draft-wysiwyg": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/react-draft-wysiwyg/-/react-draft-wysiwyg-1.15.0.tgz", + "integrity": "sha512-p1cYZcWc6/ALFBVksbFoCM3b29fGQDlZLIMrXng0TU/UElxIOF2/AWWo4L5auIYVhmqKTZ0NkNjnXOzGGuxyeA==", + "dependencies": { + "classnames": "^2.2.6", + "draftjs-utils": "^0.10.2", + "html-to-draftjs": "^1.5.0", + "linkify-it": "^2.2.0", + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "draft-js": "^0.10.x || ^0.11.x", + "immutable": "3.x.x || 4.x.x", + "react": "0.13.x || 0.14.x || ^15.0.0-0 || 15.x.x || ^16.0.0-0 || ^16.x.x || ^17.x.x || ^18.x.x", + "react-dom": "0.13.x || 0.14.x || ^15.0.0-0 || 15.x.x || ^16.0.0-0 || ^16.x.x || ^17.x.x || ^18.x.x" + } + }, "node_modules/react-element-to-jsx-string": { "version": "15.0.0", "resolved": "https://registry.npmjs.org/react-element-to-jsx-string/-/react-element-to-jsx-string-15.0.0.tgz", @@ -20091,8 +20248,7 @@ "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "dev": true + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" }, "node_modules/setprototypeof": { "version": "1.2.0", @@ -21810,6 +21966,36 @@ "node": ">=14.17" } }, + "node_modules/ua-parser-js": { + "version": "0.7.40", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.40.tgz", + "integrity": "sha512-us1E3K+3jJppDBa3Tl0L3MOJiGhe1C6P0+nIvQAFYbxlMAx0h81eOwLmU57xgqToduDDPx3y5QsdjPfDu+FgOQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + }, + { + "type": "github", + "url": "https://github.com/sponsors/faisalman" + } + ], + "bin": { + "ua-parser-js": "script/cli.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" + }, "node_modules/uglify-js": { "version": "3.17.4", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", diff --git a/package.json b/package.json index 54f90bf..8da20d6 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,8 @@ "date-fns": "^4.1.0", "dayjs": "^1.11.11", "dotenv": "^16.3.1", + "draft-js": "^0.11.7", + "draftjs-to-html": "^0.9.1", "emoji-picker-react": "^4.9.3", "esbuild": "^0.20.2", "framer-motion": "^11.0.25", @@ -65,6 +67,7 @@ "react": "18.2.0", "react-date-range": "^2.0.1", "react-dom": "^18.2.0", + "react-draft-wysiwyg": "^1.15.0", "react-hook-form": "^7.51.2", "react-hot-toast": "^2.4.1", "react-icons": "^4.11.0", @@ -98,8 +101,11 @@ "@types/aos": "^3.0.7", "@types/cookie": "^0.6.0", "@types/crypto-js": "^4.2.2", + "@types/draft-js": "^0.11.18", + "@types/draftjs-to-html": "^0.8.4", "@types/jest": "^29.5.11", "@types/react-date-range": "^1.4.9", + "@types/react-draft-wysiwyg": "^1.13.8", "@types/react-slick": "^0.23.13", "@typescript-eslint/eslint-plugin": "^6.15.0", "@typescript-eslint/parser": "^6.15.0", diff --git a/src/app/(withLayout)/timeline/page.tsx b/src/app/(withLayout)/timeline/page.tsx index 62ded44..f19b778 100644 --- a/src/app/(withLayout)/timeline/page.tsx +++ b/src/app/(withLayout)/timeline/page.tsx @@ -1,8 +1,7 @@ 'use client' -import PostContainer from '@/components/organisms/PostsContainer' import TimelinePostContainer from '@/components/organisms/TimelinePostContainer' -import UserPostContainer from '@/components/organisms/UserPostContainer' -import { PostInputType, PostType } from '@/types/constants' +import UserPostForm from '@/components/organisms/userPostForm' +import { PostInputType } from '@/types/constants' import React, { useRef } from 'react' export default function Timeline() { @@ -10,7 +9,8 @@ export default function Timeline() { return (
- + + {/**/}
) diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index b7f2222..782d91c 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -3,7 +3,7 @@ import React from 'react' const Login = () => { return ( -
+
) diff --git a/src/assets/bold.svg b/src/assets/bold.svg new file mode 100644 index 0000000..33c1626 --- /dev/null +++ b/src/assets/bold.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/bulletList.svg b/src/assets/bulletList.svg new file mode 100644 index 0000000..0028c51 --- /dev/null +++ b/src/assets/bulletList.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/assets/centerAlign.svg b/src/assets/centerAlign.svg new file mode 100644 index 0000000..8491da6 --- /dev/null +++ b/src/assets/centerAlign.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/code.svg b/src/assets/code.svg new file mode 100644 index 0000000..f4b2cf2 --- /dev/null +++ b/src/assets/code.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/italic.svg b/src/assets/italic.svg new file mode 100644 index 0000000..bddb10e --- /dev/null +++ b/src/assets/italic.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/leftAlign.svg b/src/assets/leftAlign.svg new file mode 100644 index 0000000..677be9b --- /dev/null +++ b/src/assets/leftAlign.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/numList.svg b/src/assets/numList.svg new file mode 100644 index 0000000..fba8b95 --- /dev/null +++ b/src/assets/numList.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/assets/rightAlign.svg b/src/assets/rightAlign.svg new file mode 100644 index 0000000..dc19364 --- /dev/null +++ b/src/assets/rightAlign.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/strikeThrough.svg b/src/assets/strikeThrough.svg new file mode 100644 index 0000000..c0caa80 --- /dev/null +++ b/src/assets/strikeThrough.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/components/molecules/PostCard/index.tsx b/src/components/molecules/PostCard/index.tsx index 1e95f29..aa93c78 100644 --- a/src/components/molecules/PostCard/index.tsx +++ b/src/components/molecules/PostCard/index.tsx @@ -4,14 +4,13 @@ import avatar from '@assets/avatar.svg' import Image from 'next/image' import PostCartOption from '@/components/atoms/PostCardOption/PostCartOption' import PostCardImageGrid from '@/components/atoms/PostCardImagesGrid' -import { FiMessageCircle, FiRepeat, FiShare2, FiThumbsUp } from 'react-icons/fi' +import { FiMessageCircle, FiShare2, FiThumbsUp } from 'react-icons/fi' import dayjs from 'dayjs' import relativeTime from 'dayjs/plugin/relativeTime' import PostCommentBox from '../PostCommentBox' import { useUniStore } from '@/store/store' import { useLikeUnilikeGroupPost } from '@/services/community-university' import { useLikeUnlikeTimelinePost } from '@/services/community-timeline' -import { FaUser, FaUsers } from 'react-icons/fa' import { PostType } from '@/types/constants' import { FacebookIcon, @@ -174,10 +173,12 @@ const PostCard = ({
- + {/*
{text}
-
+ */} + +
{/* //post Image */} diff --git a/src/components/organism/Login/LoginBox.tsx b/src/components/organism/Login/LoginBox.tsx index 87cd3a7..556e1b9 100644 --- a/src/components/organism/Login/LoginBox.tsx +++ b/src/components/organism/Login/LoginBox.tsx @@ -48,7 +48,7 @@ const LoginBox = () => { }, []) return ( -
+
lgog
diff --git a/src/components/organisms/UserPostContainer/index.tsx b/src/components/organisms/UserPostContainer/index.tsx index 2011e35..3b0b26f 100644 --- a/src/components/organisms/UserPostContainer/index.tsx +++ b/src/components/organisms/UserPostContainer/index.tsx @@ -1,9 +1,8 @@ 'use client' -import React, { ChangeEvent, useRef, useState } from 'react' +import React, { useRef, useState } from 'react' import { GoFileMedia } from 'react-icons/go' import { HiOutlineEmojiHappy } from 'react-icons/hi' import { MdOutlineGifBox } from 'react-icons/md' -import { VscSettings } from 'react-icons/vsc' import avatar from '@assets/avatar.svg' import Image from 'next/image' import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/Popover' @@ -15,6 +14,7 @@ import { replaceImage } from '@/services/uploadImage' import { useUniStore } from '@/store/store' import { Skeleton } from '@/components/ui/Skeleton' import SelectDropdown from '@/components/atoms/SelectDropdown/SelectDropdown' +import { RxCrossCircled } from 'react-icons/rx' type props = { communityID?: string @@ -22,7 +22,7 @@ type props = { type: PostInputType.Community | PostInputType.Timeline } -function UserPostContainer({ communityID, communityGroupID, type }: props) { +export const UserPostContainer = ({ communityID, communityGroupID, type }: props) => { const textareaRef = useRef(null) const valueRef = useRef(null) const [images, setImages] = useState([]) @@ -208,19 +208,17 @@ function UserPostContainer({ communityID, communityGroupID, type }: props) {
{/* Display selected images */} - {images.map((image, index) => ( -
- {`Selected - {/* Remove image button */} - -
- ))} +
+ {images.map((image, index) => ( +
+ {`Selected + {/* Remove image button */} +
handleImageRemove(index)} className="absolute top-1 right-1 cursor-pointer text-sm"> + +
+
+ ))} +
) } diff --git a/src/components/organisms/userPostForm/index.css b/src/components/organisms/userPostForm/index.css new file mode 100644 index 0000000..c225753 --- /dev/null +++ b/src/components/organisms/userPostForm/index.css @@ -0,0 +1,28 @@ +.rdw-editor-toolbar { + border: none; + padding: 0px 0px 0px -8px; +} +.rdw-option-wrapper { + border: none; +} + +.rdw-option-active { + border: none; + background: #f3f2ff; + box-shadow: none; +} + +.rdw-option-wrapper:hover { + box-shadow: none; + background: #f3f2ff; +} + +.rdw-text-align-wrapper { + display: flex; +} + +@media only screen and (max-width: 480px) { + .rdw-text-align-wrapper { + display: none; + } +} diff --git a/src/components/organisms/userPostForm/index.tsx b/src/components/organisms/userPostForm/index.tsx new file mode 100644 index 0000000..49e479c --- /dev/null +++ b/src/components/organisms/userPostForm/index.tsx @@ -0,0 +1,239 @@ +'use client' +import dynamic from 'next/dynamic' +import React, { useRef, useState } from 'react' +import { EditorState, convertToRaw } from 'draft-js' +//import { Editor } from 'react-draft-wysiwyg' +const Editor = dynamic(() => import('react-draft-wysiwyg').then((mod) => mod.Editor), { ssr: false }) +import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css' +import './index.css' +import draftToHtml from 'draftjs-to-html' +import { Popover, PopoverContent, PopoverTrigger } from '@radix-ui/react-popover' +import { HiOutlineEmojiHappy } from 'react-icons/hi' +import EmojiPicker, { EmojiClickData } from 'emoji-picker-react' +import { MdOutlineGifBox } from 'react-icons/md' +import { GoFileMedia } from 'react-icons/go' +import SelectDropdown from '@/components/atoms/SelectDropdown/SelectDropdown' +import { CommunityPostData, CommunityPostType, PostInputData, PostInputType, UserPostType } from '@/types/constants' +import { RxCrossCircled } from 'react-icons/rx' +import { useCreateUserPost } from '@/services/community-timeline' +import { useCreateGroupPost } from '@/services/community-university' +import { replaceImage } from '@/services/uploadImage' + +type Props = { + communityID?: string + communityGroupID?: string + type: PostInputType.Community | PostInputType.Timeline +} + +const UserPostForm = ({ communityID, communityGroupID, type }: Props) => { + const [editorState, setEditorState] = useState(() => EditorState.createEmpty()) + const textareaRef = useRef(null) + const valueRef = useRef(null) + const [images, setImages] = useState([]) + const { mutate: CreateGroupPost, isPending } = useCreateGroupPost() + const { mutate: CreateTimelinePost } = useCreateUserPost() + + const [postAccessType, setPostAccessType] = useState(UserPostType.PUBLIC) + + const userPostTypeKey = Object.values(UserPostType) + const communityPostTypeKey = Object.values(CommunityPostType) + + const handleInput = () => { + const textarea = textareaRef.current + if (textarea) { + valueRef.current = textareaRef.current.value + textarea.style.height = 'auto' + textarea.style.height = `${textarea.scrollHeight}px` + } + } + + const handleEmojiClick = (emojiData: EmojiClickData) => { + const emoji = emojiData.emoji + if (textareaRef.current) { + const cursorPosition = textareaRef.current.selectionStart + const text = textareaRef.current.value + const newText = text.slice(0, cursorPosition) + emoji + text.slice(cursorPosition) + + // Update the textarea value + textareaRef.current.value = newText + valueRef.current = newText // Update ref value + handleInput() // Call input handler to update the ref value + + // Move the cursor to the right of the inserted emoji + textareaRef.current.selectionStart = textareaRef.current.selectionEnd = cursorPosition + emoji.length + + // Refocus the textarea after emoji insertion + textareaRef.current.focus() + } + } + + const handleImageChange = (e: React.ChangeEvent) => { + const files = e.target.files + if (files) { + const fileArray = Array.from(files) + setImages((prevImages) => [...prevImages, ...fileArray]) // Store the actual files + } + } + + const handleImageRemove = (index: number) => { + setImages((prevImages) => prevImages.filter((_, i) => i !== index)) + } + const processImages = async (imagesData: File[]) => { + const promises = imagesData.map((image) => replaceImage(image, '')) + const results = await Promise.all(promises) + return results.map((result) => ({ + imageUrl: result?.imageUrl || null, + publicId: result?.publicId || null, + })) + } + + const handleGroupPost = async (inputValue: string) => { + if (images.length) { + const imagedata = await processImages(images) + const data: PostInputData = { + content: inputValue, + imageUrl: imagedata, + ...(type == PostInputType.Timeline ? { PostType: postAccessType } : { communityPostsType: postAccessType }), + } + + //if type is community , add communityId field to data + if (type === PostInputType.Community) { + const communityData: CommunityPostData = { + ...data, + communityId: communityID, + ...(communityGroupID && communityGroupID?.length > 0 && { communiyGroupId: communityGroupID }), + } + CreateGroupPost(communityData) + } else if (type === PostInputType.Timeline) { + CreateTimelinePost(data) + } + } else { + const data: PostInputData = { + content: inputValue, + ...(type == PostInputType.Timeline ? { PostType: postAccessType } : { communityPostsType: postAccessType }), + } + + if (type === PostInputType.Community) { + const communityData: CommunityPostData = { + ...data, + communityId: communityID, + ...(communityGroupID && communityGroupID?.length > 0 && { communiyGroupId: communityGroupID }), + } + CreateGroupPost(communityData) + } else if (type === PostInputType.Timeline) { + CreateTimelinePost(data) + } + } + } + + // Handle form submission + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault() + // You can do something with the value here, like an API call + //if (!textareaRef.current?.value) { + // return alert('Please enter') + //} + const contentState = editorState.getCurrentContent() + const rawContent = convertToRaw(contentState) + console.log(rawContent, 'rawContent') + const draftHtml = draftToHtml(rawContent) + console.log(draftHtml, 'draftHtml') + return handleGroupPost(draftHtml) + } + + return ( +
+
+
+ +
+ +
+
+ + + + + +
+ +
+
+
+ + + +
+ {type == PostInputType.Community ? ( + setPostAccessType(e)} + placeholder="" + icon={'single'} + // search={true} + err={false} + showIcon={true} + /> + ) : ( + setPostAccessType(e)} + placeholder="" + icon={'single'} + // search={true} + err={false} + showIcon={true} + /> + )} +
+
+
+ +
+
+ {/* Display selected images */} +
+ {images.map((image, index) => ( +
+ {`Selected + {/* Remove image button */} +
handleImageRemove(index)} className="absolute top-1 right-1 cursor-pointer text-sm"> + +
+
+ ))} +
+
+
+ ) +} + +export default UserPostForm