From 5e019e10b1530abaced01526492ad505de1dd848 Mon Sep 17 00:00:00 2001 From: Rama Priyanto Date: Fri, 22 Nov 2024 17:59:58 +0700 Subject: [PATCH] feat:static page api, static/{slug} routing landing --- app/(admin)/admin/static-page/create/page.tsx | 2 +- .../admin/static-page/edit/[id]/page.tsx | 10 + app/static/[slug]/page.tsx | 38 +++ .../form/article/generate-article-form.tsx | 2 +- .../article/generate-single-article-form.tsx | 4 +- components/form/form-article.tsx | 2 + .../static-page/static-page-edit-form.tsx | 223 ++++++++++++ .../main/static-page/static-page-main.tsx | 215 ++++++++++-- components/table/static-page-table.tsx | 323 +++++++++++++++++- service/article.ts | 3 + service/static-page-service.ts | 47 +++ 11 files changed, 832 insertions(+), 37 deletions(-) create mode 100644 app/(admin)/admin/static-page/edit/[id]/page.tsx create mode 100644 app/static/[slug]/page.tsx create mode 100644 components/form/static-page/static-page-edit-form.tsx create mode 100644 service/static-page-service.ts diff --git a/app/(admin)/admin/static-page/create/page.tsx b/app/(admin)/admin/static-page/create/page.tsx index cd7c356..734515f 100644 --- a/app/(admin)/admin/static-page/create/page.tsx +++ b/app/(admin)/admin/static-page/create/page.tsx @@ -3,7 +3,7 @@ import { Card } from "@nextui-org/react"; export default function StaticPageGenerator() { return ( - + ); diff --git a/app/(admin)/admin/static-page/edit/[id]/page.tsx b/app/(admin)/admin/static-page/edit/[id]/page.tsx new file mode 100644 index 0000000..a548ba4 --- /dev/null +++ b/app/(admin)/admin/static-page/edit/[id]/page.tsx @@ -0,0 +1,10 @@ +import StaticPageBuilderEdit from "@/components/form/static-page/static-page-edit-form"; +import { Card } from "@nextui-org/react"; + +export default function StaticPageEdit() { + return ( + + + + ); +} diff --git a/app/static/[slug]/page.tsx b/app/static/[slug]/page.tsx new file mode 100644 index 0000000..78e091a --- /dev/null +++ b/app/static/[slug]/page.tsx @@ -0,0 +1,38 @@ +"use client"; + +import { HumasLayout } from "@/components/layout/humas-layout"; +import { getCustomStaticDetailBySlug } from "@/service/static-page-service"; +import { Card } from "@nextui-org/react"; +import { useParams } from "next/navigation"; +import { useEffect, useState } from "react"; + +export default function StaticPage() { + const params = useParams(); + const slug = params.slug; + const [htmlBody, setHtmlBody] = useState(""); + + useEffect(() => { + initFetch(); + }, [slug]); + + const initFetch = async () => { + const res = await getCustomStaticDetailBySlug(slug ? String(slug) : ""); + const data = res?.data?.data; + setHtmlBody(data?.htmlBody); + }; + + const [hasMounted, setHasMounted] = useState(false); + + useEffect(() => { + setHasMounted(true); + }, []); + + if (!hasMounted) return null; + return ( + + +
+ + + ); +} diff --git a/components/form/article/generate-article-form.tsx b/components/form/article/generate-article-form.tsx index f1b84ff..315b915 100644 --- a/components/form/article/generate-article-form.tsx +++ b/components/form/article/generate-article-form.tsx @@ -153,7 +153,7 @@ export default function GenerateArticleForm() { title: title, typeId: parseInt(String(Array.from(article)[0])), slug: slug, - categoryId: 12, + categoryId: 215, tags: tags.join(","), description: content, htmlDescription: content, diff --git a/components/form/article/generate-single-article-form.tsx b/components/form/article/generate-single-article-form.tsx index 7fe1168..bb6c08c 100644 --- a/components/form/article/generate-single-article-form.tsx +++ b/components/form/article/generate-single-article-form.tsx @@ -63,10 +63,10 @@ const singleArticleSchema = z.object({ message: "Main Keyword must be at least 2 characters.", }), title: z.string().min(2, { - message: "Main Keyword must be at least 2 characters.", + message: "Title Keyword must be at least 2 characters.", }), additionalKeyword: z.string().min(2, { - message: "Main Keyword must be at least 2 characters.", + message: "Additional Keyword must be at least 2 characters.", }), }); diff --git a/components/form/form-article.tsx b/components/form/form-article.tsx index 2df6691..e8632ea 100644 --- a/components/form/form-article.tsx +++ b/components/form/form-article.tsx @@ -146,6 +146,8 @@ export default function FormArticle() { title: title, typeId: parseInt(String(Array.from(article)[0])), slug: slug, + categoryId: 215, + oldId: 1, tags: tags.join(","), description: content, htmlDescription: content, diff --git a/components/form/static-page/static-page-edit-form.tsx b/components/form/static-page/static-page-edit-form.tsx new file mode 100644 index 0000000..3fcd331 --- /dev/null +++ b/components/form/static-page/static-page-edit-form.tsx @@ -0,0 +1,223 @@ +"use client"; +import { Input, Textarea } from "@nextui-org/input"; +import { Button, Card } from "@nextui-org/react"; +import { useCallback, useEffect, useState } from "react"; +import DOMPurify from "dompurify"; +import { Controller, useForm } from "react-hook-form"; +import * as z from "zod"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { + createCustomStaticPage, + editCustomStaticPage, + getCustomStaticDetail, +} from "@/service/static-page-service"; +import { close, error, loading } from "@/config/swal"; +import Swal from "sweetalert2"; +import withReactContent from "sweetalert2-react-content"; +import { useParams, useRouter } from "next/navigation"; + +const formSchema = z.object({ + slug: z.string().min(2, { + message: "Slug must be at least 2 characters.", + }), + title: z.string().min(2, { + message: "Title must be at least 2 characters.", + }), + description: z.string().min(2, { + message: "Main Keyword must be at least 2 characters.", + }), + htmlBody: z.string().min(2, { + message: "Main Keyword must be at least 2 characters.", + }), +}); + +export default function StaticPageBuilderEdit() { + const MySwal = withReactContent(Swal); + const router = useRouter(); + const params = useParams(); + const id = params.id; + const formOptions = { + resolver: zodResolver(formSchema), + }; + type UserSettingSchema = z.infer; + const { + control, + handleSubmit, + formState: { errors }, + watch, + setValue, + getValues, + } = useForm(formOptions); + + useEffect(() => { + initFetch(); + }, [id]); + + const initFetch = async () => { + const res = await getCustomStaticDetail(id ? String(id) : ""); + const data = res?.data?.data; + console.log("res", data); + setValue("title", data?.title); + setValue("slug", data?.slug); + setValue("description", data?.description); + setValue("htmlBody", data?.htmlBody); + }; + + const content = watch("htmlBody"); + const generatedPage = useCallback(() => { + const sanitizedContent = DOMPurify.sanitize(getValues("htmlBody")); + return ( + +
+ + ); + }, [content]); + + function createSlug(value: string): string { + return value + .toLowerCase() + .trim() + .replace(/[^a-z0-9\s-]/g, "") + .replace(/\s+/g, "-") + .replace(/-+/g, "-"); + } + + const onSubmit = async (values: z.infer) => { + const request = { + id: Number(id), + title: values.title, + slug: values.slug, + description: values.description, + htmlBody: values.htmlBody, + }; + loading(); + const res = await editCustomStaticPage(request); + + if (res?.error) { + error(res.message); + return false; + } + close(); + + successSubmit("/admin/static-page"); + }; + + function successSubmit(redirect: any) { + MySwal.fire({ + title: "Sukses", + icon: "success", + confirmButtonColor: "#3085d6", + confirmButtonText: "OK", + }).then((result) => { + if (result.isConfirmed) { + router.push(redirect); + } + }); + } + const title = watch("title"); + useEffect(() => { + if (getValues("title")) { + setValue("slug", createSlug(getValues("title"))); + } + }, [title]); + + return ( +
+ ( + + )} + /> + {errors.title?.message && ( +

{errors.title?.message}

+ )} + ( + + )} + /> + ( +