diff --git a/package-lock.json b/package-lock.json index bd97015..c64e87f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,12 +12,15 @@ "@azure/msal-react": "^2.0.12", "@hookform/resolvers": "^3.3.4", "@meghoshpritam/react-image-file-resizer": "^1.0.3", + "@radix-ui/react-alert-dialog": "^1.0.5", "@radix-ui/react-avatar": "^1.0.4", "@radix-ui/react-context-menu": "^2.1.5", "@radix-ui/react-dialog": "^1.0.5", + "@radix-ui/react-dropdown-menu": "^2.0.6", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-menubar": "^1.0.4", + "@radix-ui/react-popover": "^1.0.7", "@radix-ui/react-slot": "^1.0.2", "@tanstack/react-query": "^5.22.2", "@tanstack/react-query-devtools": "^5.28.14", @@ -427,6 +430,34 @@ "@babel/runtime": "^7.13.10" } }, + "node_modules/@radix-ui/react-alert-dialog": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.0.5.tgz", + "integrity": "sha512-OrVIOcZL0tl6xibeuGt5/+UxoT2N27KCFOPjFyfXMnchxSHZ/OW7cCX2nGlIYJrbHK/fczPcFzAwvNBB6XBNMA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-dialog": "1.0.5", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-arrow": { "version": "1.0.3", "resolved": "https://rb-artifactory.bosch.com:443/artifactory/api/npm/npmjs-remote/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz", @@ -644,6 +675,35 @@ } } }, + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.0.6.tgz", + "integrity": "sha512-i6TuFOoWmLWq+M/eCLGd/bQ2HfAX1RJgvrBQ6AQLmzfvsLdefxbWu8G9zczcPFfcSPehz9GcpF6K9QYreFV8hA==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-menu": "2.0.6", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-controllable-state": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-focus-guards": { "version": "1.0.1", "resolved": "https://rb-artifactory.bosch.com:443/artifactory/api/npm/npmjs-remote/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz", @@ -807,6 +867,43 @@ } } }, + "node_modules/@radix-ui/react-popover": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.0.7.tgz", + "integrity": "sha512-shtvVnlsxT6faMnK/a7n0wptwBD23xc1Z5mdrtKLwVEfsEMXodS0r5s0/g5P0hX//EKYZS2sxUjqfzlg52ZSnQ==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.5", + "@radix-ui/react-focus-guards": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.4", + "@radix-ui/react-id": "1.0.1", + "@radix-ui/react-popper": "1.1.3", + "@radix-ui/react-portal": "1.0.4", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-slot": "1.0.2", + "@radix-ui/react-use-controllable-state": "1.0.1", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.5" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-popper": { "version": "1.1.3", "resolved": "https://rb-artifactory.bosch.com:443/artifactory/api/npm/npmjs-remote/@radix-ui/react-popper/-/react-popper-1.1.3.tgz", @@ -7464,4 +7561,4 @@ } } } -} +} \ No newline at end of file diff --git a/package.json b/package.json index 66d1417..711552a 100644 --- a/package.json +++ b/package.json @@ -15,12 +15,15 @@ "@azure/msal-react": "^2.0.12", "@hookform/resolvers": "^3.3.4", "@meghoshpritam/react-image-file-resizer": "^1.0.3", + "@radix-ui/react-alert-dialog": "^1.0.5", "@radix-ui/react-avatar": "^1.0.4", "@radix-ui/react-context-menu": "^2.1.5", "@radix-ui/react-dialog": "^1.0.5", + "@radix-ui/react-dropdown-menu": "^2.0.6", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-menubar": "^1.0.4", + "@radix-ui/react-popover": "^1.0.7", "@radix-ui/react-slot": "^1.0.2", "@tanstack/react-query": "^5.22.2", "@tanstack/react-query-devtools": "^5.28.14", diff --git a/public/imageDefault.jpg b/public/imageDefault.jpg new file mode 100644 index 0000000..1497cae Binary files /dev/null and b/public/imageDefault.jpg differ diff --git a/public/newsNotFound.png b/public/newsNotFound.png deleted file mode 100644 index 712ff23..0000000 Binary files a/public/newsNotFound.png and /dev/null differ diff --git a/src/api/hooks/news/queries.ts b/src/api/hooks/news/queries.ts index e62cf9d..87feca4 100644 --- a/src/api/hooks/news/queries.ts +++ b/src/api/hooks/news/queries.ts @@ -26,14 +26,13 @@ async function getNewsFilterScroll(ctx: QueryFunctionContext) { const pageParam = ctx.pageParam; const filterParam = usefilter({ filters: { tags, title } }); - const url = tags || title ? `${filterParam}` : ""; - + const url = tags || title ? `${filterParam}` : undefined; const { data } = await api.get(`news/preview?size=9${url}`, { params: { page: pageParam, }, }); - + console.log(data) return data; } @@ -52,7 +51,7 @@ export function useFetchGetNewsScroll(tags?: string, title?: string) { } // GET News By ID -async function getIdNews(ctx: QueryFunctionContext) { +export async function getIdNews(ctx: QueryFunctionContext) { const [, id] = ctx.queryKey; const { data } = await api.get(`news/${id}`); return data; @@ -65,6 +64,16 @@ export function useFetchGetNewsId(id: string) { }); } + +export function useFetchGetNewsIdRefetch(id: string) { + return useQuery({ + queryKey: ["newsRead", id], + queryFn: getIdNews, + enabled: false, + refetchOnWindowFocus: false + }); +} + // GET Other News async function getNewsOtherNews() { const { data } = await api.get( diff --git a/src/api/hooks/user/queries.ts b/src/api/hooks/user/queries.ts index af57010..0a45f8e 100644 --- a/src/api/hooks/user/queries.ts +++ b/src/api/hooks/user/queries.ts @@ -1,17 +1,140 @@ -import { useQuery } from "@tanstack/react-query"; -import { ContentNews } from "@/api/types/news/type"; +import { ContentComment, ContentNews, News } from "@/api/types/news/type"; import api from "@/services/api"; +import { + QueryFunctionContext, + useMutation, + useQuery, + useQueryClient, +} from "@tanstack/react-query"; +import { title } from "process"; +import toast from "react-hot-toast"; +import { getIdNews } from "../news/queries"; // News // GET user news -async function getUserNews() { - const { data } = await api.get(`news/author`); +export async function getUserNews(ctx: QueryFunctionContext) { + const [, status] = ctx.queryKey; + const filter = status === undefined ? "published" : status; + const { data } = await api.get(`news/author?sortBy=${filter}`); return data; } -export function useFetchGetUserNews() { +export function useFetchGetUserNews(status?: string) { return useQuery({ - queryKey: ["news"], + queryKey: ["userNews", status], queryFn: getUserNews, }); } + +// PATCH user news +async function patchNews({ + newsObject, + id, +}: { + newsObject: FormData; + id: string; +}) { + const promise = api.patch(`news/${id}`, newsObject); + + toast.promise(promise, { + loading: "Updated news", + success: "Updated news with success", + error: (error) => { + console.log(error); + return error.response.data + ? `${error.message}:\n${error.response.data.message}` + : `${error.message}`; + }, + }); + + return await promise; +} + +export function useMutationPatchNews() { + return useMutation({ + mutationFn: patchNews, + }); +} + +// ARCHIVE user news + +async function patchArchive(id: string) { + const archive = api.patch(`news/${id}/archive`); + + toast.promise(archive, { + loading: "Delete news", + success: "Delete news with success", + error: (error) => { + console.log(error); + return error.response.data + ? `${error.message}:\n${error.response.data.message}` + : `${error.message}`; + }, + }); + return await archive; +} + +async function patchPublish(id: string) { + const publish = api.patch(`news/${id}/publish`); + + toast.promise(publish, { + loading: "Publish news", + success: "Publish news with success", + error: (error) => { + console.log(error); + return error.response.data + ? `${error.message}:\n${error.response.data.message}` + : `${error.message}`; + }, + }); + return await publish; +} + +export function useMutationPatchArchive() { + return useMutation({ + mutationFn: patchArchive, + }); +} + +export function useMutationPatchPublish() { + return useMutation({ + mutationFn: patchPublish, + }); +} + +// News +// GET user comments + +export async function getUserComments() { + const { data } = await api.get( + `comments/author` + ); + return data; +} + +export function useFetchGetUserComments(){ + return useQuery({ + queryKey: ["userComments"], + queryFn: getUserComments + }) +} + +async function patchDelete(id: number) { + const deleteComment = api.delete(`comments/${id}`); + + toast.promise(deleteComment, { + loading: "Delete Comment", + success: "Delete Comment with success", + error: (error) => { + console.log(id); + return "Delete Comment Error"; + }, + }); + return await deleteComment; +} + +export function useMutationPatchDelete() { + return useMutation({ + mutationFn: patchDelete, + }); +} diff --git a/src/api/types/all/type.ts b/src/api/types/all/type.ts index 68f5f70..7981554 100644 --- a/src/api/types/all/type.ts +++ b/src/api/types/all/type.ts @@ -1,5 +1,6 @@ import { AppRouterInstance } from "next/dist/shared/lib/app-router-context.shared-runtime"; import { ReadonlyURLSearchParams } from "next/navigation"; +import { title } from "process"; export interface Error { text: string; @@ -21,3 +22,38 @@ export interface FilterPath { searchParams: ReadonlyURLSearchParams; router: AppRouterInstance; } + +export interface AlertType { + variantButton: + | "delete" + | "ghost" + | "bdpurple" + | "bdlight" + | "default" + | "outline"; + nameButton: string | any; + type?: "submit" | "reset" | "button" | undefined; + title: string; + description: string; + nameButtonAction: string; + Action?: () => void; + idForm?: string; +} + +interface DefaultValuesType { + title?: string; + body?: string; + image?: File | undefined; + tags?: string[]; +} + +export interface FormType { + title: string | any; + open: boolean; + openUpdate?: boolean; + OnSubmit: (values: any) => void; + idForm?: string; + idNews?: string; + defaultValues?: DefaultValuesType; + alertSubmit: JSX.Element +} diff --git a/src/app/news/page.tsx b/src/app/news/page.tsx index ac6e558..14d0bba 100644 --- a/src/app/news/page.tsx +++ b/src/app/news/page.tsx @@ -3,9 +3,9 @@ import NavBar from "@/components/base/common/NavBar"; import TopBanner from "@/components/base/common/TopBanner"; import NewsList from "@/components/base/news/NewsList"; import SearchBar from "@/components/base/news/SearchBar"; -import ModalAddNews from "@/components/base/news/ModalAddNews"; import { RoleGuard } from "@/components/base/common/RoleGuard"; import { appRoles } from "@/lib/sso/authConfig"; +import {FormAddNews} from "@/components/base/news/FormAddNews"; export default function NewsPage() { return ( @@ -18,7 +18,7 @@ export default function NewsPage() { >
- +
diff --git a/src/app/user/page.tsx b/src/app/user/page.tsx index 1ce8485..e885da7 100644 --- a/src/app/user/page.tsx +++ b/src/app/user/page.tsx @@ -8,6 +8,11 @@ import { } from "@/components/ui/carousel"; import NewsUserList from "@/components/base/user/NewsUserList"; import Footer from "@/components/base/common/Footer"; +import { LinkFilterNewsUser } from "@/components/base/user/LinkFilterNewsUser"; +import { RoleGuard } from "@/components/base/common/RoleGuard"; +import { appRoles } from "@/lib/sso/authConfig"; +import { CommentsUserList } from "@/components/base/user/CommentsUserList"; +import { useSearchParams } from "next/navigation"; export default function User() { return ( @@ -16,11 +21,23 @@ export default function User() { -
- + +
+ +
+
+ +
+ + + +