worked on the aboutus component edit functionlity

This commit is contained in:
2025-02-14 15:00:43 +05:30
parent 097d8bad99
commit 2cb6173b81
5 changed files with 332 additions and 72 deletions

138
package-lock.json generated
View File

@@ -22,6 +22,7 @@
"react-dom": "^18.3.1",
"react-hook-form": "^7.54.2",
"react-icons": "^5.4.0",
"react-quill": "^2.0.0",
"react-redux": "^9.2.0",
"react-router-dom": "^7.1.1",
"vite-plugin-pwa": "^0.21.1"
@@ -3284,6 +3285,15 @@
"devOptional": true,
"license": "MIT"
},
"node_modules/@types/quill": {
"version": "1.3.10",
"resolved": "https://registry.npmjs.org/@types/quill/-/quill-1.3.10.tgz",
"integrity": "sha512-IhW3fPW+bkt9MLNlycw8u8fWb7oO7W5URC9MfZYHBlA24rex9rs23D5DETChu1zvgVdc5ka64ICjJOgQMr6Shw==",
"license": "MIT",
"dependencies": {
"parchment": "^1.1.2"
}
},
"node_modules/@types/react": {
"version": "18.3.18",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz",
@@ -5348,6 +5358,15 @@
"node": ">= 0.2.0"
}
},
"node_modules/clone": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
"integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
"license": "MIT",
"engines": {
"node": ">=0.8"
}
},
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@@ -5574,6 +5593,26 @@
}
}
},
"node_modules/deep-equal": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz",
"integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==",
"license": "MIT",
"dependencies": {
"is-arguments": "^1.1.1",
"is-date-object": "^1.0.5",
"is-regex": "^1.1.4",
"object-is": "^1.1.5",
"object-keys": "^1.1.1",
"regexp.prototype.flags": "^1.5.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/deep-is": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
@@ -6085,12 +6124,30 @@
"node": ">=0.10.0"
}
},
"node_modules/eventemitter3": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-2.0.3.tgz",
"integrity": "sha512-jLN68Dx5kyFHaePoXWPsCGW5qdyZQtLYHkxkg02/Mz6g0kYpDx4FyP6XfArhQdlOC4b8Mv+EMxPo/8La7Tzghg==",
"license": "MIT"
},
"node_modules/extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
"license": "MIT"
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"license": "MIT"
},
"node_modules/fast-diff": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.1.2.tgz",
"integrity": "sha512-KaJUt+M9t1qaIteSvjc6P3RbMdXsNhK61GRftR6SNxqmhthcd9MGIi4T+o0jD8LUSpSnSKXE20nLtJ3fOHxQig==",
"license": "Apache-2.0"
},
"node_modules/fast-glob": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
@@ -6890,6 +6947,22 @@
"node": ">= 0.4"
}
},
"node_modules/is-arguments": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz",
"integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==",
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"has-tostringtag": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-array-buffer": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
@@ -7829,6 +7902,22 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/object-is": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz",
"integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==",
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.7",
"define-properties": "^1.2.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
@@ -7948,6 +8037,12 @@
"dev": true,
"license": "MIT"
},
"node_modules/parchment": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/parchment/-/parchment-1.1.4.tgz",
"integrity": "sha512-J5FBQt/pM2inLzg4hEWmzQx/8h8D0CiDxaG3vyp9rKrQRSDgBlhjdP5jQGgosEajXPSQouXGHOmVdgo7QmJuOg==",
"license": "BSD-3-Clause"
},
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -8206,6 +8301,34 @@
],
"license": "MIT"
},
"node_modules/quill": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/quill/-/quill-1.3.7.tgz",
"integrity": "sha512-hG/DVzh/TiknWtE6QmWAF/pxoZKYxfe3J/d/+ShUWkDvvkZQVTPeVmUJVu1uE6DDooC4fWTiCLh84ul89oNz5g==",
"license": "BSD-3-Clause",
"dependencies": {
"clone": "^2.1.1",
"deep-equal": "^1.0.1",
"eventemitter3": "^2.0.3",
"extend": "^3.0.2",
"parchment": "^1.1.4",
"quill-delta": "^3.6.2"
}
},
"node_modules/quill-delta": {
"version": "3.6.3",
"resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-3.6.3.tgz",
"integrity": "sha512-wdIGBlcX13tCHOXGMVnnTVFtGRLoP0imqxM696fIPwIf5ODIYUHIvHbZcyvGlZFiFhK5XzDC2lpjbxRhnM05Tg==",
"license": "MIT",
"dependencies": {
"deep-equal": "^1.0.1",
"extend": "^3.0.2",
"fast-diff": "1.1.2"
},
"engines": {
"node": ">=0.10"
}
},
"node_modules/randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@@ -8281,6 +8404,21 @@
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"license": "MIT"
},
"node_modules/react-quill": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/react-quill/-/react-quill-2.0.0.tgz",
"integrity": "sha512-4qQtv1FtCfLgoD3PXAur5RyxuUbPXQGOHgTlFie3jtxp43mXDtzCKaOgQ3mLyZfi1PUlyjycfivKelFhy13QUg==",
"license": "MIT",
"dependencies": {
"@types/quill": "^1.3.10",
"lodash": "^4.17.4",
"quill": "^1.3.7"
},
"peerDependencies": {
"react": "^16 || ^17 || ^18",
"react-dom": "^16 || ^17 || ^18"
}
},
"node_modules/react-redux": {
"version": "9.2.0",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz",

View File

@@ -24,6 +24,7 @@
"react-dom": "^18.3.1",
"react-hook-form": "^7.54.2",
"react-icons": "^5.4.0",
"react-quill": "^2.0.0",
"react-redux": "^9.2.0",
"react-router-dom": "^7.1.1",
"vite-plugin-pwa": "^0.21.1"

View File

@@ -1,61 +1,129 @@
// import { Badge, HStack, Text, VStack } from "@chakra-ui/react";
// import MainFrame from "../../../components/MainFrame"
// import { useGetAboutUsQuery } from "../../../Redux/Service/manage.aboutus.service";
// import { Spinner } from "../../../components/Sipnner/Spinner";
// import GlobalStateContext from "../../../Contexts/GlobalStateContext";
// import { useContext, useEffect } from "react";
// import AboutUsAddModel from "./AboutUsAddModel";
// const AboutUs = () => {
// const { data, isLoading, isFetching } = useGetAboutUsQuery();
// // const content = data?.data
// console.log('====================================');
// console.log(data);
// console.log('====================================');
// const context = useContext(GlobalStateContext);
// if (!context) throw new Error('App must be used within a GlobalStateProvider');
// const { setIsBarLoading } = context;
// useEffect(() => {
// setIsBarLoading(isFetching)
// }, [data])
// return (
// <MainFrame transperant={true}>
// <VStack gap={4} pb={4} pt={0}>
// {isLoading || isFetching ?
// <Spinner /> : data?.data?.map(({ id, content, about_language }) => <VStack bg={'#fff'}
// boxShadow={'rgba(99, 99, 99, 0.2) 0px 2px 8px 0px'} rounded={'lg'} p={3} key={id}>
// <HStack
// w={"100%"}
// justifyContent={"space-between"}
// py={0}
// px={0}
// >
// <Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
// About Us <Badge variant={'surface'} colorPalette="cyan" ms={2} size={'sm'} fontSize={'xs'} px={2}>🎓 {about_language?.language_name}</Badge>
// </Text>
// {/* <AboutUsAddModel /> */}
// <AboutUsAddModel/>
// </HStack>
// <Text
// as="p"
// fontSize="sm"
// fontWeight={400}
// color="#1D1D1D"
// >
// {content}
// </Text>
// </VStack>)}
// </VStack>
// </MainFrame>
// )
// }
// export default AboutUs
import { Badge, HStack, Text, VStack } from "@chakra-ui/react";
import MainFrame from "../../../components/MainFrame"
import AboutUsAddModel from "../../ManageCMS/AboutUs/AboutUsAddModel";
import MainFrame from "../../../components/MainFrame";
import { useGetAboutUsQuery } from "../../../Redux/Service/manage.aboutus.service";
import { Spinner } from "../../../components/Sipnner/Spinner";
import GlobalStateContext from "../../../Contexts/GlobalStateContext";
import { useContext, useEffect } from "react";
import AboutUsAddModel from "./AboutUsAddModel";
const AboutUs = () => {
const { data, isLoading, isFetching } = useGetAboutUsQuery();
// const content = data?.data
console.log('====================================');
console.log(data);
console.log('====================================');
console.log("Fetched About Us Data:", data);
const context = useContext(GlobalStateContext);
if (!context) throw new Error('App must be used within a GlobalStateProvider');
if (!context) throw new Error("App must be used within a GlobalStateProvider");
const { setIsBarLoading } = context;
useEffect(() => {
setIsBarLoading(isFetching)
}, [data])
setIsBarLoading(isFetching);
}, [isFetching, setIsBarLoading]);
return (
<MainFrame transperant={true}>
<VStack gap={4} pb={4} pt={0}>
{isLoading || isFetching ?
<Spinner /> : data?.data?.map(({ id, content, about_language }) => <VStack bg={'#fff'}
boxShadow={'rgba(99, 99, 99, 0.2) 0px 2px 8px 0px'} rounded={'lg'} p={3} key={id}>
<HStack
w={"100%"}
justifyContent={"space-between"}
py={0}
px={0}
{isLoading || isFetching ? (
<Spinner />
) : (
data?.data?.map(({ id, content, about_language }) => (
<VStack
bg={"#fff"}
boxShadow={"rgba(99, 99, 99, 0.2) 0px 2px 8px 0px"}
rounded={"lg"}
p={3}
key={id}
>
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
About Us <Badge variant={'surface'} colorPalette="cyan" ms={2} size={'sm'} fontSize={'xs'} px={2}>🎓 {about_language?.language_name}</Badge>
<HStack w={"100%"} justifyContent={"space-between"} py={0} px={0}>
<Text as={"span"} fontSize={"sm"} fontWeight={500} color={"#000"}>
About Us{" "}
<Badge
variant={"surface"}
colorPalette="cyan"
ms={2}
size={"sm"}
fontSize={"xs"}
px={2}
>
🎓 {about_language?.language_name}
</Badge>
</Text>
{/* Pass Data to AboutUsAddModel */}
<AboutUsAddModel aboutUsData={{ id, content, about_language }} />
</HStack>
<Text as="p" fontSize="sm" fontWeight={400} color="#1D1D1D">
{/* {content} */}
<div dangerouslySetInnerHTML={{ __html: content }} />
</Text>
<AboutUsAddModel />
</HStack>
<Text
as="p"
fontSize="sm"
fontWeight={400}
color="#1D1D1D"
>
{content}
</Text>
</VStack>)}
</VStack>
))
)}
</VStack>
</MainFrame>
)
}
export default AboutUs
);
};
export default AboutUs;

View File

@@ -1,3 +1,4 @@
import { FaRegEdit } from "react-icons/fa";
import {
DialogBody,
@@ -9,51 +10,94 @@ import {
DialogTitle,
DialogTrigger,
} from "../../../components/ui/dialog";
import { Field, Stack, Text, Textarea } from "@chakra-ui/react";
import { Field, Stack, Text } from "@chakra-ui/react";
import { Button } from "../../../components/ui/button";
import ReactQuill from "react-quill";
import "react-quill/dist/quill.snow.css"; // Import the styles
import { useState } from "react";
import { useUpdateAboutUsMutation } from "../../../Redux/Service/manage.aboutus.service";
// import { useUpdateAboutUsMutation } from "../../../services/api"; // Assuming you're using RTK Query
function AboutUsAddModel() {
function AboutUsAddModel({ aboutUsData }: { aboutUsData: any }) {
const [content, setContent] = useState("");
const [selectedId, setSelectedId] = useState<number | null>(null);
const [languageCode, setLanguageCode] = useState<string>("");
const [isOpen, setIsOpen] = useState(false);
// RTK Query Mutation Hook
const [updateAboutUs, { isLoading }] = useUpdateAboutUsMutation();
// Function to handle edit click (pre-fill the editor)
const handleEditClick = (data: any) => {
setSelectedId(data.id);
setContent(data.content);
setLanguageCode(data.about_language.language_code);
setIsOpen(true); // Open dialog
};
// Function to handle update submission
const handleSave = async () => {
if (!selectedId || !content.trim()) return; // Prevent empty updates
try {
await updateAboutUs({ id: selectedId, content, language_code: languageCode }).unwrap();
setIsOpen(false); // Close dialog on success
} catch (error) {
console.error("Update failed:", error);
}
};
return (
<DialogRoot placement="center">
<DialogRoot placement="center" open={isOpen} >
<DialogTrigger asChild>
<Button bgColor="#EEEEEE" pl={3} pr={3} size="xs" color="#000">
<Button
bgColor="#EEEEEE"
pl={3}
pr={3}
size="xs"
color="#000"
onClick={() => handleEditClick(aboutUsData)} // Set content before opening modal
>
<FaRegEdit color="#000" style={{ height: "14px", width: "14px" }} />
<Text color="#000" mt={1}>
Edit
</Text>
<Text color="#000" mt={1}>Edit</Text>
</Button>
</DialogTrigger>
<DialogContent
bg="#fff"
w={{ base: "90%", md: "400px" }}
height="auto"
p={3}
>
<DialogContent bg="#fff" w={{ base: "90%", md: "1200px" }} height="auto" p={3}>
<DialogHeader bg="white">
<DialogTitle alignSelf="center" color="black" fontSize="14px">
Edit
Edit About Us
</DialogTitle>
</DialogHeader>
<DialogBody bg="white">
<Stack py={3}>
<Stack py={3} mb={8}>
<Field.Root>
<Field.Label color="black" pt={1} fontSize="12px">
AboutUs
About Us Content
</Field.Label>
<Textarea
<ReactQuill
value={content}
onChange={setContent}
placeholder="Enter About Us content"
bgColor="#EEEEEE"
color="black"
border="none"
p={2}
fontSize="12px"
height="140px" // Increased height for better usability
pt={1.5}
resize={'none'}
_focusVisible={{ outline: 'none' }}
modules={{
toolbar: [
[{ 'header': [1, 2, false] }],
['bold', 'italic', 'underline', 'strike'],
['link', 'image'],
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
['clean']
],
}}
formats={[
'header',
'bold', 'italic', 'underline', 'strike',
'list', 'bullet',
'link', 'image'
]}
style={{ color: "black", border: "none", fontSize: "12px", height: "170px", width: "100%" }}
/>
</Field.Root>
</Stack>
@@ -64,7 +108,8 @@ function AboutUsAddModel() {
w="100%"
bg="#02A0A0"
color="#fff"
// isLoading={isLoading} // Show loading state while the mutation is in progress
// isLoading={isLoading}
onClick={handleSave}
>
Save
</Button>

View File

@@ -31,13 +31,21 @@ export const aboutUs = createApi({
}),
}),
// 🔹 PUT: Update an existing post
updateAboutUs: builder.mutation<UpdateAboutUsResponse, UpdateAboutUsRequest>({
query: ({ id, updatedData }) => ({
url: `/posts/${id}`,
method: "POST",
body: updatedData,
// updateAboutUs: builder.mutation<UpdateAboutUsResponse, UpdateAboutUsRequest>({
// query: ({ id, updatedData }) => ({
// url: `/posts/${id}`,
// method: "POST",
// body: updatedData,
// }),
// }),
// 🔹 PUT: Update an About Us entry
updateAboutUs: builder.mutation({
query: (updatedData) => ({
url: "/about-us/update", // ✅ Updated URL
method: "POST",
body: updatedData,
}),
}),
}),
// 🔹 DELETE: Remove a post by ID
deletePost: builder.mutation<{ success: boolean }, number>({
query: (id) => ({