ProfilePPID bagian Profile, VisiMisiPPD sudah ada seed dan bisa di edit
This commit is contained in:
@@ -4,66 +4,122 @@ import { toast } from "react-toastify";
|
||||
import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
// Schema validasi form
|
||||
const templateForm = z.object({
|
||||
name: z.string().min(3, "Nama minimal 3 karakter"),
|
||||
biodata: z.string().min(3, "Biodata minimal 3 karakter"),
|
||||
riwayat: z.string().min(3, "Riwayat minimal 3 karakter"),
|
||||
pengalaman: z.string().min(3, "Pengalaman minimal 3 karakter"),
|
||||
unggulan: z.string().min(3, "Unggulan minimal 3 karakter"),
|
||||
})
|
||||
name: z.string().min(3, "Nama minimal 3 karakter"),
|
||||
biodata: z.string().min(3, "Biodata minimal 3 karakter"),
|
||||
riwayat: z.string().min(3, "Riwayat minimal 3 karakter"),
|
||||
pengalaman: z.string().min(3, "Pengalaman minimal 3 karakter"),
|
||||
unggulan: z.string().min(3, "Unggulan minimal 3 karakter"),
|
||||
});
|
||||
|
||||
// Type ambil dari Prisma
|
||||
type ProfilePPIDForm = Prisma.ProfilePPIDGetPayload<{
|
||||
select: {
|
||||
name: true;
|
||||
biodata: true;
|
||||
riwayat: true;
|
||||
pengalaman: true;
|
||||
unggulan: true;
|
||||
}
|
||||
}>
|
||||
|
||||
const profilePPID = proxy({
|
||||
create: {
|
||||
form: {} as ProfilePPIDForm,
|
||||
loading: false,
|
||||
async create() {
|
||||
const cek = templateForm.safeParse(profilePPID.create.form);
|
||||
if (!cek.success) {
|
||||
const err = `[${cek.error.issues
|
||||
.map((v) => `${v.path.join(".")}`)
|
||||
.join("\n")}] required`;
|
||||
return toast.error(err);
|
||||
}
|
||||
try {
|
||||
profilePPID.create.loading = true;
|
||||
const res = await ApiFetch.api.ppid.profileppid["create"].post(profilePPID.create.form);
|
||||
if (res.status === 200) {
|
||||
profilePPID.findMany.load();
|
||||
return toast.success("success create");
|
||||
}
|
||||
return toast.error("failed create");
|
||||
} catch (error) {
|
||||
console.log((error as Error).message);
|
||||
} finally {
|
||||
profilePPID.create.loading = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
findMany: {
|
||||
data: null as
|
||||
| Prisma.ProfilePPIDGetPayload<{omit: {isActive: true}}>[]
|
||||
| null,
|
||||
async load() {
|
||||
const res = await ApiFetch.api.ppid.profileppid["find-many"].get();
|
||||
if (res.status === 200) {
|
||||
profilePPID.findMany.data = res.data?.data ?? [];
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
select: {
|
||||
id: true;
|
||||
name: true;
|
||||
biodata: true;
|
||||
riwayat: true;
|
||||
pengalaman: true;
|
||||
unggulan: true;
|
||||
imageUrl: true;
|
||||
};
|
||||
}>;
|
||||
|
||||
// Proxy utama
|
||||
const stateProfilePPID = proxy({
|
||||
profilePPID
|
||||
})
|
||||
findById: {
|
||||
data: null as ProfilePPIDForm | null,
|
||||
loading: false,
|
||||
initialize() {
|
||||
stateProfilePPID.findById.data = {
|
||||
id: '',
|
||||
name: '',
|
||||
biodata: '',
|
||||
riwayat: '',
|
||||
pengalaman: '',
|
||||
unggulan: '',
|
||||
imageUrl:''
|
||||
} as ProfilePPIDForm;
|
||||
},
|
||||
async load(id: string) {
|
||||
try {
|
||||
stateProfilePPID.findById.loading = true;
|
||||
const res = await ApiFetch.api.ppid.profileppid["find-by-id"].get({
|
||||
query: { id },
|
||||
});
|
||||
if (res.status === 200) {
|
||||
stateProfilePPID.findById.data = res.data?.data ?? null;
|
||||
} else {
|
||||
toast.error("Gagal mengambil data profile");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error((error as Error).message);
|
||||
toast.error("Terjadi kesalahan saat mengambil data profile");
|
||||
} finally {
|
||||
stateProfilePPID.findById.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
export default stateProfilePPID;
|
||||
update: {
|
||||
loading: false,
|
||||
async save(data: ProfilePPIDForm) {
|
||||
const cek = templateForm.safeParse(data);
|
||||
if (!cek.success) {
|
||||
const errors = cek.error.issues
|
||||
.map((issue) => `${issue.path.join(".")}: ${issue.message}`)
|
||||
.join(", ");
|
||||
toast.error(`Form tidak valid: ${errors}`);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
stateProfilePPID.update.loading = true;
|
||||
const res = await ApiFetch.api.ppid.profileppid["update"].post(data);
|
||||
if (res.status === 200) {
|
||||
toast.success("Berhasil update profile");
|
||||
await stateProfilePPID.findById.load(data.id);
|
||||
} else {
|
||||
toast.error("Gagal update profile");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error((error as Error).message);
|
||||
toast.error("Terjadi kesalahan saat update profile");
|
||||
} finally {
|
||||
stateProfilePPID.update.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
uploadImage: {
|
||||
loading: false,
|
||||
async save(file: File, id: string) {
|
||||
if (!file || !id) {
|
||||
toast.error("File atau ID harus disertakan");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
stateProfilePPID.uploadImage.loading = true;
|
||||
|
||||
const form = new FormData();
|
||||
form.append("file", file);
|
||||
form.append("id", id);
|
||||
|
||||
const res = await ApiFetch.api.ppid.profileppid["edit-img"].post(form);
|
||||
if (res.status === 200) {
|
||||
toast.success("Berhasil mengunggah gambar");
|
||||
await stateProfilePPID.findById.load(id);
|
||||
} else {
|
||||
toast.error("Gagal mengunggah gambar");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error((error as Error).message);
|
||||
toast.error("Terjadi kesalahan saat mengunggah gambar");
|
||||
} finally {
|
||||
stateProfilePPID.uploadImage.loading = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export default stateProfilePPID;
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
import ApiFetch from "@/lib/api-fetch";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { toast } from "react-toastify";
|
||||
import { proxy } from "valtio";
|
||||
import { z } from "zod";
|
||||
|
||||
const templateForm = z.object({
|
||||
misi: z.string().min(3, "Misi minimal 3 karakter"),
|
||||
visi: z.string().min(3, "Visi minimal 3 karakter"),
|
||||
});
|
||||
|
||||
type VisiMisiPPIDForm = Prisma.VisiMisiPPIDGetPayload<{
|
||||
select: {
|
||||
id: true;
|
||||
misi: true;
|
||||
visi: true;
|
||||
};
|
||||
}>;
|
||||
|
||||
const stateVisiMisiPPID = proxy({
|
||||
findById: {
|
||||
data: null as VisiMisiPPIDForm | null,
|
||||
loading: false,
|
||||
initialize() {
|
||||
stateVisiMisiPPID.findById.data = {
|
||||
id: "",
|
||||
misi: "",
|
||||
visi: "",
|
||||
} as VisiMisiPPIDForm;
|
||||
},
|
||||
async load(id: string) {
|
||||
try {
|
||||
stateVisiMisiPPID.findById.loading = true;
|
||||
const res = await ApiFetch.api.ppid.visimisippid["find-by-id"].get({
|
||||
query: { id },
|
||||
});
|
||||
if (res.status === 200) {
|
||||
stateVisiMisiPPID.findById.data = res.data?.data ?? null;
|
||||
} else {
|
||||
toast.error("Gagal mengambil data visi misi");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error((error as Error).message);
|
||||
toast.error("Terjadi kesalahan saat mengambil data visi misi");
|
||||
} finally {
|
||||
stateVisiMisiPPID.findById.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
update: {
|
||||
loading: false,
|
||||
async save(data: VisiMisiPPIDForm) {
|
||||
const cek = templateForm.safeParse(data);
|
||||
if (!cek.success) {
|
||||
const errors = cek.error.issues
|
||||
.map((issue) => `${issue.path.join(".")}: ${issue.message}`)
|
||||
.join(", ");
|
||||
toast.error(`Form tidak valid: ${errors}`);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
stateVisiMisiPPID.update.loading = true;
|
||||
const res = await ApiFetch.api.ppid.visimisippid["update"].post(data);
|
||||
if (res.status === 200) {
|
||||
toast.success("Berhasil update visi misi");
|
||||
await stateVisiMisiPPID.findById.load(data.id);
|
||||
} else {
|
||||
toast.error("Gagal update visi misi");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error((error as Error).message);
|
||||
toast.error("Terjadi kesalahan saat update visi misi");
|
||||
} finally {
|
||||
stateVisiMisiPPID.update.loading = false;
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default stateVisiMisiPPID;
|
||||
@@ -9,13 +9,12 @@ import Underline from '@tiptap/extension-underline';
|
||||
import { useEditor } from '@tiptap/react';
|
||||
import StarterKit from '@tiptap/starter-kit';
|
||||
|
||||
const content =
|
||||
'<h2 style="text-align: center;">Welcome to Mantine rich text editor</h2><p><code>RichTextEditor</code> component focuses on usability and is designed to be as simple as possible to bring a familiar editing experience to regular users. <code>RichTextEditor</code> is based on <a href="https://tiptap.dev/" rel="noopener noreferrer" target="_blank">Tiptap.dev</a> and supports all of its features:</p><ul><li>General text formatting: <strong>bold</strong>, <em>italic</em>, <u>underline</u>, <s>strike-through</s> </li><li>Headings (h1-h6)</li><li>Sub and super scripts (<sup><sup /></sup> and <sub><sub /></sub> tags)</li><li>Ordered and bullet lists</li><li>Text align </li><li>And all <a href="https://tiptap.dev/extensions" target="_blank" rel="noopener noreferrer">other extensions</a></li></ul>';
|
||||
|
||||
export function PPIDTextEditor({ onSubmit, onChange, showSubmit = true }: {
|
||||
export function PPIDTextEditor({ onSubmit, onChange, showSubmit = true, initialContent = '', }: {
|
||||
onSubmit?: (val: string) => void,
|
||||
onChange: (val: string) => void,
|
||||
showSubmit?: boolean }) {
|
||||
showSubmit?: boolean,
|
||||
initialContent?: string }) {
|
||||
const editor = useEditor({
|
||||
extensions: [
|
||||
StarterKit,
|
||||
@@ -27,7 +26,7 @@ export function PPIDTextEditor({ onSubmit, onChange, showSubmit = true }: {
|
||||
TextAlign.configure({ types: ['heading', 'paragraph'] }),
|
||||
],
|
||||
immediatelyRender: false,
|
||||
content,
|
||||
content: initialContent,
|
||||
onUpdate : ({editor}) => {
|
||||
onChange(editor.getHTML())
|
||||
}
|
||||
|
||||
10
src/app/admin/(dashboard)/ppid/profile-ppid/_com/biodata.ts
Normal file
10
src/app/admin/(dashboard)/ppid/profile-ppid/_com/biodata.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
const biodata = {
|
||||
id: "1",
|
||||
name: "<p>I.B Surya Prabhawa Manuaba, S.H., M.H.</p>",
|
||||
biodata: "<h2>Biodata</h2> <p>....</p>",
|
||||
riwayat: "<h2>Riwayat Karir</h2> <ul>...</ul>",
|
||||
pengalaman: "<h2>Pengalaman Organisasi</h2> <ul>...</ul>",
|
||||
unggulan: "<h2>Program Kerja Unggulan</h2> <h3>...</h3>",
|
||||
}
|
||||
|
||||
export default biodata
|
||||
@@ -1,23 +1,82 @@
|
||||
'use client'
|
||||
import { Box, Text } from '@mantine/core';
|
||||
import { Box, Group, Text } from '@mantine/core';
|
||||
import React from 'react';
|
||||
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import stateProfilePPID from '../../../_state/ppid/profile_ppid/profile_PPID';
|
||||
import { PPIDEditor } from '../../_com/ppid_Editor';
|
||||
import { PPIDTextEditor } from '../../_com/PPIDTextEditor';
|
||||
import { Dropzone, MIME_TYPES } from '@mantine/dropzone';
|
||||
import { IconUpload, IconX, IconPhoto } from '@tabler/icons-react';
|
||||
|
||||
|
||||
function Biodata() {
|
||||
const biodataState = useProxy(stateProfilePPID.profilePPID)
|
||||
const biodataState = useProxy(stateProfilePPID)
|
||||
const handleUpload = async (file: File) => {
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
formData.append("id", biodataState.findById.data?.id ?? ''); // pastikan ID-nya sesuai
|
||||
|
||||
const res = await fetch("/api/ppid/profileppid/edit-img", {
|
||||
method: "POST",
|
||||
body: formData,
|
||||
});
|
||||
|
||||
const result = await res.json();
|
||||
|
||||
if (result.success && biodataState.findById.data) {
|
||||
biodataState.findById.data.imageUrl = result.url;
|
||||
}
|
||||
};
|
||||
return (<Box>
|
||||
<Text fw={"bold"}>Biodata</Text>
|
||||
<PPIDEditor
|
||||
showSubmit={false}
|
||||
onChange={(val) => {
|
||||
biodataState.create.form.biodata = val
|
||||
}}
|
||||
<Dropzone
|
||||
mb={20}
|
||||
onDrop={(files) => {
|
||||
const file = files[0];
|
||||
const currentId = biodataState.findById.data?.id;
|
||||
if (file && currentId) {
|
||||
handleUpload(file);
|
||||
}
|
||||
}}
|
||||
onReject={() => console.log('File rejected')}
|
||||
maxSize={5 * 1024 ** 2} // 5MB
|
||||
accept={[MIME_TYPES.jpeg, MIME_TYPES.png, MIME_TYPES.webp]}
|
||||
loading={stateProfilePPID.uploadImage.loading}
|
||||
>
|
||||
<Group justify="center" gap="md" mih={150} style={{ pointerEvents: 'none' }}>
|
||||
<Dropzone.Accept>
|
||||
<IconUpload size={50} stroke={1.5} />
|
||||
</Dropzone.Accept>
|
||||
<Dropzone.Reject>
|
||||
<IconX size={50} stroke={1.5} />
|
||||
</Dropzone.Reject>
|
||||
<Dropzone.Idle>
|
||||
<IconPhoto size={50} stroke={1.5} />
|
||||
</Dropzone.Idle>
|
||||
|
||||
<div>
|
||||
<Text size="xl" inline>
|
||||
Drag & drop gambar di sini atau klik untuk pilih file
|
||||
</Text>
|
||||
<Text size="sm" c="dimmed" inline mt={7}>
|
||||
Maksimal ukuran file 5MB. Format: JPG, PNG, WebP
|
||||
</Text>
|
||||
</div>
|
||||
</Group>
|
||||
</Dropzone>
|
||||
<PPIDTextEditor
|
||||
key={biodataState.findById.data?.id ?? 'new'}
|
||||
showSubmit={false}
|
||||
onChange={(val) => {
|
||||
if (biodataState.findById.data) {
|
||||
biodataState.findById.data.biodata = val;
|
||||
}
|
||||
}}
|
||||
initialContent={biodataState.findById.data?.biodata ?? ''}
|
||||
/>
|
||||
|
||||
</Box>
|
||||
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
68
src/app/admin/(dashboard)/ppid/profile-ppid/listPage.tsx
Normal file
68
src/app/admin/(dashboard)/ppid/profile-ppid/listPage.tsx
Normal file
@@ -0,0 +1,68 @@
|
||||
import colors from '@/con/colors';
|
||||
import { Stack, Skeleton, Paper, Title, Box, Text, Image } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import React from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import stateProfilePPID from '../../_state/ppid/profile_ppid/profile_PPID';
|
||||
|
||||
function ProfileList() {
|
||||
const allList = useProxy(stateProfilePPID)
|
||||
useShallowEffect(() => {
|
||||
allList.findById.load("1") // Assuming "1" is your default ID, adjust as needed
|
||||
}, [])
|
||||
|
||||
if (!allList.findById.data) return <Stack>
|
||||
{Array.from({ length: 10 }).map((v, k) => <Skeleton key={k} h={40} />)}
|
||||
</Stack>
|
||||
|
||||
const dataArray = Array.isArray(allList.findById.data)
|
||||
? allList.findById.data
|
||||
: [allList.findById.data];
|
||||
|
||||
return (
|
||||
<Paper bg={colors['white-1']} p={'md'}>
|
||||
<Stack gap={"xs"}>
|
||||
<Title order={3}>List Profile PPID</Title>
|
||||
{dataArray.map((item) => (
|
||||
<Box key={item.id}>
|
||||
<Box>
|
||||
<Text fw={"bold"}>Gambar</Text>
|
||||
{item.imageUrl ? (
|
||||
<Image
|
||||
src={item.imageUrl}
|
||||
alt="Foto Profil"
|
||||
w={200}
|
||||
radius="md"
|
||||
/>
|
||||
) : (
|
||||
<Text c="dimmed">Belum ada foto</Text>
|
||||
)}
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fw={"bold"}>Nama</Text>
|
||||
<Text dangerouslySetInnerHTML={{ __html: item.name }}></Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fw={"bold"}>Biodata</Text>
|
||||
<Text dangerouslySetInnerHTML={{ __html: item.biodata }}></Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fw={"bold"}>Riwayat</Text>
|
||||
<Text dangerouslySetInnerHTML={{ __html: item.riwayat }}></Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fw={"bold"}>Pengalaman</Text>
|
||||
<Text dangerouslySetInnerHTML={{ __html: item.pengalaman }}></Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fw={"bold"}>Program Kerja Unggulan</Text>
|
||||
<Text dangerouslySetInnerHTML={{ __html: item.unggulan }}></Text>
|
||||
</Box>
|
||||
</Box>
|
||||
))}
|
||||
</Stack>
|
||||
</Paper>
|
||||
)
|
||||
}
|
||||
|
||||
export default ProfileList;
|
||||
@@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Group, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||
import { Box, Button, Group, Paper, SimpleGrid, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||
import Biodata from './biodata/page';
|
||||
import PengalamanOrganisasi from './pengalaman_organisasi/page';
|
||||
import RiwayatKarir from './riwayat_karir/page';
|
||||
@@ -8,6 +8,7 @@ import ProgramKerjaUnggulan from './program_kerja_unggulan/page';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import stateProfilePPID from '../../_state/ppid/profile_ppid/profile_PPID';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import ProfileList from './listPage';
|
||||
|
||||
|
||||
function Page() {
|
||||
@@ -23,15 +24,24 @@ function Page() {
|
||||
|
||||
function ProfileCreate() {
|
||||
const allState = useProxy(stateProfilePPID)
|
||||
|
||||
// Initialize data if it doesn't exist
|
||||
useShallowEffect(() => {
|
||||
if (!allState.findById.data) {
|
||||
allState.findById.initialize()
|
||||
}
|
||||
}, [])
|
||||
|
||||
const submit = () => {
|
||||
if (
|
||||
allState.profilePPID.create.form.name &&
|
||||
allState.profilePPID.create.form.biodata &&
|
||||
allState.profilePPID.create.form.riwayat &&
|
||||
allState.profilePPID.create.form.pengalaman &&
|
||||
allState.profilePPID.create.form.unggulan) {
|
||||
allState.profilePPID.create.create()
|
||||
}
|
||||
allState.findById.data?.name &&
|
||||
allState.findById.data?.biodata &&
|
||||
allState.findById.data?.riwayat &&
|
||||
allState.findById.data?.pengalaman &&
|
||||
allState.findById.data?.unggulan
|
||||
) {
|
||||
allState.update.save(allState.findById.data)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -41,8 +51,11 @@ function ProfileCreate() {
|
||||
<TextInput
|
||||
label={<Text fw={"bold"}>Nama Perbekel</Text>}
|
||||
placeholder="masukkan nama perbekel"
|
||||
value={allState.findById.data?.name || ''}
|
||||
onChange={(val) => {
|
||||
allState.profilePPID.create.form.name = val.currentTarget.value
|
||||
if (allState.findById.data) {
|
||||
allState.findById.data.name = val.currentTarget.value
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<Biodata />
|
||||
@@ -50,53 +63,17 @@ function ProfileCreate() {
|
||||
<PengalamanOrganisasi />
|
||||
<ProgramKerjaUnggulan />
|
||||
<Group>
|
||||
<Button bg={colors['blue-button']} onClick={submit}>Submit</Button>
|
||||
<Button
|
||||
bg={colors['blue-button']}
|
||||
onClick={submit}
|
||||
loading={allState.update.loading}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
)
|
||||
}
|
||||
|
||||
function ProfileList() {
|
||||
const allList = useProxy(stateProfilePPID)
|
||||
useShallowEffect(() => {
|
||||
allList.profilePPID.findMany.load()
|
||||
}, [])
|
||||
|
||||
if (!allList.profilePPID.findMany.data) return <Stack>
|
||||
{Array.from({ length: 10 }).map((v, k) => <Skeleton key={k} h={40} />)}
|
||||
</Stack>
|
||||
return (
|
||||
<Paper bg={colors['white-1']} p={'md'}>
|
||||
<Stack gap={"xs"}>
|
||||
<Title order={3}>List Profile PPID</Title>
|
||||
{allList.profilePPID.findMany.data?.map((item) => (
|
||||
<Box key={item.id}>
|
||||
<Box>
|
||||
<Text fw={"bold"}>Nama</Text>
|
||||
<Text dangerouslySetInnerHTML={{ __html: item.name }}></Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fw={"bold"}>Biodata</Text>
|
||||
<Text dangerouslySetInnerHTML={{ __html: item.biodata }}></Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fw={"bold"}>Riwayat</Text>
|
||||
<Text dangerouslySetInnerHTML={{ __html: item.riwayat }}></Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fw={"bold"}>Pengalaman</Text>
|
||||
<Text dangerouslySetInnerHTML={{ __html: item.pengalaman }}></Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fw={"bold"}>Program Kerja Unggulan</Text>
|
||||
<Text dangerouslySetInnerHTML={{ __html: item.unggulan }}></Text>
|
||||
</Box>
|
||||
</Box>
|
||||
))}
|
||||
</Stack>
|
||||
</Paper>
|
||||
)
|
||||
}
|
||||
|
||||
export default Page;
|
||||
export default Page;
|
||||
@@ -3,17 +3,21 @@ import { Box, Text } from '@mantine/core';
|
||||
import React from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import stateProfilePPID from '../../../_state/ppid/profile_ppid/profile_PPID';
|
||||
import { PPIDEditor } from '../../_com/ppid_Editor';
|
||||
import { PPIDTextEditor } from '../../_com/PPIDTextEditor';
|
||||
|
||||
function PengalamanOrganisasi() {
|
||||
const pengalamanOrganisasiState = useProxy(stateProfilePPID.profilePPID)
|
||||
const pengalamanOrganisasiState = useProxy(stateProfilePPID)
|
||||
return (<Box>
|
||||
<Text fw={"bold"}>Pengalaman Organisasi</Text>
|
||||
<PPIDEditor
|
||||
<PPIDTextEditor
|
||||
key={pengalamanOrganisasiState.findById.data?.id ?? 'new'}
|
||||
showSubmit={false}
|
||||
onChange={(val) => {
|
||||
pengalamanOrganisasiState.create.form.pengalaman = val
|
||||
if (pengalamanOrganisasiState.findById.data) {
|
||||
pengalamanOrganisasiState.findById.data.pengalaman = val;
|
||||
}
|
||||
}}
|
||||
initialContent={pengalamanOrganisasiState.findById.data?.pengalaman ?? ''}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -3,17 +3,21 @@ import { Box, Text } from '@mantine/core';
|
||||
import React from 'react';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import stateProfilePPID from '../../../_state/ppid/profile_ppid/profile_PPID';
|
||||
import { PPIDEditor } from '../../_com/ppid_Editor';
|
||||
import { PPIDTextEditor } from '../../_com/PPIDTextEditor';
|
||||
|
||||
function ProgramKerjaUnggulan() {
|
||||
const programKerjaUnggulanState = useProxy(stateProfilePPID.profilePPID)
|
||||
const programKerjaUnggulanState = useProxy(stateProfilePPID)
|
||||
return (<Box>
|
||||
<Text fw={"bold"}>Program Kerja Unggulan</Text>
|
||||
<PPIDEditor
|
||||
<PPIDTextEditor
|
||||
key={programKerjaUnggulanState.findById.data?.id ?? 'new'}
|
||||
showSubmit={false}
|
||||
onChange={(val) => {
|
||||
programKerjaUnggulanState.create.form.unggulan = val
|
||||
if (programKerjaUnggulanState.findById.data) {
|
||||
programKerjaUnggulanState.findById.data.unggulan = val;
|
||||
}
|
||||
}}
|
||||
initialContent={programKerjaUnggulanState.findById.data?.unggulan ?? ''}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -7,21 +7,24 @@ import dynamic from 'next/dynamic';
|
||||
import stateProfilePPID from '../../../_state/ppid/profile_ppid/profile_PPID';
|
||||
|
||||
// ini penting
|
||||
const PPIDEditor = dynamic(() => import('../../_com/ppid_Editor').then(mod => mod.PPIDEditor), {
|
||||
const PPIDTextEditor = dynamic(() => import('../../_com/PPIDTextEditor').then(mod => mod.PPIDTextEditor), {
|
||||
ssr: false, // disable server side rendering
|
||||
});
|
||||
|
||||
function RiwayatKarir() {
|
||||
const biodataState = useProxy(stateProfilePPID.profilePPID);
|
||||
const riwayatKarirState = useProxy(stateProfilePPID);
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Text fw={"bold"}>Riwayat Karir</Text>
|
||||
<PPIDEditor
|
||||
<PPIDTextEditor
|
||||
key={riwayatKarirState.findById.data?.id ?? 'new'}
|
||||
showSubmit={false}
|
||||
onChange={(val) => {
|
||||
biodataState.create.form.riwayat = val;
|
||||
if (riwayatKarirState.findById.data) {
|
||||
riwayatKarirState.findById.data.riwayat = val;
|
||||
}
|
||||
}}
|
||||
initialContent={riwayatKarirState.findById.data?.riwayat ?? ''}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
'use client'
|
||||
import { Box, Text } from '@mantine/core';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import { PPIDTextEditor } from '../../_com/PPIDTextEditor';
|
||||
import stateVisiMisiPPID from '../../../_state/ppid/visi_misi_ppid/visimisiPPID';
|
||||
|
||||
function MisiPPID() {
|
||||
const misiState = useProxy(stateVisiMisiPPID)
|
||||
return (
|
||||
<Box>
|
||||
<Text fw={"bold"}>Misi PPID</Text>
|
||||
<PPIDTextEditor
|
||||
key={misiState.findById.data?.id ?? 'new'}
|
||||
showSubmit={false}
|
||||
onChange={(val) => {
|
||||
if(misiState.findById.data){
|
||||
misiState.findById.data.misi = val
|
||||
}
|
||||
}}
|
||||
initialContent={misiState.findById.data?.misi ?? ''}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export default MisiPPID;
|
||||
@@ -1,11 +1,83 @@
|
||||
import React from 'react';
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Group, Paper, SimpleGrid, Skeleton, Stack, Text, Title } from '@mantine/core';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import stateVisiMisiPPID from '../../_state/ppid/visi_misi_ppid/visimisiPPID';
|
||||
import MisiPPID from './misiPPID/page';
|
||||
import VisiPPID from './visiPPID/page';
|
||||
|
||||
function Page() {
|
||||
return (
|
||||
<div>
|
||||
visi-misi-ppid
|
||||
</div>
|
||||
<Box>
|
||||
<SimpleGrid cols={{ base: 1, md: 2 }}>
|
||||
<VisiMisiPPIDCreate />
|
||||
<VisiMisiPPIDList />
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
function VisiMisiPPIDCreate() {
|
||||
const visiMisi = useProxy(stateVisiMisiPPID)
|
||||
|
||||
useShallowEffect(() => {
|
||||
if(!visiMisi.findById.data){
|
||||
visiMisi.findById.initialize()
|
||||
}
|
||||
}, [])
|
||||
|
||||
const submit = () => {
|
||||
if(visiMisi.findById.data?.misi && visiMisi.findById.data?.visi){
|
||||
visiMisi.update.save(visiMisi.findById.data)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Paper bg={colors['white-1']} p={'md'} radius={10}>
|
||||
<Stack gap={"xs"}>
|
||||
<Title order={3}>Visi Misi PPID</Title>
|
||||
<VisiPPID />
|
||||
<MisiPPID />
|
||||
<Group>
|
||||
<Button
|
||||
bg={colors['blue-button']}
|
||||
onClick={submit}
|
||||
loading={visiMisi.update.loading}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
)
|
||||
}
|
||||
|
||||
function VisiMisiPPIDList() {
|
||||
const listVisiMisi = useProxy(stateVisiMisiPPID)
|
||||
useShallowEffect(() => {
|
||||
listVisiMisi.findById.load("1")
|
||||
}, [])
|
||||
|
||||
if(!listVisiMisi.findById.data) return <Stack>
|
||||
{Array.from({length: 10}).map((v, k) => <Skeleton key={k} h={40} />)}
|
||||
</Stack>
|
||||
|
||||
return (
|
||||
<Paper bg={colors['white-1']} p={'md'} radius={10}>
|
||||
<Stack gap={"xs"}>
|
||||
<Title order={3}>List Visi Misi PPID</Title>
|
||||
<Box>
|
||||
<Text fw={"bold"}>Visi PPID</Text>
|
||||
<Text dangerouslySetInnerHTML={{__html: listVisiMisi.findById.data?.visi}}></Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fw={"bold"}>Misi PPID</Text>
|
||||
<Text dangerouslySetInnerHTML={{__html: listVisiMisi.findById.data?.misi}}></Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Paper>
|
||||
)
|
||||
}
|
||||
|
||||
export default Page;
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
'use client'
|
||||
import { Box, Text } from '@mantine/core';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import { PPIDTextEditor } from '../../_com/PPIDTextEditor';
|
||||
import stateVisiMisiPPID from '../../../_state/ppid/visi_misi_ppid/visimisiPPID';
|
||||
|
||||
function VisiPPID() {
|
||||
const visiState = useProxy(stateVisiMisiPPID)
|
||||
return (
|
||||
<Box>
|
||||
<Text fw={"bold"}>Visi PPID</Text>
|
||||
<PPIDTextEditor
|
||||
key={visiState.findById.data?.id ?? 'new'}
|
||||
showSubmit={false}
|
||||
onChange={(val) => {
|
||||
if(visiState.findById.data){
|
||||
visiState.findById.data.visi = val
|
||||
}
|
||||
}}
|
||||
initialContent={visiState.findById.data?.visi ?? ''}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export default VisiPPID;
|
||||
Reference in New Issue
Block a user