Jum'at, 30 May 2025 :
Yang Sudah Di Kerjakan * Tampilan UI Admin di menu inovasi * API Create, edit dan delete potensi * Tampilan UI Landing Page sudah sesuai di mobile Yang Lagi Dikerjakan: * Progress Tampilan UI Admin Di Menu lingkungan * Progress API Create, edit dan delete potensi Yang Akan Dikerjakan: * API Create, edit dan delete pengumuman * Tampilan UI Admin Di Menu Pendidikan
This commit is contained in:
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
"use client";
|
||||
|
||||
import {
|
||||
@@ -15,19 +14,19 @@ import {
|
||||
Title,
|
||||
} from "@mantine/core";
|
||||
import { IconArrowBack, IconImageInPicture } from "@tabler/icons-react";
|
||||
import { useParams, useRouter } from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useRouter, useParams } from "next/navigation";
|
||||
import { useProxy } from "valtio/utils";
|
||||
import { toast } from "react-toastify";
|
||||
import { useProxy } from "valtio/utils";
|
||||
|
||||
|
||||
import EditEditor from "@/app/admin/(dashboard)/_com/editEditor";
|
||||
import colors from "@/con/colors";
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { FileInput } from "@mantine/core";
|
||||
import stateDashboardBerita from "../../../../_state/desa/berita";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { useShallowEffect } from "@mantine/hooks";
|
||||
import { BeritaEditor } from "../../_com/BeritaEditor";
|
||||
import colors from "@/con/colors";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import stateDashboardBerita from "../../../../_state/desa/berita";
|
||||
|
||||
function EditBerita() {
|
||||
const beritaState = useProxy(stateDashboardBerita);
|
||||
@@ -36,8 +35,6 @@ function EditBerita() {
|
||||
|
||||
const [previewImage, setPreviewImage] = useState<string | null>(null);
|
||||
const [file, setFile] = useState<File | null>(null);
|
||||
const [editorInstance, setEditorInstance] = useState<any>(null);
|
||||
const [isEditorReady, setIsEditorReady] = useState(false);
|
||||
const [formData, setFormData] = useState({
|
||||
judul: beritaState.berita.edit.form.judul || '',
|
||||
deskripsi: beritaState.berita.edit.form.deskripsi || '',
|
||||
@@ -76,28 +73,7 @@ function EditBerita() {
|
||||
loadBerita();
|
||||
}, [params?.id]); // ✅ hapus beritaState dari dependency
|
||||
|
||||
|
||||
|
||||
// Handle editor ready
|
||||
const handleEditorReady = (editor: any) => {
|
||||
setEditorInstance(editor);
|
||||
setIsEditorReady(true);
|
||||
|
||||
// Set initial content if exists
|
||||
if (formData.content) {
|
||||
editor.commands.setContent(formData.content);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!isEditorReady || !editorInstance) {
|
||||
return toast.error("Editor belum siap");
|
||||
}
|
||||
|
||||
const htmlContent = editorInstance.getHTML();
|
||||
if (!htmlContent || htmlContent === "<p></p>") {
|
||||
return toast.warn("Konten tidak boleh kosong");
|
||||
}
|
||||
|
||||
try {
|
||||
// Update global state with form data
|
||||
@@ -105,7 +81,7 @@ function EditBerita() {
|
||||
...beritaState.berita.edit.form,
|
||||
judul: formData.judul,
|
||||
deskripsi: formData.deskripsi,
|
||||
content: htmlContent,
|
||||
content: formData.content,
|
||||
kategoriBeritaId: formData.kategoriBeritaId || '',
|
||||
imageId: formData.imageId // Keep existing imageId if not changed
|
||||
};
|
||||
@@ -189,14 +165,12 @@ function EditBerita() {
|
||||
|
||||
<Box>
|
||||
<Text fz={"sm"} fw={"bold"}>Konten</Text>
|
||||
<BeritaEditor
|
||||
initialContent={formData.content}
|
||||
onEditorReady={handleEditorReady}
|
||||
showSubmit={false}
|
||||
onUpdate={(content) => {
|
||||
setFormData((prev) => ({ ...prev, content }));
|
||||
beritaState.berita.edit.form.content = content;
|
||||
}}
|
||||
<EditEditor
|
||||
value={formData.content}
|
||||
onChange={(htmlContent) => {
|
||||
setFormData((prev) => ({ ...prev, content: htmlContent }));
|
||||
beritaState.berita.edit.form.content = htmlContent;
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
@@ -8,8 +8,8 @@ import { useParams, useRouter } from 'next/navigation';
|
||||
import { useState } from 'react';
|
||||
|
||||
import colors from '@/con/colors';
|
||||
import { ModalKonfirmasiHapus } from '../../../../_com/modalKonfirmasiHapus';
|
||||
import stateDashboardBerita from '../../../../_state/desa/berita';
|
||||
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
|
||||
import stateDashboardBerita from '../../../_state/desa/berita';
|
||||
|
||||
function DetailBerita() {
|
||||
const beritaState = useProxy(stateDashboardBerita)
|
||||
@@ -45,52 +45,64 @@ function DetailBerita() {
|
||||
return (
|
||||
<Box>
|
||||
<Box mb={10}>
|
||||
<Button variant="subtle" onClick={() => router.back()}>
|
||||
<IconArrowBack color={colors['blue-button']} size={25} />
|
||||
</Button>
|
||||
<Button variant="subtle" onClick={() => router.back()}>
|
||||
<IconArrowBack color={colors['blue-button']} size={25} />
|
||||
</Button>
|
||||
</Box>
|
||||
<Paper bg={colors['white-1']} w={{ base: "100%", md: "100%", lg: "50%" }} p={'md'}>
|
||||
<Stack>
|
||||
<Text fz={"xl"} fw={"bold"}>Detail Berita</Text>
|
||||
{beritaState.berita.findUnique.data ? (
|
||||
<Paper key={beritaState.berita.findUnique.data.id} bg={colors['BG-trans']} p={'md'}>
|
||||
{beritaState.berita.findUnique.data ? (
|
||||
<Paper key={beritaState.berita.findUnique.data.id} bg={colors['BG-trans']} p={'md'}>
|
||||
<Stack gap={"xs"}>
|
||||
<Box>
|
||||
<Text fw={"bold"} fz={"lg"}>Kategori</Text>
|
||||
<Text fz={"lg"}>{beritaState.berita.findUnique.data?.kategoriBerita?.name}</Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fw={"bold"} fz={"lg"}>Judul</Text>
|
||||
<Text fz={"lg"}>{beritaState.berita.findUnique.data?.judul}</Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fw={"bold"} fz={"lg"}>Deskripsi</Text>
|
||||
<Text fz={"lg"} >{beritaState.berita.findUnique.data?.deskripsi}</Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fw={"bold"} fz={"lg"}>Gambar</Text>
|
||||
<Image w={{ base: 150, md: 150, lg: 150 }} src={beritaState.berita.findUnique.data?.image?.link} alt="gambar" />
|
||||
<Flex gap={"xs"} mt={10}>
|
||||
<Button
|
||||
onClick={() => {
|
||||
if (beritaState.berita.findUnique.data) {
|
||||
setSelectedId(beritaState.berita.findUnique.data.id);
|
||||
setModalHapus(true);
|
||||
}
|
||||
}}
|
||||
disabled={beritaState.berita.delete.loading || !beritaState.berita.findUnique.data}
|
||||
color={"red"}
|
||||
>
|
||||
<IconX size={20} />
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
if (beritaState.berita.findUnique.data) {
|
||||
router.push(`/admin/desa/berita/edit/${beritaState.berita.findUnique.data.id}`);
|
||||
}
|
||||
}}
|
||||
disabled={!beritaState.berita.findUnique.data}
|
||||
color={"green"}
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Flex>
|
||||
</Box>
|
||||
</Paper>
|
||||
) : null}
|
||||
<Box>
|
||||
<Text fw={"bold"} fz={"lg"}>Konten</Text>
|
||||
<Text fz={"lg"} dangerouslySetInnerHTML={{ __html: beritaState.berita.findUnique.data?.content }} />
|
||||
</Box>
|
||||
<Flex gap={"xs"} mt={10}>
|
||||
<Button
|
||||
onClick={() => {
|
||||
if (beritaState.berita.findUnique.data) {
|
||||
setSelectedId(beritaState.berita.findUnique.data.id);
|
||||
setModalHapus(true);
|
||||
}
|
||||
}}
|
||||
disabled={beritaState.berita.delete.loading || !beritaState.berita.findUnique.data}
|
||||
color={"red"}
|
||||
>
|
||||
<IconX size={20} />
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
if (beritaState.berita.findUnique.data) {
|
||||
router.push(`/admin/desa/berita/${beritaState.berita.findUnique.data.id}/edit`);
|
||||
}
|
||||
}}
|
||||
disabled={!beritaState.berita.findUnique.data}
|
||||
color={"green"}
|
||||
>
|
||||
<IconEdit size={20} />
|
||||
</Button>
|
||||
</Flex>
|
||||
</Stack>
|
||||
</Paper>
|
||||
) : null}
|
||||
</Stack>
|
||||
</Paper>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import ApiFetch from '@/lib/api-fetch';
|
||||
@@ -10,14 +9,13 @@ import { useRouter } from 'next/navigation';
|
||||
import { useState } from 'react';
|
||||
import { toast } from 'react-toastify';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import CreateEditor from '../../../_com/createEditor';
|
||||
import stateDashboardBerita from '../../../_state/desa/berita';
|
||||
import { BeritaEditor } from '../_com/BeritaEditor';
|
||||
|
||||
export default function CreateBerita() {
|
||||
const beritaState = useProxy(stateDashboardBerita);
|
||||
const [previewImage, setPreviewImage] = useState<string | null>(null);
|
||||
const [file, setFile] = useState<File | null>(null);
|
||||
const [editorInstance, setEditorInstance] = useState<any>(null);
|
||||
const router = useRouter()
|
||||
|
||||
const resetForm = () => {
|
||||
@@ -33,21 +31,12 @@ export default function CreateBerita() {
|
||||
// Reset state lokal
|
||||
setPreviewImage(null);
|
||||
setFile(null);
|
||||
if (editorInstance) {
|
||||
editorInstance.commands.setContent(""); // Kosongkan editor
|
||||
}
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
if (!file) {
|
||||
return toast.warn("Pilih file gambar terlebih dahulu");
|
||||
}
|
||||
if (!editorInstance) return toast.error("Editor belum siap");
|
||||
|
||||
const htmlContent = editorInstance.getHTML();
|
||||
if (!htmlContent || htmlContent === "<p></p>") return toast.warn("Konten tidak boleh kosong");
|
||||
|
||||
beritaState.berita.create.form.content = htmlContent;
|
||||
|
||||
// Upload gambar dulu
|
||||
const res = await ApiFetch.api.fileStorage.create.post({
|
||||
@@ -124,9 +113,11 @@ export default function CreateBerita() {
|
||||
)}
|
||||
<Box>
|
||||
<Text fz={"sm"} fw={"bold"}>Konten</Text>
|
||||
<BeritaEditor
|
||||
showSubmit={false}
|
||||
onEditorReady={(ed) => setEditorInstance(ed)}
|
||||
<CreateEditor
|
||||
value={beritaState.berita.create.form.content}
|
||||
onChange={(htmlContent) => {
|
||||
beritaState.berita.create.form.content = htmlContent;
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<Button bg={colors['blue-button']} onClick={handleSubmit}>Simpan Berita</Button>
|
||||
|
||||
@@ -163,7 +163,7 @@ function BeritaList() {
|
||||
<Image w={100} src={item.image?.link} alt="gambar" />
|
||||
</TableTd>
|
||||
<TableTd>
|
||||
<Button bg={"green"} onClick={() => router.push(`/admin/desa/berita/detail/${item.id}`)}>
|
||||
<Button bg={"green"} onClick={() => router.push(`/admin/desa/berita/${item.id}`)}>
|
||||
<IconDeviceImacCog size={25} />
|
||||
</Button>
|
||||
</TableTd>
|
||||
|
||||
Reference in New Issue
Block a user