Merge pull request #421 from bipproduction/amalia/15-apr-25
Amalia/15 apr 25
This commit is contained in:
@@ -29,7 +29,12 @@
|
||||
"@mantine/tiptap": "^7.11.0",
|
||||
"@prisma/client": "5.16.1",
|
||||
"@tabler/icons-react": "^3.7.0",
|
||||
"@tiptap/extension-color": "^2.11.7",
|
||||
"@tiptap/extension-highlight": "^2.11.7",
|
||||
"@tiptap/extension-link": "^2.4.0",
|
||||
"@tiptap/extension-text-align": "^2.11.7",
|
||||
"@tiptap/extension-underline": "^2.11.7",
|
||||
"@tiptap/pm": "^2.11.7",
|
||||
"@tiptap/react": "^2.4.0",
|
||||
"@tiptap/starter-kit": "^2.4.0",
|
||||
"@types/lodash": "^4.17.6",
|
||||
|
||||
@@ -3,6 +3,7 @@ import { WrapLayout } from "@/module/_global"
|
||||
import { funDetectCookies, funGetUserByCookies } from "@/module/auth"
|
||||
import _ from "lodash"
|
||||
import { redirect } from "next/navigation"
|
||||
import '@mantine/tiptap/styles.css';
|
||||
|
||||
export default async function Layout({ children }: { children: React.ReactNode }) {
|
||||
const cookies = await funDetectCookies()
|
||||
|
||||
@@ -7,7 +7,7 @@ import { IoCloseOutline } from 'react-icons/io5';
|
||||
import { TEMA } from '../bin/val_global';
|
||||
|
||||
export default function NotificationCustomeCenter({ title, desc, onClick }: { title: string, desc: string, onClick: (val: string) => void, }) {
|
||||
const [opened, setOpened] = useState(false);
|
||||
const [opened, setOpened] = useState(false)
|
||||
const tema = useHookstate(TEMA)
|
||||
|
||||
useShallowEffect(() => {
|
||||
@@ -72,7 +72,15 @@ export default function NotificationCustomeCenter({ title, desc, onClick }: { ti
|
||||
/>
|
||||
<Text size="xl" fw={500} ta="center">PENGUMUMAN</Text>
|
||||
<Text size="sm" ta="center">{desc}</Text>
|
||||
<SimpleGrid cols={2} spacing="xs" w={'90%'}>
|
||||
<SimpleGrid
|
||||
cols={{ base: 1, sm: 2, lg: 2 }}
|
||||
spacing="xs"
|
||||
w={'90%'}>
|
||||
{/* {
|
||||
isMobile
|
||||
? <></>
|
||||
:
|
||||
<> */}
|
||||
<Button
|
||||
fullWidth
|
||||
radius="md"
|
||||
@@ -93,6 +101,8 @@ export default function NotificationCustomeCenter({ title, desc, onClick }: { ti
|
||||
>
|
||||
Tandai Telah Dibaca
|
||||
</Button>
|
||||
{/* </>
|
||||
} */}
|
||||
</SimpleGrid>
|
||||
</Flex>
|
||||
</Box>
|
||||
|
||||
@@ -2,8 +2,16 @@
|
||||
import { keyWibu, LayoutNavbarNew, TEMA } from "@/module/_global";
|
||||
import LayoutModal from "@/module/_global/layout/layout_modal";
|
||||
import { useHookstate } from "@hookstate/core";
|
||||
import { Box, Button, Flex, Group, rem, Stack, Text, Textarea, TextInput } from "@mantine/core";
|
||||
import { Box, Button, Flex, Group, rem, Stack, Text, TextInput } from "@mantine/core";
|
||||
import { useShallowEffect } from "@mantine/hooks";
|
||||
import { Link, RichTextEditor } from "@mantine/tiptap";
|
||||
import { Color } from '@tiptap/extension-color';
|
||||
import Highlight from '@tiptap/extension-highlight';
|
||||
import TextAlign from '@tiptap/extension-text-align';
|
||||
import TextStyle from '@tiptap/extension-text-style';
|
||||
import Underline from '@tiptap/extension-underline';
|
||||
import { useEditor } from "@tiptap/react";
|
||||
import StarterKit from '@tiptap/starter-kit';
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
@@ -36,6 +44,19 @@ export default function CreateAnnouncement() {
|
||||
desc: false
|
||||
});
|
||||
|
||||
const editor = useEditor({
|
||||
extensions: [
|
||||
StarterKit,
|
||||
Underline,
|
||||
Link,
|
||||
Highlight,
|
||||
TextStyle,
|
||||
Color,
|
||||
TextAlign.configure({ types: ['heading', 'paragraph'] }),
|
||||
],
|
||||
content: "",
|
||||
});
|
||||
|
||||
|
||||
async function onSubmit() {
|
||||
try {
|
||||
@@ -74,14 +95,17 @@ export default function CreateAnnouncement() {
|
||||
|
||||
|
||||
function onCheck() {
|
||||
const cek = checkAll()
|
||||
if (!cek)
|
||||
return false
|
||||
onValidation('desc', '')
|
||||
setTimeout(() => {
|
||||
const cek = checkAll()
|
||||
if (!cek)
|
||||
return false
|
||||
|
||||
if (memberValue.length == 0)
|
||||
return toast.error("Error! silahkan pilih divisi")
|
||||
if (memberValue.length == 0)
|
||||
return toast.error("Error! silahkan pilih divisi")
|
||||
|
||||
setOpen(true)
|
||||
setOpen(true)
|
||||
}, 500)
|
||||
}
|
||||
|
||||
function checkAll() {
|
||||
@@ -90,14 +114,16 @@ export default function CreateAnnouncement() {
|
||||
setTouched(touched => ({ ...touched, title: true }))
|
||||
nilai = false
|
||||
}
|
||||
if (isData.desc === "") {
|
||||
if (String(editor?.getHTML()) === "" || String(editor?.getHTML()) === "<p></p>" || String(editor?.getHTML()) === "undefined") {
|
||||
setTouched(touched => ({ ...touched, desc: true }))
|
||||
nilai = false
|
||||
toast.error("Pengumuman Tidak Boleh Kosong!")
|
||||
}
|
||||
return nilai
|
||||
}
|
||||
|
||||
|
||||
|
||||
function onValidation(kategori: string, val: string) {
|
||||
if (kategori == 'title') {
|
||||
setisData({ ...isData, title: val })
|
||||
@@ -107,15 +133,16 @@ export default function CreateAnnouncement() {
|
||||
setTouched({ ...touched, title: false })
|
||||
}
|
||||
} else if (kategori == 'desc') {
|
||||
setisData({ ...isData, desc: val })
|
||||
if (val === "") {
|
||||
setTouched({ ...touched, desc: true })
|
||||
} else {
|
||||
setTouched({ ...touched, desc: false })
|
||||
}
|
||||
setisData({ ...isData, desc: String(editor?.getHTML()) })
|
||||
// if (val === "") {
|
||||
// setTouched({ ...touched, desc: true })
|
||||
// } else {
|
||||
// setTouched({ ...touched, desc: false })
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (isChooseMember) return <CreateUsersAnnouncement onClose={() => { setIsChooseMember(false) }} />
|
||||
|
||||
return (
|
||||
@@ -141,7 +168,7 @@ export default function CreateAnnouncement() {
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Textarea
|
||||
{/* <Textarea
|
||||
size="md"
|
||||
radius={10}
|
||||
w={"100%"}
|
||||
@@ -162,7 +189,75 @@ export default function CreateAnnouncement() {
|
||||
isData.desc == "" ? "Pengumuman Tidak Boleh Kosong" : null
|
||||
)
|
||||
}
|
||||
/>
|
||||
/> */}
|
||||
<Box>
|
||||
<Group gap="xs">
|
||||
<Text>Pengumuman</Text>
|
||||
<Text c={'red'}>*</Text>
|
||||
</Group>
|
||||
<RichTextEditor editor={editor} style={{ border: `1px solid ${tema.get().utama}` }}>
|
||||
<RichTextEditor.Toolbar sticky stickyOffset={60}>
|
||||
<RichTextEditor.ControlsGroup>
|
||||
<RichTextEditor.Bold />
|
||||
<RichTextEditor.Italic />
|
||||
<RichTextEditor.Underline />
|
||||
<RichTextEditor.Strikethrough />
|
||||
<RichTextEditor.Highlight />
|
||||
</RichTextEditor.ControlsGroup>
|
||||
|
||||
<RichTextEditor.ControlsGroup>
|
||||
<RichTextEditor.H1 />
|
||||
<RichTextEditor.H2 />
|
||||
<RichTextEditor.H3 />
|
||||
<RichTextEditor.H4 />
|
||||
</RichTextEditor.ControlsGroup>
|
||||
|
||||
<RichTextEditor.ControlsGroup>
|
||||
<RichTextEditor.Hr />
|
||||
<RichTextEditor.BulletList />
|
||||
<RichTextEditor.OrderedList />
|
||||
</RichTextEditor.ControlsGroup>
|
||||
|
||||
<RichTextEditor.ControlsGroup>
|
||||
<RichTextEditor.AlignLeft />
|
||||
<RichTextEditor.AlignCenter />
|
||||
<RichTextEditor.AlignJustify />
|
||||
<RichTextEditor.AlignRight />
|
||||
</RichTextEditor.ControlsGroup>
|
||||
|
||||
<RichTextEditor.ColorPicker
|
||||
colors={[
|
||||
'#25262b',
|
||||
'#868e96',
|
||||
'#fa5252',
|
||||
'#e64980',
|
||||
'#be4bdb',
|
||||
'#7950f2',
|
||||
'#4c6ef5',
|
||||
'#228be6',
|
||||
'#15aabf',
|
||||
'#12b886',
|
||||
'#40c057',
|
||||
'#82c91e',
|
||||
'#fab005',
|
||||
'#fd7e14',
|
||||
]}
|
||||
/>
|
||||
|
||||
<RichTextEditor.ControlsGroup>
|
||||
<RichTextEditor.Color color="#F03E3E" />
|
||||
<RichTextEditor.Color color="#7048E8" />
|
||||
<RichTextEditor.Color color="#1098AD" />
|
||||
<RichTextEditor.Color color="#37B24D" />
|
||||
<RichTextEditor.Color color="#F59F00" />
|
||||
</RichTextEditor.ControlsGroup>
|
||||
<RichTextEditor.UnsetColor />
|
||||
</RichTextEditor.Toolbar>
|
||||
|
||||
<RichTextEditor.Content />
|
||||
</RichTextEditor>
|
||||
</Box>
|
||||
|
||||
<Box pt={10}>
|
||||
<Group justify="space-between" style={{
|
||||
border: `1px solid ${tema.get().utama}`,
|
||||
|
||||
@@ -95,7 +95,7 @@ export default function DetailAnnouncement({ id }: { id: string }) {
|
||||
</Grid.Col>
|
||||
<Grid.Col span={10}>
|
||||
<Spoiler maxHeight={100} showLabel="Lebih banyak" hideLabel="Lebih sedikit">
|
||||
<Text>{isData?.desc}</Text>
|
||||
<Box dangerouslySetInnerHTML={{ __html: String(isData?.desc) }} />
|
||||
</Spoiler>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
|
||||
@@ -2,8 +2,16 @@
|
||||
import { LayoutNavbarNew, TEMA } from "@/module/_global";
|
||||
import LayoutModal from "@/module/_global/layout/layout_modal";
|
||||
import { useHookstate } from "@hookstate/core";
|
||||
import { Box, Button, Flex, Group, List, rem, Skeleton, Stack, Text, Textarea, TextInput } from "@mantine/core";
|
||||
import { Box, Button, Flex, Group, List, rem, Skeleton, Stack, Text, TextInput } from "@mantine/core";
|
||||
import { useShallowEffect } from "@mantine/hooks";
|
||||
import { Link, RichTextEditor } from "@mantine/tiptap";
|
||||
import Color from "@tiptap/extension-color";
|
||||
import Highlight from '@tiptap/extension-highlight';
|
||||
import TextAlign from "@tiptap/extension-text-align";
|
||||
import TextStyle from "@tiptap/extension-text-style";
|
||||
import Underline from "@tiptap/extension-underline";
|
||||
import { useEditor } from "@tiptap/react";
|
||||
import StarterKit from "@tiptap/starter-kit";
|
||||
import { useParams, useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
@@ -15,7 +23,6 @@ import EditChooseMember from "./edit_choose_member";
|
||||
|
||||
export default function EditAnnouncement() {
|
||||
const [isOpen, setOpen] = useState(false)
|
||||
const [loadingKonfirmasi, setLoadingKonfirmasi] = useState(false)
|
||||
const [isChooseDivisi, setChooseDivisi] = useState(false)
|
||||
const param = useParams<{ id: string }>()
|
||||
const [loading, setLoading] = useState(true)
|
||||
@@ -32,6 +39,19 @@ export default function EditAnnouncement() {
|
||||
})
|
||||
const memberGroup = useHookstate(globalMemberEditAnnouncement)
|
||||
|
||||
const editor = useEditor({
|
||||
extensions: [
|
||||
StarterKit,
|
||||
Underline,
|
||||
Link,
|
||||
Highlight,
|
||||
TextStyle,
|
||||
Color,
|
||||
TextAlign.configure({ types: ['heading', 'paragraph'] }),
|
||||
],
|
||||
content: body.desc,
|
||||
});
|
||||
|
||||
|
||||
async function fetchOneAnnouncement() {
|
||||
try {
|
||||
@@ -60,16 +80,11 @@ export default function EditAnnouncement() {
|
||||
})
|
||||
arrNew.push(newObject)
|
||||
})
|
||||
|
||||
|
||||
memberGroup.set(arrNew)
|
||||
|
||||
} else {
|
||||
toast.error(res.message)
|
||||
}
|
||||
|
||||
setLoading(false)
|
||||
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
toast.error("Gagal mendapatkan pengumuman, coba lagi nanti")
|
||||
@@ -84,12 +99,16 @@ export default function EditAnnouncement() {
|
||||
fetchOneAnnouncement()
|
||||
}, [])
|
||||
|
||||
useShallowEffect(() => {
|
||||
editor?.commands.insertContent(body.desc)
|
||||
}, [editor, body.desc])
|
||||
|
||||
async function onSubmit() {
|
||||
try {
|
||||
setLoadingSubmit(true)
|
||||
const response = await funEditAnnouncement(param.id, {
|
||||
title: body.title,
|
||||
desc: body.desc,
|
||||
desc: String(editor?.getHTML()),
|
||||
groups: memberGroup.get() as GroupData[]
|
||||
})
|
||||
|
||||
@@ -109,10 +128,10 @@ export default function EditAnnouncement() {
|
||||
}
|
||||
|
||||
function onCheck() {
|
||||
if (Object.values(touched).some((v) => v == true))
|
||||
return false
|
||||
if (Object.values(touched).some((v) => v == true) || String(editor?.getHTML()) === "" || String(editor?.getHTML()) === "<p></p>" || String(editor?.getHTML()) === "undefined")
|
||||
return toast.error("Error! Judul dan pengumuman tidak boleh kosong")
|
||||
if (memberGroup.get().length == 0)
|
||||
return toast.error("Error! silahkan pilih divisi")
|
||||
return toast.error("Error! sila∏hkan pilih divisi")
|
||||
setOpen(true)
|
||||
}
|
||||
|
||||
@@ -126,8 +145,7 @@ export default function EditAnnouncement() {
|
||||
setTouched({ ...touched, title: false })
|
||||
}
|
||||
} else if (kategori == 'desc') {
|
||||
setBody({ ...body, desc: val })
|
||||
if (val === "") {
|
||||
if (String(editor?.getHTML()) === "" || String(editor?.getHTML()) === "<p></p>" || String(editor?.getHTML()) === "undefined") {
|
||||
setTouched({ ...touched, desc: true })
|
||||
} else {
|
||||
setTouched({ ...touched, desc: false })
|
||||
@@ -166,14 +184,16 @@ export default function EditAnnouncement() {
|
||||
},
|
||||
}}
|
||||
value={body.title}
|
||||
onChange={(e) => { onValidation('title', e.target.value) }}
|
||||
onChange={(e) => {
|
||||
onValidation('title', e.target.value)
|
||||
}}
|
||||
error={
|
||||
touched.title && (
|
||||
body.title == "" ? "Judul Tidak Boleh Kosong" : null
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Textarea
|
||||
{/* <Textarea
|
||||
size="md"
|
||||
radius={10}
|
||||
w={"100%"}
|
||||
@@ -194,7 +214,76 @@ export default function EditAnnouncement() {
|
||||
body.desc == "" ? "Pengumuman Tidak Boleh Kosong" : null
|
||||
)
|
||||
}
|
||||
/>
|
||||
/> */}
|
||||
|
||||
<Box>
|
||||
<Group gap="xs">
|
||||
<Text>Pengumuman</Text>
|
||||
<Text c={'red'}>*</Text>
|
||||
</Group>
|
||||
<RichTextEditor editor={editor} style={{ border: `1px solid ${tema.get().utama}` }}>
|
||||
<RichTextEditor.Toolbar sticky stickyOffset={60}>
|
||||
<RichTextEditor.ControlsGroup>
|
||||
<RichTextEditor.Bold />
|
||||
<RichTextEditor.Italic />
|
||||
<RichTextEditor.Underline />
|
||||
<RichTextEditor.Strikethrough />
|
||||
<RichTextEditor.Highlight />
|
||||
</RichTextEditor.ControlsGroup>
|
||||
|
||||
<RichTextEditor.ControlsGroup>
|
||||
<RichTextEditor.H1 />
|
||||
<RichTextEditor.H2 />
|
||||
<RichTextEditor.H3 />
|
||||
<RichTextEditor.H4 />
|
||||
</RichTextEditor.ControlsGroup>
|
||||
|
||||
<RichTextEditor.ControlsGroup>
|
||||
<RichTextEditor.Hr />
|
||||
<RichTextEditor.BulletList />
|
||||
<RichTextEditor.OrderedList />
|
||||
</RichTextEditor.ControlsGroup>
|
||||
|
||||
<RichTextEditor.ControlsGroup>
|
||||
<RichTextEditor.AlignLeft />
|
||||
<RichTextEditor.AlignCenter />
|
||||
<RichTextEditor.AlignJustify />
|
||||
<RichTextEditor.AlignRight />
|
||||
</RichTextEditor.ControlsGroup>
|
||||
|
||||
<RichTextEditor.ColorPicker
|
||||
colors={[
|
||||
'#25262b',
|
||||
'#868e96',
|
||||
'#fa5252',
|
||||
'#e64980',
|
||||
'#be4bdb',
|
||||
'#7950f2',
|
||||
'#4c6ef5',
|
||||
'#228be6',
|
||||
'#15aabf',
|
||||
'#12b886',
|
||||
'#40c057',
|
||||
'#82c91e',
|
||||
'#fab005',
|
||||
'#fd7e14',
|
||||
]}
|
||||
/>
|
||||
|
||||
<RichTextEditor.ControlsGroup>
|
||||
<RichTextEditor.Color color="#F03E3E" />
|
||||
<RichTextEditor.Color color="#7048E8" />
|
||||
<RichTextEditor.Color color="#1098AD" />
|
||||
<RichTextEditor.Color color="#37B24D" />
|
||||
<RichTextEditor.Color color="#F59F00" />
|
||||
</RichTextEditor.ControlsGroup>
|
||||
<RichTextEditor.UnsetColor />
|
||||
</RichTextEditor.Toolbar>
|
||||
|
||||
<RichTextEditor.Content />
|
||||
</RichTextEditor>
|
||||
</Box>
|
||||
|
||||
<Box pt={10} w={"100%"}>
|
||||
<Group justify="space-between" style={{
|
||||
border: `1px solid ${tema.get().utama}`,
|
||||
|
||||
@@ -182,9 +182,12 @@ export default function ListAnnouncement() {
|
||||
</Grid>
|
||||
{/* <Text c={tema.get().utama} lineClamp={2}>{v.desc}</Text> */}
|
||||
<Spoiler maxHeight={50} showLabel="Lebih banyak" hideLabel="Lebih sedikit">
|
||||
<Text c={tema.get().utama} onClick={() => {
|
||||
router.push(`/announcement/${v.id}`)
|
||||
}} >{v.desc}</Text>
|
||||
<Box
|
||||
dangerouslySetInnerHTML={{ __html: String(v.desc) }}
|
||||
onClick={() => {
|
||||
router.push(`/announcement/${v.id}`)
|
||||
}}
|
||||
/>
|
||||
</Spoiler>
|
||||
</Grid.Col>
|
||||
</Grid>
|
||||
|
||||
Reference in New Issue
Block a user