Merge pull request #146 from bipproduction/lukman/26-agustus-2024

feat : update validation
This commit is contained in:
Amalia
2024-08-26 17:36:32 +08:00
committed by GitHub
27 changed files with 762 additions and 318 deletions

View File

@@ -26,6 +26,10 @@ export default function CreateAnnouncement() {
title: "",
desc: "",
})
const [touched, setTouched] = useState({
title: false,
desc: false
});
async function onSubmit() {
@@ -85,7 +89,16 @@ export default function CreateAnnouncement() {
},
}}
value={isData.title}
onChange={(e) => { setisData({ ...isData, title: e.target.value }) }}
onChange={(e) => {
setisData({ ...isData, title: e.target.value })
setTouched({ ...touched, title: false })
}}
onBlur={() => setTouched({ ...touched, title: true })}
error={
touched.title && (
isData.title == "" ? "Judul Tidak Boleh Kosong" : null
)
}
/>
<Textarea
size="md"
@@ -102,7 +115,16 @@ export default function CreateAnnouncement() {
},
}}
value={isData.desc}
onChange={(e) => { setisData({ ...isData, desc: e.target.value }) }}
onChange={(e) => {
setisData({ ...isData, desc: e.target.value })
setTouched({ ...touched, desc: false })
}}
onBlur={() => setTouched({ ...touched, desc: true })}
error={
touched.desc && (
isData.desc == "" ? "Pengumuman Tidak Boleh Kosong" : null
)
}
/>
<Box pt={10}>
<Group justify="space-between" style={{
@@ -145,7 +167,16 @@ export default function CreateAnnouncement() {
size="md"
radius={30}
fullWidth
onClick={() => { setOpen(true) }}
onClick={() => {
if (
isData.title !== "" &&
isData.desc !== ""
) {
setOpen(true)
} else {
toast.error("Isi data dengan lengkap")
}
}}
>
Simpan
</Button>

View File

@@ -17,6 +17,10 @@ export default function EditAnnouncement() {
const [isOpen, setOpen] = useState(false)
const [isChooseDivisi, setChooseDivisi] = useState(false)
const param = useParams<{ id: string }>()
const [touched, setTouched] = useState({
title: false,
desc: false
});
const [body, setBody] = useState({
title: "",
desc: "",
@@ -116,7 +120,16 @@ export default function EditAnnouncement() {
},
}}
value={body.title}
onChange={(val) => setBody({ ...body, title: val.target.value })}
onChange={(val) => {
setBody({ ...body, title: val.target.value })
setTouched({ ...touched, title: false })
}}
onBlur={() => setTouched({ ...touched, title: true })}
error={
touched.title && (
body.title == "" ? "Judul Tidak Boleh Kosong" : null
)
}
/>
<Textarea
size="md"
@@ -133,7 +146,17 @@ export default function EditAnnouncement() {
},
}}
value={body.desc}
onChange={(val) => setBody({ ...body, desc: val.target.value })}
onChange={(val) => {
setBody({ ...body, desc: val.target.value })
setTouched({ ...touched, desc: false })
}}
onBlur={() => setTouched({ ...touched, desc: true })}
error={
touched.desc && (
body.desc == "" ? "Pengumuman Tidak Boleh Kosong" : null
)
}
/>
<Button onClick={() => { setChooseDivisi(true) }} rightSection={<HiOutlineChevronRight size={14} />} variant="default" fullWidth radius={30} size="md" mt={10}>
@@ -169,7 +192,16 @@ export default function EditAnnouncement() {
size="md"
radius={30}
fullWidth
onClick={() => { setOpen(true) }}
onClick={() => {
if (
body.title !== "" &&
body.desc !== ""
) {
setOpen(true)
} else {
toast.error("Isi data dengan lengkap")
}
}}
>
Simpan
</Button>

View File

@@ -1,6 +1,6 @@
'use client'
import { LayoutDrawer, LayoutNavbarNew, WARNA } from '@/module/_global';
import { ActionIcon, Avatar, Box, CopyButton, Flex, Group, Stack, Text, Tooltip } from '@mantine/core';
import { LayoutDrawer, LayoutNavbarNew, SkeletonSingle, WARNA } from '@/module/_global';
import { ActionIcon, Avatar, Box, CopyButton, Flex, Group, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
import React, { useState } from 'react';
import { BsCalendar2Event, BsCalendarDate } from 'react-icons/bs';
import { MdEventNote, MdOutlineFormatListBulleted } from "react-icons/md";
@@ -15,6 +15,7 @@ import { useShallowEffect } from '@mantine/hooks';
import moment from "moment";
import "moment/locale/id";
import { IDataDetailByIdCalender, IDataDetailByIdMember } from '../lib/type_calender';
import SkeletonDetailEvent from './skeleton_detail_event';
export default function DetailEventDivision() {
const [openDrawer, setOpenDrawer] = useState(false)
@@ -22,16 +23,21 @@ export default function DetailEventDivision() {
const [isDataCalender, setDataCalender] = useState<IDataDetailByIdCalender>()
const [isDataAnggota, setDataAnggota] = useState<IDataDetailByIdMember[]>([])
const [isLengthMember, setLengthMember] = useState()
const [loading, setLoading] = useState(true)
const getData = async () => {
try {
setLoading(true)
const response = await funGetOneCalender(param.detail)
setDataCalender(response.data.calender)
setDataAnggota(response.data.member)
setLengthMember(response.data.total)
setLoading(false)
} catch (error) {
console.log(error)
} finally {
setLoading(false)
}
}
@@ -41,104 +47,142 @@ export default function DetailEventDivision() {
return (
<Box>
<LayoutNavbarNew back="" title="Detail Event"
<LayoutNavbarNew back={`/division/${param.id}/calender/`} title="Detail Event"
menu={<ActionIcon variant="light" onClick={() => setOpenDrawer(true)} bg={WARNA.bgIcon} size="lg" radius="lg" aria-label="Settings">
<HiMenu size={20} color='white' />
</ActionIcon>} />
<Box p={20}>
<Box style={{
border: `1px solid ${"#D8D8F1"}`,
padding: 20,
borderRadius: 10
}}>
<Stack ml={10}>
<Group mb={10} gap={30}>
<BsCalendar2Event size={25} color={WARNA.biruTua} />
<Text>{isDataCalender?.title}</Text>
</Group>
<Group mb={10} gap={30}>
<BsCalendarDate size={25} color={WARNA.biruTua} />
<Text>{moment(isDataCalender?.dateStart).format('LL')}</Text>
</Group>
<Group mb={10} gap={30}>
<LuClock size={25} color={WARNA.biruTua} />
<Text>{isDataCalender?.timeStart} | {isDataCalender?.timeEnd} </Text>
</Group>
<Group mb={10} gap={30}>
<BsCalendarDate size={25} color={WARNA.biruTua} />
<Text>
{isDataCalender?.repeatEventTyper.toString() === '1' ? 'Acara 1 Kali' :
isDataCalender?.repeatEventTyper.toString() === '2' ? 'Hari Kerja (senin - jumat)' :
isDataCalender?.repeatEventTyper.toString() === '3' ? 'Minggu' :
isDataCalender?.repeatEventTyper.toString() === '4' ? 'Bulanan' :
isDataCalender?.repeatEventTyper.toString() === '5' ? 'Tahunan' :
''}
</Text>
</Group>
<Group mb={10} gap={30}>
<LuLink size={25} color={WARNA.biruTua} />
<Group justify='space-between'>
<Text>{isDataCalender?.linkMeet}</Text>
<CopyButton value={String(isDataCalender?.linkMeet)} timeout={2000}>
{({ copied, copy }) => (
<Tooltip label={copied ? 'Copied' : 'Copy'} withArrow position="right">
<ActionIcon color={copied ? 'teal' : WARNA.biruTua} variant="subtle" onClick={copy}>
{copied ? (
<FaCheck size={20} />
) : (
<TbCopy size={20} />
)}
</ActionIcon>
</Tooltip>
)}
</CopyButton>
{loading
?
<SkeletonDetailEvent/>
:
<Box style={{
border: `1px solid ${"#D8D8F1"}`,
padding: 20,
borderRadius: 10
}}>
<Stack ml={10}>
<Group mb={10} gap={30}>
<BsCalendar2Event size={25} color={WARNA.biruTua} />
<Text>{isDataCalender?.title}</Text>
</Group>
</Group>
<Group gap={30}>
<MdOutlineFormatListBulleted size={25} color={WARNA.biruTua} />
<Text>{isDataCalender?.desc}</Text>
</Group>
</Stack>
</Box>
<Box pt={20}>
<Group justify='space-between'>
<Text fw={"bold"}>Total Anggota</Text>
<Text>{isLengthMember} Anggota</Text>
</Group>
<Box mb={20}>
<Group mb={10} gap={30}>
<BsCalendarDate size={25} color={WARNA.biruTua} />
<Text>{moment(isDataCalender?.dateStart).format('LL')}</Text>
</Group>
<Group mb={10} gap={30}>
<LuClock size={25} color={WARNA.biruTua} />
<Text>{isDataCalender?.timeStart} | {isDataCalender?.timeEnd} </Text>
</Group>
<Group mb={10} gap={30}>
<BsCalendarDate size={25} color={WARNA.biruTua} />
<Text>
{isDataCalender?.repeatEventTyper.toString() === '1' ? 'Acara 1 Kali' :
isDataCalender?.repeatEventTyper.toString() === '2' ? 'Hari Kerja (senin - jumat)' :
isDataCalender?.repeatEventTyper.toString() === '3' ? 'Minggu' :
isDataCalender?.repeatEventTyper.toString() === '4' ? 'Bulanan' :
isDataCalender?.repeatEventTyper.toString() === '5' ? 'Tahunan' :
''}
</Text>
</Group>
<Group mb={10} gap={30}>
<LuLink size={25} color={WARNA.biruTua} />
{isDataCalender?.linkMeet ? (
<Group justify='space-between'>
<Text>{isDataCalender?.linkMeet}</Text>
<CopyButton value={String(isDataCalender?.linkMeet)} timeout={2000}>
{({ copied, copy }) => (
<Tooltip label={copied ? 'Copied' : 'Copy'} withArrow position="right">
<ActionIcon color={copied ? 'teal' : WARNA.biruTua} variant="subtle" onClick={copy}>
{copied ? (
<FaCheck size={20} />
) : (
<TbCopy size={20} />
)}
</ActionIcon>
</Tooltip>
)}
</CopyButton>
</Group>
) : (
<Text>-</Text>
)
}
</Group>
<Group gap={30}>
<MdOutlineFormatListBulleted size={25} color={WARNA.biruTua} />
{isDataCalender?.desc ? (
<Text>{isDataCalender?.desc}</Text>
) : (
<Text>-</Text>
)
}
</Group>
</Stack>
</Box>
}
{loading ?
<Box pt={20}>
<Box
style={{
border: `1px solid ${"#C7D6E8"}`,
borderRadius: 10,
}}
px={20}
pt={20}
pb={20}
>
{isDataAnggota.map((v, i) => {
return (
<Flex
justify={"space-between"}
align={"center"}
mb={20}
{Array(4)
.fill(null)
.map((_, i) => (
<Box
key={i}
>
<Group>
<Avatar src={""} alt="it's me" size="lg" />
<Box>
<Text c={WARNA.biruTua} fw={"bold"}>
{v.name}
</Text>
<Text c={"#5A687D"} fz={14}>
{v.email}
</Text>
</Box>
</Group>
</Flex>
);
})}
<SkeletonSingle />
</Box>
))}
</Box>
</Box>
</Box>
:
<Box pt={20}>
<Group justify='space-between'>
<Text fw={"bold"}>Total Anggota</Text>
<Text>{isLengthMember} Anggota</Text>
</Group>
<Box mb={20}>
<Box
style={{
border: `1px solid ${"#C7D6E8"}`,
borderRadius: 10,
}}
px={20}
pt={20}
>
{isDataAnggota.map((v, i) => {
return (
<Flex
justify={"space-between"}
align={"center"}
mb={20}
key={i}
>
<Group>
<Avatar src={""} alt="it's me" size="lg" />
<Box>
<Text c={WARNA.biruTua} fw={"bold"}>
{v.name}
</Text>
<Text c={"#5A687D"} fz={14}>
{v.email}
</Text>
</Box>
</Group>
</Flex>
);
})}
</Box>
</Box>
</Box>
}
</Box>
<LayoutDrawer opened={openDrawer} title={'Menu'} onClose={() => setOpenDrawer(false)}>
<DrawerDetailEvent />

View File

@@ -27,7 +27,6 @@ export default function NavbarCreateDivisionCalender() {
dateStart: false,
timeStart: false,
timeEnd: false,
linkMeet: false,
repeatEventTyper: false,
desc: false
})
@@ -94,7 +93,7 @@ export default function NavbarCreateDivisionCalender() {
return (
<Box>
<LayoutNavbarNew back="/calender" title="tambah kalender" menu />
<LayoutNavbarNew back={`/division/${param.id}/calender/`} title="tambah kalender" menu />
<Box p={20}>
<Stack>
<TextInput
@@ -179,12 +178,12 @@ export default function NavbarCreateDivisionCalender() {
error={
touched.timeEnd && (
isData.timeEnd == "" ? "Waktu Akhir Tidak Boleh Kosong" : null
)
) ||
(isData.timeStart > isData.timeEnd ? "Waktu Akhir Tidak Tepat" : null)
}
/>
</SimpleGrid>
<TextInput
required
styles={{
input: {
border: `1px solid ${"#D6D8F6"}`,
@@ -196,12 +195,6 @@ export default function NavbarCreateDivisionCalender() {
label="Link Meet"
value={isData.linkMeet}
onChange={(event) => setData({ ...isData, linkMeet: event.target.value })}
onBlur={() => setTouched({ ...touched, linkMeet: true })}
error={
touched.linkMeet && (
isData.linkMeet == "" ? "Link Meet Tidak Boleh Kosong" : null
)
}
/>
<Select
required
@@ -312,7 +305,6 @@ export default function NavbarCreateDivisionCalender() {
isData.dateStart !== " " &&
isData.timeStart !== "" &&
isData.timeEnd !== "" &&
isData.linkMeet !== "" &&
isData.repeatEventTyper !== ""
) {
setModal(true);

View File

@@ -5,12 +5,14 @@ import React, { useState } from 'react';
import { HiMenu } from 'react-icons/hi';
import DawerDivisionCalender from './dawer_division_calender';
import DateEventDivision from './date_event_division';
import { useParams } from 'next/navigation';
export default function NavbarDivisionCalender() {
const [openDrawer, setOpenDrawer] = useState(false)
const param = useParams<{ id: string }>()
return (
<div>
<LayoutNavbarNew back="" title="Divisi - kalender"
<LayoutNavbarNew back={`/division/${param.id}`} title="Divisi - kalender"
menu={
<ActionIcon variant="light" onClick={() => setOpenDrawer(true)} bg={WARNA.bgIcon} size="lg" radius="lg" aria-label="Settings">
<HiMenu size={20} color='white' />

View File

@@ -0,0 +1,40 @@
import { Box, Group, Skeleton, Stack } from '@mantine/core';
import React from 'react';
export default function SkeletonDetailEvent() {
return (
<Box style={{
border: `1px solid ${"#D8D8F1"}`,
padding: 20,
borderRadius: 10
}}>
<Stack ml={10}>
<Group mb={10} gap={30}>
<Skeleton height={30} width={30} radius="md" />
<Skeleton height={20} width={"60%"} radius="md" />
</Group>
<Group mb={10} gap={30}>
<Skeleton height={30} width={30} radius="md" />
<Skeleton height={20} width={"60%"} radius="md" />
</Group>
<Group mb={10} gap={30}>
<Skeleton height={30} width={30} radius="md" />
<Skeleton height={20} width={"60%"} radius="md" />
</Group>
<Group mb={10} gap={30}>
<Skeleton height={30} width={30} radius="md" />
<Skeleton height={20} width={"60%"} radius="md" />
</Group>
<Group mb={10} gap={30}>
<Skeleton height={30} width={30} radius="md" />
<Skeleton height={20} width={"60%"} radius="md" />
</Group>
<Group gap={30}>
<Skeleton height={30} width={30} radius="md" />
<Skeleton height={20} width={"60%"} radius="md" />
</Group>
</Stack>
</Box>
);
}

View File

@@ -23,6 +23,14 @@ export default function UpdateDivisionCalender() {
const memberValue = memberUser.get() as IFormMemberCalender[]
const [isDataCalender, setDataCalender] = useState<IDetailByIdCalender>()
const [openMember, setOpenMember] = useState(false)
const [touched, setTouched] = useState({
title: false,
dateStart: false,
timeStart: false,
timeEnd: false,
repeatEventTyper: false,
desc: false
})
const fetchGetOne = async () => {
try {
@@ -40,7 +48,6 @@ export default function UpdateDivisionCalender() {
const [value, setValue] = useState<Date | null>(null);
const router = useRouter()
async function onSubmit(val: boolean) {
try {
if (val) {
@@ -77,7 +84,7 @@ export default function UpdateDivisionCalender() {
return (
<Box>
<LayoutNavbarNew back={`/division/${param.id}/calender`} title="Edit kalender" menu />
<LayoutNavbarNew back={`/division/${param.id}/calender/${param.detail}`} title="Edit kalender" menu />
<Box p={20}>
<Stack>
<TextInput
@@ -99,6 +106,9 @@ export default function UpdateDivisionCalender() {
})
}
}
onBlur={() => setTouched({ ...touched, title: true })}
required
error={touched.title && !isDataCalender?.title ? "Nama Acara Tidak Boleh Kosong" : null}
/>
<DateInput
styles={{
@@ -122,6 +132,10 @@ export default function UpdateDivisionCalender() {
}
placeholder="Input Tanggal"
label="Tanggal"
minDate={new Date()}
onBlur={() => setTouched({ ...touched, dateStart: true })}
error={touched.dateStart && !isDataCalender?.dateStart ? "Tanggal Tidak Boleh Kosong" : null}
required
/>
<SimpleGrid
cols={{ base: 2, sm: 2, lg: 2 }}
@@ -145,6 +159,9 @@ export default function UpdateDivisionCalender() {
})
}
}
onBlur={() => setTouched({ ...touched, timeStart: true })}
error={touched.timeStart && !isDataCalender?.timeStart ? "Waktu Awal Tidak Boleh Kosong" : null}
required
/>
<TimeInput
styles={{
@@ -165,6 +182,14 @@ export default function UpdateDivisionCalender() {
})
}
}
onBlur={() => setTouched({ ...touched, timeEnd: true })}
required
error={
touched.timeEnd && (
isDataCalender?.timeEnd == "" ? "Waktu Akhir Tidak Boleh Kosong" : null
) ||
(String(isDataCalender?.timeStart) > String(isDataCalender?.timeEnd) ? "Waktu Akhir Tidak Tepat" : null)
}
/>
</SimpleGrid>
<TextInput
@@ -215,20 +240,14 @@ export default function UpdateDivisionCalender() {
})
}
}
onBlur={() => setTouched({ ...touched, repeatEventTyper: true })}
error={
touched.repeatEventTyper && (
isDataCalender?.repeatEventTyper == "" ? "Ulangi Event Tidak Boleh Kosong" : null
)
}
required
/>
<Box mt={5} onClick={() => setOpenMember(true)}>
<Group
justify="space-between"
p={10}
style={{
border: `1px solid ${"#D6D8F6"}`,
borderRadius: 10,
}}
>
<Text>Tambah Anggota</Text>
<IoIosArrowDropright size={25} />
</Group>
</Box>
<Textarea styles={{
input: {
border: `1px solid ${"#D6D8F6"}`,
@@ -236,7 +255,7 @@ export default function UpdateDivisionCalender() {
},
}}
size="md" placeholder='Deskripsi' label="Deskripsi"
// value={isDataCalender?.desc}
// value={isDataCalender?.desc}
defaultValue={isDataCalender?.desc}
onChange={
(event) => {
@@ -247,6 +266,19 @@ export default function UpdateDivisionCalender() {
}
}
/>
<Box mt={5} onClick={() => setOpenMember(true)}>
<Group
justify="space-between"
p={10}
style={{
border: `1px solid ${"#D6D8F6"}`,
borderRadius: 10,
}}
>
<Text>Tambah Anggota *</Text>
<IoIosArrowDropright size={25} />
</Group>
</Box>
<Box pt={30}>
<Group justify="space-between">
<Text c={WARNA.biruTua}>Anggota Terpilih</Text>

View File

@@ -11,6 +11,9 @@ export default function FormCreateDiscussion({ id }: { id: string }) {
const [isValModal, setValModal] = useState(false)
const router = useRouter()
const param = useParams<{ id: string }>()
const [touched, setTouched] = useState({
desc: false,
});
const [isData, setData] = useState({
desc: "",
idDivision: id
@@ -26,8 +29,9 @@ export default function FormCreateDiscussion({ id }: { id: string }) {
if (response.success) {
toast.success(response.message)
router.push(`/division/${response.data.id}/discussion/`)
router.push(`/division/${param.id}/discussion/`)
setValModal(false)
router.back()
} else {
toast.error(response.message)
}
@@ -62,6 +66,12 @@ export default function FormCreateDiscussion({ id }: { id: string }) {
}}
value={isData.desc}
onChange={(e) => setData({ ...isData, desc: e.target.value })}
onBlur={() => setTouched({ ...touched, desc: true })}
error={
touched.desc && (
isData.desc == "" ? "Form Tidak Boleh Kosong" : null
)
}
/>
</Box>
</Grid.Col>
@@ -73,7 +83,15 @@ export default function FormCreateDiscussion({ id }: { id: string }) {
size="lg"
radius={30}
fullWidth
onClick={() => setValModal(true)}
onClick={() => {
if (
isData.desc !== ""
) {
setValModal(true)
} else {
toast.error("Form Tidak Boleh Kosong");
}
}}
>
Simpan
</Button>

View File

@@ -13,6 +13,9 @@ export default function FormEditDiscussion() {
const router = useRouter()
const param = useParams<{ id: string, detail: string }>()
const [isDataOne, setDataOne] = useState("")
const [touched, setTouched] = useState({
desc: false,
});
async function fetchGetOneDiscussion() {
try {
@@ -53,7 +56,7 @@ export default function FormEditDiscussion() {
}, [])
return (
<Box>
<Box pos={"relative"} h={"89vh"}>
<Box p={20}>
<Grid gutter={0} pt={10}>
<Grid.Col span={"auto"}>
@@ -67,23 +70,37 @@ export default function FormEditDiscussion() {
input: {
border: 'none',
backgroundColor: 'transparent',
height: "50vh"
height: "60vh"
}
}}
value={isDataOne}
onChange={(e) => setDataOne(e.target.value)}
onBlur={() => setTouched({ ...touched, desc: true })}
error={
touched.desc && (
isDataOne == "" ? "Form Tidak Boleh Kosong" : null
)
}
/>
</Box>
</Grid.Col>
</Grid>
<Box mt="xl">
<Box pos={"absolute"} bottom={10} left={0} right={0} p={20}>
<Button
color="white"
bg={WARNA.biruTua}
size="lg"
radius={30}
fullWidth
onClick={() => setValModal(true)}
onClick={() => {
if (
isDataOne !== ""
) {
setValModal(true)
} else {
toast.error("Form Tidak Boleh Kosong");
}
}}
>
Simpan
</Button>

View File

@@ -8,6 +8,8 @@ import { HiMagnifyingGlass } from "react-icons/hi2";
import { funGetAllDiscussion } from "../lib/api_discussion";
import { useShallowEffect } from "@mantine/hooks";
import { IDataDiscussion } from "../lib/type_discussion";
import toast from "react-hot-toast";
import _ from "lodash";
export default function ListDiscussion({ id }: { id: string }) {
const [isData, setData] = useState<IDataDiscussion[]>([])
@@ -19,7 +21,13 @@ export default function ListDiscussion({ id }: { id: string }) {
try {
setLoading(true)
const response = await funGetAllDiscussion('?division=' + id + '&search=' + searchQuery)
setData(response.data)
if (
response.success
) {
setData(response.data)
} else {
toast.error(response.message)
}
setLoading(false)
} catch (error) {
console.log(error)
@@ -84,59 +92,65 @@ export default function ListDiscussion({ id }: { id: string }) {
</Box>
))
:
isData.map((v, i) => {
return (
<Box key={i} pl={10} pr={10}>
<Flex
justify={"space-between"}
align={"center"}
mt={20}
onClick={() => {
router.push(`/division/${param.id}/discussion/${v.id}`)
}}
>
<Group>
<Avatar alt="it's me" size="lg" />
<Box>
<Text c={WARNA.biruTua} fw={"bold"}>
{v.user_name}
_.isEmpty(isData)
?
<Box style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '50vh' }}>
<Text c="dimmed" ta={"center"} fs={"italic"}>Tidak ada Diskusi</Text>
</Box>
:
isData.map((v, i) => {
return (
<Box key={i} pl={10} pr={10}>
<Flex
justify={"space-between"}
align={"center"}
mt={20}
onClick={() => {
router.push(`/division/${param.id}/discussion/${v.id}`)
}}
>
<Group>
<Avatar alt="it's me" size="lg" />
<Box>
<Text c={WARNA.biruTua} fw={"bold"}>
{v.user_name}
</Text>
<Badge color={v.status === 1 ? "green" : "red"} size="sm">{v.status === 1 ? "BUKA" : "TUTUP"}</Badge>
</Box>
</Group>
<Text c={"grey"} fz={13}>{v.createdAt}</Text>
</Flex>
<Box mt={10}>
<Spoiler maxHeight={50} showLabel="Lebih banyak" hideLabel="Lebih sedikit">
<Text
style={{
overflowWrap: "break-word"
}}
onClick={() => {
router.push(`/division/${param.id}/discussion/${v.id}`)
}}
>
{v.desc}
</Text>
<Badge color={v.status === 1 ? "green" : "red"} size="sm">{v.status === 1 ? "BUKA" : "TUTUP"}</Badge>
</Box>
</Spoiler>
</Box>
<Group justify="space-between" mt={40} c={'#8C8C8C'}>
<Group gap={5} align="center">
<GrChatOption size={18} />
<Text fz={13}>Diskusikan</Text>
</Group >
<Group gap={5} align="center">
<Text fz={13}>{v.total_komentar} Komentar</Text>
</Group>
</Group>
<Text c={"grey"} fz={13}>{v.createdAt}</Text>
</Flex>
<Box mt={10}>
<Spoiler maxHeight={50} showLabel="Lebih banyak" hideLabel="Lebih sedikit">
<Text
style={{
overflowWrap: "break-word"
}}
onClick={() => {
router.push(`/division/${param.id}/discussion/${v.id}`)
}}
>
{v.desc}
</Text>
</Spoiler>
<Box mt={20}>
{isData.length <= 1 ? "" :
<Divider size={"xs"} />
}
</Box>
</Box>
<Group justify="space-between" mt={40} c={'#8C8C8C'}>
<Group gap={5} align="center">
<GrChatOption size={18} />
<Text fz={13}>Diskusikan</Text>
</Group >
<Group gap={5} align="center">
<Text fz={13}>{v.total_komentar} Komentar</Text>
</Group>
</Group>
<Box mt={20}>
{isData.length <= 1 ? "" :
<Divider size={"xs"} />
}
</Box>
</Box>
);
})
);
})
}
</Box>

View File

@@ -36,6 +36,10 @@ export default function CreateDivision() {
name: "",
desc: "",
});
const [touched, setTouched] = useState({
idGroup: false,
name: false,
});
async function loadData() {
const loadGroup = await funGetAllGroup('?active=true')
@@ -86,7 +90,7 @@ export default function CreateDivision() {
loadData();
}, []);
if (isChooseAdmin) return <NavbarAdminDivision data={body} onSuccess={(val) => {
if (val) {
@@ -124,7 +128,12 @@ export default function CreateDivision() {
onChange={(val) => {
onChooseGroup(val)
}}
onBlur={() => setTouched({ ...touched, idGroup: true })}
error={
touched.idGroup && (
body.idGroup == "" ? "Grup Tidak Boleh Kosong" : null
)
}
value={body.idGroup}
/>
)
@@ -137,6 +146,12 @@ export default function CreateDivision() {
radius={40}
value={body.name}
onChange={(val) => { setBody({ ...body, name: val.target.value }) }}
onBlur={() => setTouched({ ...touched, name: true })}
error={
touched.name && (
body.name == "" ? "Nama Tidak Boleh Kosong" : null
)
}
/>
<Textarea size="md" placeholder="Deskripsi" label="Deskripsi" value={body.desc} radius={10} onChange={(val) => { setBody({ ...body, desc: val.currentTarget.value }) }} />
<Box onClick={() => { onToChooseAnggota() }}>

View File

@@ -22,12 +22,9 @@ export default function EditDivision() {
desc: "",
});
function onTrue(val: boolean) {
if (val) {
toast.success("Sukses! Data tersimpan");
}
setOpenModal(false)
}
const [touched, setTouched] = useState({
name: false,
});
async function getOneData() {
@@ -88,30 +85,47 @@ export default function EditDivision() {
required
radius={40}
value={body.name}
onChange={(e) => { setBody({ ...body, name: e.target.value }) }}
onChange={(e) => {
setBody({ ...body, name: e.target.value })
setTouched({ ...touched, name: false })
}}
onBlur={() => setTouched({ ...touched, name: true })}
error={
touched.name && (
body.name == "" ? "Judul Tidak Boleh Kosong" : null
)
}
/>
<Textarea placeholder="Deskripsi" label="Deskripsi" size="md" radius={10}
value={body.desc}
onChange={(e) => { setBody({ ...body, desc: e.currentTarget.value }) }}
styles={{
input: {
height: "40vh"
height: "40vh"
}
}}
}}
/>
</Stack>
<Box pos={"absolute"} bottom={10} left={0} right={0} p={20}>
<Button
color="white"
bg={WARNA.biruTua}
size="lg"
radius={30}
fullWidth
onClick={() => { setOpenModal(true) }}
>
Simpan
</Button>
</Box>
<Box pos={"absolute"} bottom={10} left={0} right={0} p={20}>
<Button
color="white"
bg={WARNA.biruTua}
size="lg"
radius={30}
fullWidth
onClick={() => {
if (
body.name !== ""
) {
setOpenModal(true)
} else {
toast.error("Judul Tidak Boleh Kosong")
}
}}
>
Simpan
</Button>
</Box>
</Box>
<LayoutModal opened={openModal} onClose={() => setOpenModal(false)} description='Apakah Anda yakin ingin edit data'
onYes={(val) => {

View File

@@ -7,12 +7,14 @@ import EchartPaiReport from './echart_pai_report';
import EchartBarReport from './echart_bar_report';
import EventReport from './event_report';
import DiscussionReport from './discussion_report';
import { useParams } from 'next/navigation';
export default function ReportDivisionId() {
const [value, setValue] = useState<Date | null>(null);
const param = useParams<{ id: string }>()
return (
<Box>
<LayoutNavbarNew back="/division/1" title="Report Divisi" menu />
<LayoutNavbarNew back={`/division/${param.id}`} title="Report Divisi" menu />
<Box p={20}>
<Stack>
<DateInput

View File

@@ -18,6 +18,9 @@ import toast from "react-hot-toast";
export default function DrawerGroup({ onSuccess, }: { onSuccess: (val: boolean) => void; }) {
const [openDrawerGroup, setOpenDrawerGroup] = useState(false);
const [namaGroup, setNamaGroup] = useState("");
const [touched, setTouched] = useState({
name: false,
});
async function createData() {
@@ -50,7 +53,7 @@ export default function DrawerGroup({ onSuccess, }: { onSuccess: (val: boolean)
<IoAddCircle size={30} color={WARNA.biruTua} />
</Box>
<Box>
<Text c={WARNA.biruTua}>Tambah Group</Text>
<Text c={WARNA.biruTua}>Tambah Grup</Text>
</Box>
</Flex>
</SimpleGrid>
@@ -71,8 +74,15 @@ export default function DrawerGroup({ onSuccess, }: { onSuccess: (val: boolean)
}}
size="lg"
radius={10}
label="Grup"
required
placeholder="Grup"
onChange={(e) => setNamaGroup(e.target.value)}
onChange={(e) => {
setNamaGroup(e.target.value)
setTouched({ ...touched, name: false })
}}
error={touched.name ? "Error! harus memasukkan grup" : ""}
onBlur={() => setTouched({ ...touched, name: true })}
/>
<Box mt={"xl"}>
<Button

View File

@@ -24,6 +24,9 @@ export default function EditDrawerGroup({ onUpdated, id, isActive, }: { onUpdate
const [isModal, setModal] = useState(false);
const [name, setName] = useState("");
const [loading, setLoading] = useState(false);
const [touched, setTouched] = useState({
name: false,
});
async function getOneGroup() {
try {
@@ -135,9 +138,18 @@ export default function EditDrawerGroup({ onUpdated, id, isActive, }: { onUpdate
}}
size="lg"
value={name}
onChange={(e) => setName(e.target.value)}
onChange={(e) => {
setName(e.target.value)
setTouched({ ...touched, name: false })
}}
onBlur={() => setTouched({ ...touched, name: true })}
error={touched.name ? "Error! harus memasukkan grup" : ""}
radius={10}
placeholder="Grup"
label="Grup"
required
/>
<Box mt={"xl"}>
<Button

View File

@@ -20,6 +20,10 @@ export default function DrawerDetailPosition({ onUpdated, id, isActive }: {
idGroup: ""
})
const [listGroup, setListGorup] = useState<IDataPosition[]>([])
const [touched, setTouched] = useState({
name: false,
idGroup: false
});
function onCLose() {
onUpdated(true)
@@ -153,7 +157,10 @@ export default function DrawerDetailPosition({ onUpdated, id, isActive }: {
}
value={String(data.idGroup)}
mb={5}
onChange={(val) => setData({ ...data, idGroup: val })}
onChange={(val) => {
setData({ ...data, idGroup: val })
setTouched({ ...touched, idGroup: false })
}}
withAsterisk
styles={{
input: {
@@ -162,6 +169,12 @@ export default function DrawerDetailPosition({ onUpdated, id, isActive }: {
borderColor: WARNA.biruTua,
},
}}
error={
touched.idGroup && (
data.idGroup == "" ? "Grup Tidak Boleh Kosong" : null
)
}
onBlur={() => setTouched({ ...touched, idGroup: true })}
/>
<TextInput
label="Jabatan"
@@ -172,10 +185,20 @@ export default function DrawerDetailPosition({ onUpdated, id, isActive }: {
borderColor: WARNA.biruTua,
},
}}
required
my={15}
size="md"
value={String(data.name)}
onChange={(e) => setData({ ...data, name: e.target.value })}
onChange={(e) => {
setData({ ...data, name: e.target.value })
setTouched({ ...touched, name: false })
}}
onBlur={() => setTouched({ ...touched, name: true })}
error={
touched.name && (
data.name == "" ? "Nama Jabatan Tidak Boleh Kosong" : null
)
}
radius={10}
placeholder="Nama Jabatan"
/>

View File

@@ -14,6 +14,10 @@ export default function DrawerListPosition({ onCreated }: { onCreated: (val: boo
const [openDrawerGroup, setOpenDrawerGroup] = useState(false)
const router = useRouter()
const [listGroup, setListGorup] = useState<IDataGroup[]>([])
const [touched, setTouched] = useState({
name: false,
idGroup: false
});
const [listData, setListData] = useState({
name: "",
@@ -101,10 +105,13 @@ export default function DrawerListPosition({ onCreated }: { onCreated: (val: boo
radius={10}
mb={5}
withAsterisk
onChange={(val: any) => setListData({
...listData,
idGroup: val
})}
onChange={(val: any) => {
setListData({
...listData,
idGroup: val
})
setTouched({ ...touched, idGroup: false })
}}
styles={{
input: {
color: WARNA.biruTua,
@@ -112,6 +119,13 @@ export default function DrawerListPosition({ onCreated }: { onCreated: (val: boo
borderColor: WARNA.biruTua,
},
}}
error={
touched.idGroup && (
listData.idGroup == "" ? "Grup Tidak Boleh Kosong" : null
)
}
onFocus={() => setTouched({ ...touched, idGroup: true })}
onBlur={() => setTouched({ ...touched, idGroup: true })}
/>
<TextInput
label="Jabatan"
@@ -124,12 +138,23 @@ export default function DrawerListPosition({ onCreated }: { onCreated: (val: boo
}}
my={15}
size="md"
onChange={(event: any) => setListData({
...listData,
name: event.target.value
})}
onChange={(event: any) => {
setListData({
...listData,
name: event.target.value
})
setTouched({ ...touched, name: false })
}}
radius={10}
placeholder="Nama Jabatan"
error={
touched.name && (
listData.name == "" ? "Nama Jabatan Tidak Boleh Kosong" : null
)
}
onFocus={() => setTouched({ ...touched, name: true })}
onBlur={() => setTouched({ ...touched, name: true })}
required
/>
<Box mt={'xl'}>
<Button

View File

@@ -43,7 +43,11 @@ export default function CreateProject() {
const [body, setBody] = useState<any>({
idGroup: "",
title: "",
desc: "",
});
const [touched, setTouched] = useState({
title: false,
idGroup: false,
desc: false
});
function deleteFile(index: number) {
@@ -138,9 +142,16 @@ export default function CreateProject() {
}))}
onChange={(val) => {
onChooseGroup(val)
setTouched({ ...touched, idGroup: false })
}}
value={(body.idGroup=="")?null:body.idGroup}
value={(body.idGroup == "") ? null : body.idGroup}
onBlur={() => setTouched({ ...touched, idGroup: true })}
error={
touched.idGroup && (
body.idGroup == "" ? "Grup Tidak Boleh Kosong" : null
)
}
/>
)
}
@@ -157,6 +168,12 @@ export default function CreateProject() {
size="md"
value={body.title}
onChange={(e) => setBody({ ...body, title: e.target.value })}
onBlur={() => setTouched({ ...touched, title: true })}
error={
touched.title && (
body.title == "" ? "Proyek Tidak Boleh Kosong" : null
)
}
/>
<Box onClick={() => { setOpenTugas(true) }}>
<Group

View File

@@ -10,6 +10,7 @@ import {
SimpleGrid,
Stack,
Text,
TextInput,
} from "@mantine/core";
import React, { useState } from "react";
import { DatePicker } from "@mantine/dates";
@@ -27,6 +28,9 @@ export default function AddDetailTask() {
const [title, setTitle] = useState("")
const [openModal, setOpenModal] = useState(false)
const param = useParams<{ id: string, detail: string }>()
const [touched, setTouched] = useState({
title: false,
});
function onVerification() {
if (value[0] == null || value[1] == null)
@@ -106,17 +110,25 @@ export default function AddDetailTask() {
</Box>
</SimpleGrid>
<Stack pt={15}>
<Input
<TextInput
styles={{
input: {
border: `1px solid ${"#D6D8F6"}`,
borderRadius: 10,
},
}}
label="Tahapan"
placeholder="Input Nama Tahapan"
size="md"
required
value={title}
onChange={(e) => setTitle(e.target.value)}
onChange={(e) => {
setTitle(e.target.value)
setTouched({ ...touched, title: false })
}
}
onBlur={() => setTouched({ ...touched, title: true })}
error={touched.title ? "Tahapan wajib diisi" : undefined}
/>
</Stack>
<Box mt={"xl"}>

View File

@@ -121,26 +121,13 @@ export default function AddMemberDetailTask() {
menu
/>
<Box p={20}>
{/* <TextInput
styles={{
input: {
color: WARNA.biruTua,
borderRadius: WARNA.biruTua,
borderColor: WARNA.biruTua,
},
}}
size="md"
radius={30}
leftSection={<HiMagnifyingGlass size={20} />}
placeholder="Pencarian"
/> */}
<Group justify="space-between" mt={20} onClick={handleSelectAll}>
<Text c={WARNA.biruTua} fw={"bold"}>
Pilih Semua Anggota
</Text>
{selectAll ? <FaCheck style={{ marginRight: 10 }} /> : ""}
</Group>
{/* <Box mt={15}>
<Box mt={15}>
{isData.map((v, i) => {
const isSelected = selectedFiles.some((i: any) => i?.idUser == v.idUser);
const found = isDataMember.some((i: any) => i.idUser == v.idUser)
@@ -175,7 +162,7 @@ export default function AddMemberDetailTask() {
</Box>
);
})}
</Box> */}
</Box>
<Box mt={"xl"}>
<Button
c={"white"}

View File

@@ -18,6 +18,9 @@ export default function CancelTask() {
const [alasan, setAlasan] = useState("")
const [openModal, setOpenModal] = useState(false)
const param = useParams<{ id: string, detail: string }>()
const [touched, setTouched] = useState({
reason: false,
});
function onVerification() {
if (alasan == "")
@@ -44,7 +47,7 @@ export default function CancelTask() {
return (
<Box>
<Box pos={"relative"} h={"100vh"}>
<LayoutNavbarNew back="" title={"Pembatalan Tugas"} menu />
<Box p={20}>
<Stack pt={15}>
@@ -56,10 +59,15 @@ export default function CancelTask() {
}}
value={alasan}
size="md" placeholder='Contoh : Tugas tidak sesuai' label="Alasan Pembatalan"
onChange={(event) => setAlasan(event.target.value)}
onChange={(event) => {
setAlasan(event.target.value)
setTouched({ ...touched, reason: false })
}}
error={touched.reason ? "Error! harus memasukkan alasan pembatalan tugas" : ""}
onBlur={() => setTouched({ ...touched, reason: true })}
/>
</Stack>
<Box mt={"xl"}>
<Box pos={"absolute"} bottom={10} left={0} right={0} p={20}>
<Button
c={"white"}
bg={WARNA.biruTua}

View File

@@ -10,10 +10,11 @@ import {
SimpleGrid,
Stack,
Text,
TextInput,
} from "@mantine/core";
import React, { useState } from "react";
import { DatePicker } from "@mantine/dates";
import { useRouter } from "next/navigation";
import { useParams, useRouter } from "next/navigation";
import toast from "react-hot-toast";
import { IFormDateTask } from "../lib/type_task";
import moment from "moment";
@@ -22,7 +23,11 @@ import moment from "moment";
export default function ViewDateEndTask({ onClose }: { onClose: (val: IFormDateTask) => void }) {
const [value, setValue] = useState<[Date | null, Date | null]>([null, null]);
const router = useRouter()
const param = useParams<{ id: string }>()
const [title, setTitle] = useState("")
const [touched, setTouched] = useState({
title: false,
});
function onSubmit() {
if (value[0] == null || value[1] == null)
@@ -43,7 +48,7 @@ export default function ViewDateEndTask({ onClose }: { onClose: (val: IFormDateT
return (
<Box>
<LayoutNavbarNew back="" title={"Tanggal Tugas"} menu />
<LayoutNavbarNew back={`/division/${param.id}/task/create`} title={"Tanggal Tugas"} menu />
<Box p={20}>
<Group
justify="center"
@@ -85,7 +90,7 @@ export default function ViewDateEndTask({ onClose }: { onClose: (val: IFormDateT
</Box>
</SimpleGrid>
<Stack pt={15}>
<Input
<TextInput
styles={{
input: {
border: `1px solid ${"#D6D8F6"}`,
@@ -93,9 +98,16 @@ export default function ViewDateEndTask({ onClose }: { onClose: (val: IFormDateT
},
}}
placeholder="Input Nama Tahapan"
label="Judul Tugas"
required
size="md"
value={title}
onChange={(e) => setTitle(e.target.value)}
onChange={(e) => {
setTitle(e.target.value)
setTouched({ ...touched, title: false })
}}
onBlur={() => setTouched({ ...touched, title: true })}
error={touched.title && title == "" ? "Judul Tugas Tidak Boleh Kosong" : null}
/>
</Stack>
<Box mt={"xl"}>

View File

@@ -1,6 +1,6 @@
"use client";
import { LayoutDrawer, LayoutNavbarNew, WARNA } from "@/module/_global";
import { Avatar, Box, Button, Center, Flex, Group, Input, SimpleGrid, Stack, Text } from "@mantine/core";
import { Avatar, Box, Button, Center, Flex, Group, Input, SimpleGrid, Stack, Text, TextInput } from "@mantine/core";
import { useParams, useRouter } from "next/navigation";
import React, { useRef, useState } from "react";
import { IoIosArrowDropright } from "react-icons/io";
@@ -37,6 +37,11 @@ export default function CreateTask() {
const [indexDelFile, setIndexDelFile] = useState<number>(0)
const [indexDelTask, setIndexDelTask] = useState<number>(0)
const [title, setTitle] = useState("")
const [touched, setTouched] = useState({
title: false,
task: false,
member: false
});
function deleteFile(index: number) {
setListFile([...listFile.filter((val, i) => i !== index)])
@@ -52,7 +57,14 @@ export default function CreateTask() {
async function onSubmit() {
try {
const response = await funCreateTask({ idDivision: param.id, title, task: dataTask, file: fileForm, member: memberValue })
const response = await funCreateTask(
{
idDivision: param.id,
title,
task: dataTask,
file: fileForm,
member: memberValue
})
if (response.success) {
toast.success(response.message)
@@ -81,20 +93,31 @@ export default function CreateTask() {
return (
<Box>
<LayoutNavbarNew back="" title="tambah tugas" menu />
<LayoutNavbarNew back={`/division/${param.id}/task/`} title="tambah tugas" menu />
<Box p={20}>
<Stack>
<Input
<TextInput
styles={{
input: {
border: `1px solid ${"#D6D8F6"}`,
borderRadius: 10,
},
}}
placeholder="Nama Proyek"
placeholder="Nama Tugas"
size="md"
label="Judul Tugas"
value={title}
onChange={(e) => setTitle(e.target.value)}
onChange={(e) => {
setTitle(e.target.value)
setTouched({ ...touched, title: false })
}}
onBlur={() => setTouched({ ...touched, title: true })}
required
error={
touched.title && (
title == "" ? "Nama Tidak Boleh Kosong" : null
)
}
/>
<Box onClick={() => { setOpenTugas(true) }}>
<Group
@@ -227,7 +250,20 @@ export default function CreateTask() {
<Box mt="xl">
<Button color="white" bg={WARNA.biruTua} size="lg" radius={30} fullWidth onClick={() => setOpenModal(true)}>
<Button
color="white"
bg={WARNA.biruTua}
size="lg" radius={30}
fullWidth
onClick={() => {
if (
title !== ""
) {
setOpenModal(true)
} else {
toast.error("Semua form harus diisi")
}
}}>
Simpan
</Button>
</Box>

View File

@@ -6,6 +6,7 @@ import {
Input,
Stack,
Textarea,
TextInput,
} from "@mantine/core";
import React, { useState } from "react";
import { useParams, useRouter } from "next/navigation";
@@ -20,6 +21,9 @@ export default function EditTask() {
const [title, setTitle] = useState("")
const [openModal, setOpenModal] = useState(false)
const param = useParams<{ id: string, detail: string }>()
const [touched, setTouched] = useState({
title: false,
});
function onVerification() {
if (title == "")
@@ -65,11 +69,11 @@ export default function EditTask() {
return (
<Box>
<Box pos={"relative"} h={"100vh"}>
<LayoutNavbarNew back="" title={"Edit Judul Tugas"} menu />
<Box p={20}>
<Stack pt={15}>
<Input
<TextInput
styles={{
input: {
border: `1px solid ${"#D6D8F6"}`,
@@ -77,12 +81,22 @@ export default function EditTask() {
},
}}
placeholder="Tugas"
label="Judul Tugas"
size="md"
value={title}
onChange={(e) => { setTitle(e.target.value) }}
onChange={(e) => {
setTitle(e.target.value)
setTouched({ ...touched, title: false })
}}
error={
touched.title && (
title == "" ? "Error! harus memasukkan judul tugas" : null
)
}
onBlur={() => setTouched({ ...touched, title: true })}
/>
</Stack>
<Box mt={"xl"}>
<Box pos={"absolute"} bottom={10} left={0} right={0} p={20}>
<Button
c={"white"}
bg={WARNA.biruTua}

View File

@@ -39,7 +39,7 @@ export default function NavbarDetailDivisionTask() {
return (
<>
<LayoutNavbarNew back="" title={name} menu={
<LayoutNavbarNew back={`/division/${param.id}/task/`} title={name} menu={
<ActionIcon
variant="light"
bg={WARNA.bgIcon}

View File

@@ -165,6 +165,7 @@ export default function CreateMember() {
}
onChange={(val: any) => {
changeGrup(val);
setTouched({ ...touched, idGroup: false })
}}
onBlur={() => setTouched({ ...touched, idGroup: true })}
error={
@@ -196,11 +197,13 @@ export default function CreateMember() {
}))
: []
}
onChange={(val: any) =>
onChange={(val: any) => {
setListData({
...listData,
idPosition: val,
})
setTouched({ ...touched, idPosition: false })
}
}
value={listData.idPosition == "" ? null : listData.idPosition}
onBlur={() => setTouched({ ...touched, idPosition: true })}
@@ -233,11 +236,13 @@ export default function CreateMember() {
}))
: []
}
onChange={(val: any) =>
onChange={(val: any) => {
setListData({
...listData,
idUserRole: val,
})
setTouched({ ...touched, idUserRole: false })
}
}
onBlur={() => setTouched({ ...touched, idUserRole: true })}
error={
@@ -263,7 +268,7 @@ export default function CreateMember() {
}}
onChange={(event: any) => {
setListData({ ...listData, nik: event.target.value });
setTouched({ ...touched, nik: true });
setTouched({ ...touched, nik: false });
}}
onBlur={() => setTouched({ ...touched, nik: true })}
error={
@@ -288,11 +293,13 @@ export default function CreateMember() {
borderColor: WARNA.biruTua,
},
}}
onChange={(event: any) =>
onChange={(event: any) => {
setListData({
...listData,
name: event.target.value,
})
setTouched({ ...touched, name: false })
}
}
onBlur={() => setTouched({ ...touched, name: true })}
error={
@@ -316,11 +323,13 @@ export default function CreateMember() {
borderColor: WARNA.biruTua,
},
}}
onChange={(event: any) =>
onChange={(event: any) => {
setListData({
...listData,
email: event.target.value,
})
setTouched({ ...touched, email: false })
}
}
onBlur={() => setTouched({ ...touched, email: true })}
error={
@@ -345,11 +354,13 @@ export default function CreateMember() {
borderColor: WARNA.biruTua,
},
}}
onChange={(event: any) =>
onChange={(event: any) => {
setListData({
...listData,
phone: event.target.value,
})
setTouched({ ...touched, phone: false })
}
}
onBlur={() => setTouched({ ...touched, phone: true })}
error={
@@ -378,11 +389,13 @@ export default function CreateMember() {
{ value: "M", label: "Laki-laki" },
{ value: "F", label: "Perempuan" },
]}
onChange={(val: any) =>
onChange={(val: any) => {
setListData({
...listData,
gender: val,
})
setTouched({ ...touched, gender: false })
}
}
onBlur={() => setTouched({ ...touched, gender: true })}
error={

View File

@@ -29,7 +29,7 @@ export default function EditMember({ id }: { id: string }) {
idGroup: false,
idPosition: false,
idUserRole: false
});
});
const [data, setData] = useState<IEditDataMember>({
id: "",
nik: "",
@@ -121,7 +121,7 @@ export default function EditMember({ id }: { id: string }) {
idPosition: data.idPosition,
idUserRole: data.idUserRole
})
toast.success(res.message)
router.push(`/member?active=true`)
}
@@ -165,13 +165,14 @@ export default function EditMember({ id }: { id: string }) {
}
onChange={(val: any) => {
changeGrup(val)
setTouched({ ...touched, idGroup: false })
}}
value={data?.idGroup}
onBlur={() => setTouched({ ...touched, idGroup: true })}
error={
touched.idGroup && (
data.idGroup == "" ? "Grup Tidak Boleh Kosong" : null
)
touched.idGroup && (
data.idGroup == "" ? "Grup Tidak Boleh Kosong" : null
)
}
/>
<Select
@@ -191,13 +192,16 @@ export default function EditMember({ id }: { id: string }) {
}))
: []
}
onChange={(val: any) => setData({ ...data, idPosition: val })}
onChange={(val: any) => {
setData({ ...data, idPosition: val })
setTouched({ ...touched, idPosition: false })
}}
value={(data?.idPosition == "") ? null : data.idPosition}
onBlur={() => setTouched({ ...touched, idPosition: true })}
error={
touched.idPosition && (
data.idPosition == "" ? "Jabatan Tidak Boleh Kosong" : null
)
touched.idPosition && (
data.idPosition == "" ? "Jabatan Tidak Boleh Kosong" : null
)
}
/>
<Select
@@ -217,13 +221,16 @@ export default function EditMember({ id }: { id: string }) {
}))
: []
}
onChange={(val: any) => setData({ ...data, idUserRole: val })}
onChange={(val: any) => {
setData({ ...data, idUserRole: val })
setTouched({ ...touched, idUserRole: false })
}}
value={data?.idUserRole}
onBlur={() => setTouched({ ...touched, idUserRole: true })}
error={
touched.idUserRole && (
data.idUserRole == "" ? "Role Tidak Boleh Kosong" : null
)
touched.idUserRole && (
data.idUserRole == "" ? "Role Tidak Boleh Kosong" : null
)
}
/>
<TextInput
@@ -235,14 +242,17 @@ export default function EditMember({ id }: { id: string }) {
borderColor: WARNA.biruTua,
},
}}
onChange={(e) => setData({ ...data, nik: e.target.value })}
onChange={(e) => {
setData({ ...data, nik: e.target.value })
setTouched({ ...touched, nik: false })
}}
value={data.nik}
onBlur={() => setTouched({ ...touched, nik: true })}
error={
touched.nik && (
data.nik == "" ? "NIK Tidak Boleh Kosong" :
data.nik.length < 16 ? "NIK Harus 16 Karakter" : null
)
touched.nik && (
data.nik == "" ? "NIK Tidak Boleh Kosong" :
data.nik.length < 16 ? "NIK Harus 16 Karakter" : null
)
}
/>
<TextInput
@@ -254,13 +264,16 @@ export default function EditMember({ id }: { id: string }) {
borderColor: WARNA.biruTua,
},
}}
onChange={(e) => setData({ ...data, name: e.target.value })}
onChange={(e) => {
setData({ ...data, name: e.target.value })
setTouched({ ...touched, name: false })
}}
value={data.name}
onBlur={() => setTouched({ ...touched, name: true })}
error={
touched.name && (
data.name == "" ? "Nama Tidak Boleh Kosong" : null
)
touched.name && (
data.name == "" ? "Nama Tidak Boleh Kosong" : null
)
}
/>
<TextInput
@@ -272,14 +285,17 @@ export default function EditMember({ id }: { id: string }) {
borderColor: WARNA.biruTua,
},
}}
onChange={(e) => setData({ ...data, email: e.target.value })}
onChange={(e) => {
setData({ ...data, email: e.target.value })
setTouched({ ...touched, email: false })
}}
value={data.email}
onBlur={() => setTouched({ ...touched, email: true })}
error={
touched.email && (
data.email == "" ? "Email Tidak Boleh Kosong" :
!/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(data.email) ? "Email tidak valid" : null
)
touched.email && (
data.email == "" ? "Email Tidak Boleh Kosong" :
!/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(data.email) ? "Email tidak valid" : null
)
}
/>
<TextInput
@@ -291,14 +307,17 @@ export default function EditMember({ id }: { id: string }) {
borderColor: WARNA.biruTua,
},
}}
onChange={(e) => setData({ ...data, phone: e.target.value })}
onChange={(e) => {
setData({ ...data, phone: e.target.value })
setTouched({ ...touched, phone: false })
}}
value={data.phone}
onBlur={() => setTouched({ ...touched, phone: true })}
error={
touched.phone && (
data.phone == "" ? "Nomor Telepon Tidak Boleh Kosong" :
data.phone.length < 10 ? "Nomor Telepon harus 10 digit" : null
)
touched.phone && (
data.phone == "" ? "Nomor Telepon Tidak Boleh Kosong" :
data.phone.length < 10 ? "Nomor Telepon harus 10 digit" : null
)
}
/>
<Select
@@ -322,42 +341,45 @@ export default function EditMember({ id }: { id: string }) {
}
]
}
onChange={(val: any) => setData({ ...data, gender: val })}
onChange={(val: any) => {
setData({ ...data, gender: val })
setTouched({ ...touched, gender: false })
}}
value={data.gender}
onBlur={() => setTouched({ ...touched, gender: true })}
error={
touched.gender && (
data.gender == "" ? "Gender Tidak Boleh Kosong" : null
)
touched.gender && (
data.gender == "" ? "Gender Tidak Boleh Kosong" : null
)
}
/>
</Stack>
<Box mt={30} mx={20} pb={20}>
<Button
c={"white"}
bg={WARNA.biruTua}
size="md"
radius={30}
fullWidth
onClick={() => {
if (
data.nik !== "" &&
data.name !== "" &&
data.email !== "" &&
data.phone !== "" &&
data.gender !== "" &&
data.idGroup !== "" &&
data.idPosition !== "" &&
data.idUserRole !== ""
) {
setModal(true);
} else {
toast.error("Mohon lengkapi semua form");
}
}}
>
Simpan
</Button>
<Button
c={"white"}
bg={WARNA.biruTua}
size="md"
radius={30}
fullWidth
onClick={() => {
if (
data.nik !== "" &&
data.name !== "" &&
data.email !== "" &&
data.phone !== "" &&
data.gender !== "" &&
data.idGroup !== "" &&
data.idPosition !== "" &&
data.idUserRole !== ""
) {
setModal(true);
} else {
toast.error("Mohon lengkapi semua form");
}
}}
>
Simpan
</Button>
</Box>
<LayoutModal opened={isModal} onClose={() => setModal(false)}
description="Apakah Anda yakin ingin mengubah data?"