diff --git a/src/app/(application)/profile/edit/page.tsx b/src/app/(application)/profile/edit/page.tsx
index 6ca9661..da3e588 100644
--- a/src/app/(application)/profile/edit/page.tsx
+++ b/src/app/(application)/profile/edit/page.tsx
@@ -1,8 +1,8 @@
-import { ViewEditProfile } from "@/module/user"
+import { EditProfile } from "@/module/user"
function Page() {
return (
-
+
)
}
diff --git a/src/app/(application)/profile/page.tsx b/src/app/(application)/profile/page.tsx
index 2c27402..b747f4e 100644
--- a/src/app/(application)/profile/page.tsx
+++ b/src/app/(application)/profile/page.tsx
@@ -1,8 +1,8 @@
-import { ViewProfile } from "@/module/user";
+import { Profile } from "@/module/user";
function Page() {
return (
-
+
)
}
diff --git a/src/app/api/user/profile/[id]/route.ts b/src/app/api/user/profile/[id]/route.ts
new file mode 100644
index 0000000..1dc7be6
--- /dev/null
+++ b/src/app/api/user/profile/[id]/route.ts
@@ -0,0 +1,59 @@
+import { prisma } from "@/module/_global";
+import { funGetUserByCookies } from "@/module/auth";
+import { NextResponse } from "next/server";
+
+
+// UPDATE PROFILE BY COOKIES
+export async function PUT(request: Request, context: { params: { id: string } }) {
+ try {
+ const user = await funGetUserByCookies()
+ if (user.id == undefined) {
+ return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
+ }
+ const { id } = context.params;
+ const data = await request.json();
+ const cek = await prisma.user.count({
+ where: {
+ id: id,
+ nik: data.nik,
+ email: data.email,
+ phone: data.phone
+ }
+ })
+ if (cek == 0) {
+ return NextResponse.json(
+ {
+ success: false,
+ message: "Gagal mendapatkan profile, data tidak ditemukan",
+ },
+ { status: 404 }
+ );
+ }
+
+ const result = await prisma.user.update({
+ where: {
+ id: id,
+ },
+ data: {
+ nik: data.nik,
+ name: data.name,
+ email: data.email,
+ phone: data.phone,
+ gender: data.gender,
+ },
+ });
+
+ return NextResponse.json(
+ {
+ success: true,
+ message: "Berhasil mendapatkan profile",
+ result,
+ },
+ { status: 200 }
+ );
+
+ } catch (error) {
+ console.error(error);
+ return NextResponse.json({ success: false, message: "Gagal mendapatkan anggota, coba lagi nanti", reason: (error as Error).message, }, { status: 500 });
+ }
+}
\ No newline at end of file
diff --git a/src/app/api/user/profile/route.ts b/src/app/api/user/profile/route.ts
new file mode 100644
index 0000000..63f8172
--- /dev/null
+++ b/src/app/api/user/profile/route.ts
@@ -0,0 +1,82 @@
+import { prisma } from "@/module/_global";
+import { funGetUserByCookies } from "@/module/auth";
+import _ from "lodash";
+import { NextResponse } from "next/server";
+
+
+// GET PROFILE BY COOKIES
+export async function GET(request: Request) {
+ try {
+ const user = await funGetUserByCookies()
+ if (user.id == undefined) {
+ return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
+ }
+ const data = await prisma.user.findUnique({
+ where: {
+ id: user.id
+ },
+ select: {
+ id: true,
+ name: true,
+ email: true,
+ phone: true,
+ nik: true,
+ gender: true,
+ idGroup: true,
+ idPosition: true,
+ Group: {
+ select: {
+ name: true
+ }
+ },
+ Position: {
+ select: {
+ name: true
+ }
+ }
+ }
+ })
+ const { ...userData } = data;
+ const group = data?.Group.name
+ const position = data?.Position.name
+
+ const result = { ...userData, group, position };
+
+ const omitData = _.omit(result, ["Group", "Position",])
+
+ return NextResponse.json({ success: true, data: omitData });
+ } catch (error) {
+ return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
+ }
+
+}
+
+// UPDATE PROFILE BY COOKIES
+export async function PUT(request: Request) {
+ try {
+ const user = await funGetUserByCookies()
+ if (user.id == undefined) {
+ return NextResponse.json({ success: false, message: "Anda harus login untuk mengakses ini" }, { status: 401 });
+ }
+
+ const body = await request.json();
+ const { name, email, phone, nik, gender } = body;
+ const data = await prisma.user.update({
+ where: {
+ id: user.id
+ },
+ data: {
+ name: name,
+ email: email,
+ phone: phone,
+ nik: nik,
+ gender: gender
+ }
+ })
+
+ return NextResponse.json({ success: true, message: "Berhasil ubah profile", data: data });
+ } catch (error) {
+ return NextResponse.json({ success: false, message: "Gagal ubah profile" }, { status: 401 });
+ }
+}
+
diff --git a/src/module/_global/layout/layout_modal.tsx b/src/module/_global/layout/layout_modal.tsx
index 7d1e779..93f0e44 100644
--- a/src/module/_global/layout/layout_modal.tsx
+++ b/src/module/_global/layout/layout_modal.tsx
@@ -19,7 +19,7 @@ export default function LayoutModal({ opened, onClose, description, onYes }: { o
{description}
-
+
diff --git a/src/module/discussion/ui/detail_discussion.tsx b/src/module/discussion/ui/detail_discussion.tsx
index 1364b06..68658be 100644
--- a/src/module/discussion/ui/detail_discussion.tsx
+++ b/src/module/discussion/ui/detail_discussion.tsx
@@ -93,47 +93,90 @@ export default function DetailDiscussion({ id, idDivision }: { id: string, idDiv
)) :
-
-
- {isData?.username ?
-
-
-
-
- {isData?.username}
-
- {isData?.status === 1 ? "BUKA" : "TUTUP"}
-
- : ""
- }
- {isData?.createdAt}
-
-
-
-
+ {isData?.totalComments == 0 ?
+
+
- {isData?.desc}
-
-
-
-
- {isData?.totalComments ?
-
- {isData?.totalComments} Komentar
- : ""}
+ {isData?.username ?
+
+
+
+
+ {isData?.username}
+
+ {isData?.status === 1 ? "BUKA" : "TUTUP"}
+
+ : ""
+ }
+ {isData?.createdAt}
+
+
+
+
+ {isData?.desc}
+
+
+
+
+ {isData?.totalComments ?
+
+ {isData?.totalComments} Komentar
+ : ""}
-
-
+
+ :
+
+
+ {isData?.username ?
+
+
+
+
+ {isData?.username}
+
+ {isData?.status === 1 ? "BUKA" : "TUTUP"}
+
+ : ""
+ }
+ {isData?.createdAt}
+
+
+
+
+ {isData?.desc}
+
+
+
+
+ {isData?.totalComments ?
+
+ {isData?.totalComments} Komentar
+ : ""}
+
+
+
+ }
+ >
}
-
+
{isLoad ?
Array(2)
.fill(0)
@@ -167,7 +210,7 @@ export default function DetailDiscussion({ id, idDivision }: { id: string, idDiv
)) :
isData?.DivisionDisscussionComment.map((v, i) => {
return (
-
+
{
fetchData()
}, [param.id])
-
+ const isMobile = useMediaQuery('(max-width: 399px)');
return (
@@ -69,7 +69,7 @@ export default function FeatureDetailDivision() {
Tugas
{feature?.tugas} Tugas
-
+ {!isMobile && }
@@ -94,7 +94,7 @@ export default function FeatureDetailDivision() {
Dokumen
{feature?.dokumen} File
-
+ {!isMobile && }
@@ -119,7 +119,7 @@ export default function FeatureDetailDivision() {
Diskusi
{feature?.diskusi} Diskusi
-
+ {!isMobile && }
@@ -144,7 +144,7 @@ export default function FeatureDetailDivision() {
Kalender
{feature?.kalender} Acara
-
+ {!isMobile && }
diff --git a/src/module/document/ui/navbar_document_division.tsx b/src/module/document/ui/navbar_document_division.tsx
index 6e1365d..7d8f917 100644
--- a/src/module/document/ui/navbar_document_division.tsx
+++ b/src/module/document/ui/navbar_document_division.tsx
@@ -238,14 +238,14 @@ export default function NavbarDocumentDivision() {
zIndex: 999,
}}>
-
+
0) ? 'white' : 'grey'} />
- 0) ? 'white' : 'grey'}>Unduh
+ 0) ? 'white' : 'grey'}>Unduh
setIsDelete(true)} justify={'center'} align={'center'} direction={'column'}>
0 && !shareSelected) ? 'white' : 'grey'} />
- 0 && !shareSelected) ? 'white' : 'grey'}>Hapus
+ 0 && !shareSelected) ? 'white' : 'grey'}>Hapus
{
if (selectedFiles.length == 1) {
@@ -253,15 +253,15 @@ export default function NavbarDocumentDivision() {
}
}} justify={'center'} align={'center'} direction={'column'}>
- Ganti Nama
+ Ganti Nama
setShare(true)} justify={'center'} align={'center'} direction={'column'}>
0 && !shareSelected) ? 'white' : 'grey'} />
- 0 && !shareSelected) ? 'white' : 'grey'}>Bagikan
+ 0 && !shareSelected) ? 'white' : 'grey'}>Bagikan
setMore(true)} justify={'center'} align={'center'} direction={'column'}>
0 && !shareSelected) ? 'white' : 'grey'} />
- 0 && !shareSelected) ? 'white' : 'grey'}>Lainnya
+ 0 && !shareSelected) ? 'white' : 'grey'}>Lainnya
@@ -269,15 +269,13 @@ export default function NavbarDocumentDivision() {
>
)}
- setOpen(true)} variant="light" bg={WARNA.bgIcon} size="lg" radius="lg" aria-label="Settings">
}
/>
-
-
diff --git a/src/module/user/index.ts b/src/module/user/index.ts
index af89e21..e898624 100644
--- a/src/module/user/index.ts
+++ b/src/module/user/index.ts
@@ -1,11 +1,13 @@
import { TypeUser } from './lib/type_user';
import createLogUser from "./log/fun/createLogUser";
-import ViewEditProfile from "./profile/view/view_edit_profile";
import ViewProfile from "./profile/view/view_profile";
import { funGetAllmember } from './member/lib/api_member';
+import Profile from './profile/ui/profile';
+import EditProfile from './profile/ui/edit_profile';
export { ViewProfile };
-export { ViewEditProfile };
export { createLogUser };
export type { TypeUser }
export { funGetAllmember }
+export { Profile }
+export { EditProfile }
diff --git a/src/module/user/member/ui/create_member.tsx b/src/module/user/member/ui/create_member.tsx
index fbd6c08..b07d12b 100644
--- a/src/module/user/member/ui/create_member.tsx
+++ b/src/module/user/member/ui/create_member.tsx
@@ -273,8 +273,8 @@ export default function CreateMember() {
onBlur={() => setTouched({ ...touched, nik: true })}
error={
touched.nik && (
- listData.nik == "" ? "NIK Tidak Boleh Kosong" :
- listData.nik.length < 16 ? "NIK Harus 16 Karakter" : null
+ listData.nik === "" ? "NIK Tidak Boleh Kosong" :
+ listData.nik.length !== 16 ? "NIK Harus 16 Karakter" : null
)
}
/>
diff --git a/src/module/user/member/ui/edit_member.tsx b/src/module/user/member/ui/edit_member.tsx
index af68033..ba64dbc 100644
--- a/src/module/user/member/ui/edit_member.tsx
+++ b/src/module/user/member/ui/edit_member.tsx
@@ -250,10 +250,10 @@ export default function EditMember({ id }: { id: string }) {
onBlur={() => setTouched({ ...touched, nik: true })}
error={
touched.nik && (
- data.nik == "" ? "NIK Tidak Boleh Kosong" :
- data.nik.length < 16 ? "NIK Harus 16 Karakter" : null
+ data.nik === "" ? "NIK Tidak Boleh Kosong" :
+ data.nik.length !== 16 ? "NIK Harus 16 Karakter" : null
)
- }
+ }
/>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setValModal(false)}
- description="Apakah Anda yakin ingin
- melakukan perubahan data?"
- onYes={(val) => { onTrue(val) }} />
-
- )
-}
-
diff --git a/src/module/user/profile/lib/api_profile.ts b/src/module/user/profile/lib/api_profile.ts
new file mode 100644
index 0000000..bf05d41
--- /dev/null
+++ b/src/module/user/profile/lib/api_profile.ts
@@ -0,0 +1,17 @@
+import { IEditDataProfile } from "./type_profile";
+
+export const funGetProfileByCookies = async (path?: string) => {
+ const response = await fetch(`/api/user/profile${(path) ? path : ''}`, { next: { tags: ['profile'] } });
+ return await response.json().catch(() => null);
+}
+
+export const funEditProfileByCookies = async ( data: IEditDataProfile) => {
+ const response = await fetch(`/api/user/profile/`, {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(data),
+ });
+ return await response.json().catch(() => null);
+}
diff --git a/src/module/user/profile/lib/type_profile.ts b/src/module/user/profile/lib/type_profile.ts
new file mode 100644
index 0000000..db31c15
--- /dev/null
+++ b/src/module/user/profile/lib/type_profile.ts
@@ -0,0 +1,21 @@
+export interface IProfileById {
+ id: string
+ name: string
+ email: string
+ phone: string
+ nik: string
+ gender: string
+ idGroup: string
+ idPosition: string
+ group: string
+ position: string
+ }
+
+ export interface IEditDataProfile {
+ id: string;
+ nik: string;
+ name: string;
+ phone: string;
+ email: string;
+ gender: string;
+ }
\ No newline at end of file
diff --git a/src/module/user/profile/ui/edit_profile.tsx b/src/module/user/profile/ui/edit_profile.tsx
new file mode 100644
index 0000000..596f6ef
--- /dev/null
+++ b/src/module/user/profile/ui/edit_profile.tsx
@@ -0,0 +1,237 @@
+"use client"
+import { LayoutNavbarNew, WARNA } from "@/module/_global";
+import { Box, Button, Flex, Modal, Select, Stack, Text, TextInput } from "@mantine/core";
+import { HiUser } from "react-icons/hi2";
+import toast from "react-hot-toast";
+import LayoutModal from "@/module/_global/layout/layout_modal";
+import { useState } from "react";
+import { IEditDataProfile, IProfileById } from "../lib/type_profile";
+import { funEditProfileByCookies, funGetProfileByCookies } from "../lib/api_profile";
+import { useShallowEffect } from "@mantine/hooks";
+import { funGetUserByCookies } from "@/module/auth";
+
+export default function EditProfile() {
+ const [isValModal, setValModal] = useState(false)
+ const [isDataEdit, setDataEdit] = useState([])
+ const [touched, setTouched] = useState({
+ nik: false,
+ name: false,
+ phone: false,
+ email: false,
+ gender: false,
+ });
+ const [data, setData] = useState({
+ id: "",
+ nik: "",
+ name: "",
+ phone: "",
+ email: "",
+ gender: "",
+ })
+
+ async function getAllProfile() {
+ try {
+ const res = await funGetProfileByCookies()
+ setData(res.data)
+ } catch (error) {
+ console.error(error);
+ }
+ }
+
+ useShallowEffect(() => {
+ getAllProfile()
+ }, [])
+
+ async function onEditProfile(val: boolean) {
+ try {
+ if (val) {
+ const res = await funEditProfileByCookies({
+ id: data.id,
+ nik: data.nik,
+ name: data.name,
+ phone: data.phone,
+ email: data.email,
+ gender: data.gender,
+ })
+ if (res.success) {
+ setValModal(false)
+ toast.success(res.message)
+ } else {
+ toast.error(res.message)
+ }
+ }
+ setValModal(false)
+ } catch (error) {
+ console.error(error);
+ toast.error("Gagal edit profil, coba lagi nanti");
+ }
+ }
+
+ return (
+
+
+
+
+
+
+ {
+ 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
+ )
+ }
+ />
+ {
+ 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
+ )
+ }
+ />
+ {
+ 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
+ )
+ }
+ />
+ {
+ 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" : null
+ )
+ }
+ />
+
+
+
+
+ setValModal(false)}
+ description="Apakah Anda yakin ingin
+ melakukan perubahan data?"
+ onYes={(val) => { onEditProfile(val) }} />
+
+ )
+}
+
diff --git a/src/module/user/profile/ui/profile.tsx b/src/module/user/profile/ui/profile.tsx
new file mode 100644
index 0000000..dc435c1
--- /dev/null
+++ b/src/module/user/profile/ui/profile.tsx
@@ -0,0 +1,135 @@
+"use client"
+import { LayoutIconBack, LayoutNavbarHome, SkeletonDetailProfile, WARNA } from "@/module/_global";
+import { ActionIcon, Anchor, Box, Button, Flex, Group, Skeleton, Stack, Text } from "@mantine/core";
+import { BsInfo } from "react-icons/bs";
+import { HiUser } from "react-icons/hi2";
+import { RiIdCardFill } from "react-icons/ri";
+import { FaSquarePhone } from "react-icons/fa6";
+import { MdEmail } from "react-icons/md";
+import { InfoTitleProfile } from "../component/ui/ui_profile";
+import { IoMaleFemale } from "react-icons/io5";
+import toast from "react-hot-toast";
+import { LuLogOut } from "react-icons/lu";
+import LayoutModal from "@/module/_global/layout/layout_modal";
+import { useState } from "react";
+import { funGetProfileByCookies } from "../lib/api_profile";
+import { useShallowEffect } from "@mantine/hooks";
+import { IProfileById } from "../lib/type_profile";
+import { useRouter } from "next/navigation";
+
+export default function Profile() {
+ const [openModal, setOpenModal] = useState(false);
+ const [isData, setData] = useState()
+ const router = useRouter()
+ const [loading, setLoading] = useState(true)
+
+ async function getData() {
+ try {
+ setLoading(true)
+ const res = await funGetProfileByCookies()
+ setData(res.data)
+ setLoading(false)
+ } catch (error) {
+ console.error(error);
+ } finally {
+ setLoading(false)
+ }
+ }
+
+ useShallowEffect(() => {
+ getData()
+ }, [])
+
+ async function onLogout(val: boolean) {
+ try {
+ if (val) {
+ await fetch('/api/auth/logout', {
+ method: 'DELETE',
+ });
+ toast.success('Logout Success')
+ window.location.href = '/';
+ }
+
+ setOpenModal(false)
+
+ } catch (error) {
+ console.error(error);
+ }
+ }
+ return (
+ <>
+
+
+
+
+
+ { setOpenModal(true) }} variant="light" bg={WARNA.bgIcon} size="lg" radius="lg" aria-label="Info">
+
+
+
+
+
+ {loading ?
+
+ :
+ <>
+ {isData?.name}
+ {isData?.group} - {isData?.position}
+ >
+ }
+
+
+ {loading
+ ?
+
+ :
+
+
+ Informasi
+ router.push(`/profile/edit/`)}>Edit
+
+
+
+
+ NIK
+
+ {isData?.nik}
+
+
+
+
+ No Telepon
+
+ {isData?.phone}
+
+
+
+
+ Email
+
+ {isData?.email}
+
+
+
+
+ Gender
+
+
+ {isData?.gender === 'M' ? 'Laki-laki' : isData?.gender === 'F' ? 'Perempuan' : ''}
+
+
+
+
+ }
+
+ setOpenModal(false)}
+ description="Apakah Anda yakin ingin Keluar?"
+ onYes={(val) => onLogout(val)} />
+ >
+ )
+}
+
diff --git a/src/module/user/profile/view/view_edit_profile.tsx b/src/module/user/profile/view/view_edit_profile.tsx
deleted file mode 100644
index 4f93b49..0000000
--- a/src/module/user/profile/view/view_edit_profile.tsx
+++ /dev/null
@@ -1,7 +0,0 @@
-import EditProfile from "../component/edit_profile";
-
-export default function ViewEditProfile() {
- return (
-
- )
-}
\ No newline at end of file