API Profile Desa Menu Desa
Fix Eror gallery bagian tabs video Next UI Profile Desa
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,18 +1,31 @@
|
||||
export function convertYoutubeUrlToEmbed(url: string): string | null {
|
||||
const watchRegex = /(?:https?:\/\/)?(?:www\.)?youtube\.com\/watch\?v=([^&]+)/;
|
||||
const shortRegex = /(?:https?:\/\/)?youtu\.be\/([^?]+)/;
|
||||
export function convertYoutubeUrlToEmbed(url: string) {
|
||||
const videoIdMatch = url.match(/(?:youtube\.com\/watch\?v=|youtu\.be\/)([a-zA-Z0-9_-]{11})/);
|
||||
return videoIdMatch ? `https://www.youtube.com/embed/${videoIdMatch[1]}` : null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// (url: string): string | null {
|
||||
// const watchRegex = /(?:https?:\/\/)?(?:www\.)?youtube\.com\/watch\?v=([^&]+)/;
|
||||
// const shortRegex = /(?:https?:\/\/)?youtu\.be\/([^?]+)/;
|
||||
|
||||
const matchWatch = url.match(watchRegex);
|
||||
const matchShort = url.match(shortRegex);
|
||||
// const matchWatch = url.match(watchRegex);
|
||||
// const matchShort = url.match(shortRegex);
|
||||
|
||||
if (matchWatch) {
|
||||
return `https://www.youtube.com/embed/${matchWatch[1]}`;
|
||||
}
|
||||
// if (matchWatch) {
|
||||
// return `https://www.youtube.com/embed/${matchWatch[1]}`;
|
||||
// }
|
||||
|
||||
if (matchShort) {
|
||||
return `https://www.youtube.com/embed/${matchShort[1]}`;
|
||||
}
|
||||
// if (matchShort) {
|
||||
// return `https://www.youtube.com/embed/${matchShort[1]}`;
|
||||
// }
|
||||
|
||||
return null;
|
||||
}
|
||||
// return null;
|
||||
// }
|
||||
|
||||
@@ -11,18 +11,16 @@ import { toast } from 'react-toastify';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import { convertYoutubeUrlToEmbed } from '../../../lib/youtube-utils';
|
||||
|
||||
|
||||
|
||||
function EditVideo() {
|
||||
const router = useRouter();
|
||||
const [embedLink, setEmbedLink] = useState("");
|
||||
const router = useRouter();
|
||||
const videoState = useProxy(stateGallery.video)
|
||||
const params = useParams()
|
||||
|
||||
const [formData, setFormData] = useState({
|
||||
name: videoState.findUnique.data?.name || '',
|
||||
deskripsi: videoState.findUnique.data?.deskripsi || '',
|
||||
linkVideo: videoState.findUnique.data?.linkVideo || '',
|
||||
})
|
||||
name: '',
|
||||
deskripsi: '',
|
||||
linkVideo: '',
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const loadVideo = async () => {
|
||||
@@ -36,8 +34,6 @@ function EditVideo() {
|
||||
deskripsi: data.deskripsi || '',
|
||||
linkVideo: data.linkVideo || '',
|
||||
});
|
||||
const embed = convertYoutubeUrlToEmbed(data.linkVideo);
|
||||
setEmbedLink(embed || "");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading video:', error);
|
||||
@@ -47,7 +43,15 @@ function EditVideo() {
|
||||
loadVideo();
|
||||
}, [params?.id]);
|
||||
|
||||
const embedLink = convertYoutubeUrlToEmbed(formData.linkVideo);
|
||||
|
||||
const handleSubmit = async () => {
|
||||
const converted = convertYoutubeUrlToEmbed(formData.linkVideo);
|
||||
if (!converted) {
|
||||
toast.error("Link YouTube tidak valid. Pastikan formatnya benar.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
videoState.update.form = {
|
||||
...videoState.update.form,
|
||||
@@ -55,11 +59,6 @@ function EditVideo() {
|
||||
deskripsi: formData.deskripsi,
|
||||
linkVideo: formData.linkVideo,
|
||||
};
|
||||
const converted = convertYoutubeUrlToEmbed(formData.linkVideo);
|
||||
if (!converted) {
|
||||
toast.error("Link YouTube tidak valid. Pastikan formatnya benar.");
|
||||
return;
|
||||
}
|
||||
await videoState.update.update();
|
||||
toast.success('Video berhasil diperbarui!');
|
||||
router.push('/admin/desa/gallery/video');
|
||||
@@ -80,29 +79,23 @@ function EditVideo() {
|
||||
<Paper w={{ base: '100%', md: '50%' }} bg={colors['white-1']} p={'md'}>
|
||||
<Stack gap={"xs"}>
|
||||
<Title order={4}>Edit Video</Title>
|
||||
|
||||
<TextInput
|
||||
label={<Text fw={"bold"} fz={"sm"}>Judul Video</Text>}
|
||||
placeholder='Masukkan judul video'
|
||||
value={formData.name}
|
||||
onChange={(val) => {
|
||||
setFormData({
|
||||
...formData,
|
||||
name: val.target.value,
|
||||
})
|
||||
setFormData({ ...formData, name: val.target.value });
|
||||
}}
|
||||
/>
|
||||
|
||||
<Box>
|
||||
<TextInput
|
||||
label="Link Video YouTube"
|
||||
placeholder="https://www.youtube.com/watch?v=abc123"
|
||||
value={formData.linkVideo}
|
||||
onChange={(e) => {
|
||||
setFormData({
|
||||
...formData,
|
||||
linkVideo: e.currentTarget.value,
|
||||
})
|
||||
const embed = convertYoutubeUrlToEmbed(e.currentTarget.value);
|
||||
setEmbedLink(embed || "");
|
||||
setFormData({ ...formData, linkVideo: e.currentTarget.value });
|
||||
}}
|
||||
required
|
||||
/>
|
||||
@@ -118,18 +111,17 @@ function EditVideo() {
|
||||
></iframe>
|
||||
)}
|
||||
</Box>
|
||||
|
||||
<Box>
|
||||
<Text fw={"bold"} fz={"sm"}>Deskripsi Video</Text>
|
||||
<EditEditor
|
||||
value={formData.deskripsi}
|
||||
onChange={(val) => {
|
||||
setFormData({
|
||||
...formData,
|
||||
deskripsi: val,
|
||||
})
|
||||
setFormData({ ...formData, deskripsi: val });
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<Group>
|
||||
<Button onClick={handleSubmit} bg={colors['blue-button']}>Submit</Button>
|
||||
</Group>
|
||||
|
||||
@@ -16,7 +16,7 @@ function CreateVideo() {
|
||||
const videoState = useProxy(stateGallery.video)
|
||||
const router = useRouter();
|
||||
const [link, setLink] = useState("");
|
||||
const [embedLink, setEmbedLink] = useState("");
|
||||
const embedLink = convertYoutubeUrlToEmbed(link);
|
||||
|
||||
const resetForm = () => {
|
||||
videoState.create.form = {
|
||||
@@ -26,15 +26,17 @@ function CreateVideo() {
|
||||
};
|
||||
};
|
||||
const handleSubmit = async () => {
|
||||
const converted = convertYoutubeUrlToEmbed(videoState.create.form.linkVideo);
|
||||
if (!converted) {
|
||||
if (!embedLink) {
|
||||
toast.error("Link YouTube tidak valid. Pastikan formatnya benar.");
|
||||
return;
|
||||
}
|
||||
|
||||
videoState.create.form.linkVideo = embedLink; // pastikan diset di sini juga (jaga-jaga)
|
||||
await videoState.create.create();
|
||||
resetForm();
|
||||
router.push("/admin/desa/gallery/video")
|
||||
router.push("/admin/desa/gallery/video");
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<Box>
|
||||
@@ -63,8 +65,6 @@ function CreateVideo() {
|
||||
value={link}
|
||||
onChange={(e) => {
|
||||
setLink(e.currentTarget.value);
|
||||
const embed = convertYoutubeUrlToEmbed(e.currentTarget.value);
|
||||
setEmbedLink(embed || "");
|
||||
}}
|
||||
required
|
||||
/>
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
|
||||
import { usePathname, useRouter } from 'next/navigation';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
function LayoutTabsDetail({ children }: { children: React.ReactNode }) {
|
||||
const router = useRouter()
|
||||
const pathname = usePathname()
|
||||
const tabs = [
|
||||
{
|
||||
label: "Profile Desa",
|
||||
value: "profiledesa",
|
||||
href: "/admin/desa/profile/profile-desa"
|
||||
},
|
||||
{
|
||||
label: "Profile Perbekel",
|
||||
value: "profileperbekel",
|
||||
href: "/admin/desa/profile/profile-perbekel"
|
||||
}
|
||||
];
|
||||
const curentTab = tabs.find(tab => tab.href === pathname)
|
||||
const [activeTab, setActiveTab] = useState<string | null>(curentTab?.value || tabs[0].value);
|
||||
|
||||
const handleTabChange = (value: string | null) => {
|
||||
const tab = tabs.find(t => t.value === value)
|
||||
if (tab) {
|
||||
router.push(tab.href)
|
||||
}
|
||||
setActiveTab(value)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const match = tabs.find(tab => tab.href === pathname)
|
||||
if (match) {
|
||||
setActiveTab(match.value)
|
||||
}
|
||||
}, [pathname])
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<Title order={3}>Profile Desa</Title>
|
||||
<Tabs color={colors['blue-button']} variant='pills' value={activeTab} onChange={handleTabChange}>
|
||||
<TabsList p={"xs"} bg={"#BBC8E7FF"}>
|
||||
{tabs.map((e, i) => (
|
||||
<TabsTab key={i} value={e.value}>{e.label}</TabsTab>
|
||||
))}
|
||||
</TabsList>
|
||||
{tabs.map((e, i) => (
|
||||
<TabsPanel key={i} value={e.value}>
|
||||
{/* Konten dummy, bisa diganti tergantung routing */}
|
||||
<></>
|
||||
</TabsPanel>
|
||||
))}
|
||||
</Tabs>
|
||||
{children}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
export default LayoutTabsDetail;
|
||||
@@ -0,0 +1,71 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { Stack, Tabs, TabsList, TabsPanel, TabsTab } from '@mantine/core';
|
||||
import { usePathname, useRouter } from 'next/navigation';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
function LayoutTabsEdit({ children }: { children: React.ReactNode }) {
|
||||
const router = useRouter()
|
||||
const pathname = usePathname()
|
||||
const tabs = [
|
||||
{
|
||||
label: "Sejarah Desa",
|
||||
value: "sejarahdesa",
|
||||
href: "/admin/desa/profile/edit/sejarah_desa"
|
||||
},
|
||||
{
|
||||
label: "Visi Misi Desa",
|
||||
value: "visimisidesa",
|
||||
href: "/admin/desa/profile/edit/visi_misi_desa"
|
||||
},
|
||||
{
|
||||
label: "Lambang Desa",
|
||||
value: "lambangdesa",
|
||||
href: "/admin/desa/profile/edit/lambang_desa"
|
||||
},
|
||||
{
|
||||
label: "Maskot Desa",
|
||||
value: "maskotdesa",
|
||||
href: "/admin/desa/profile/edit/maskot_desa"
|
||||
},
|
||||
];
|
||||
const curentTab = tabs.find(tab => tab.href === pathname)
|
||||
const [activeTab, setActiveTab] = useState<string | null>(curentTab?.value || tabs[0].value);
|
||||
|
||||
const handleTabChange = (value: string | null) => {
|
||||
const tab = tabs.find(t => t.value === value)
|
||||
if (tab) {
|
||||
router.push(tab.href)
|
||||
}
|
||||
setActiveTab(value)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const match = tabs.find(tab => tab.href === pathname)
|
||||
if (match) {
|
||||
setActiveTab(match.value)
|
||||
}
|
||||
}, [pathname])
|
||||
|
||||
return (
|
||||
<Stack>
|
||||
<Tabs color={colors['blue-button']} variant='default' value={activeTab} onChange={handleTabChange}>
|
||||
<TabsList>
|
||||
{tabs.map((e, i) => (
|
||||
<TabsTab key={i} value={e.value}>{e.label}</TabsTab>
|
||||
))}
|
||||
</TabsList>
|
||||
{tabs.map((e, i) => (
|
||||
<TabsPanel key={i} value={e.value}>
|
||||
{/* Konten dummy, bisa diganti tergantung routing */}
|
||||
<></>
|
||||
</TabsPanel>
|
||||
))}
|
||||
</Tabs>
|
||||
{children}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
export default LayoutTabsEdit;
|
||||
13
src/app/admin/(dashboard)/desa/profile/edit/layout.tsx
Normal file
13
src/app/admin/(dashboard)/desa/profile/edit/layout.tsx
Normal file
@@ -0,0 +1,13 @@
|
||||
'use client'
|
||||
|
||||
import LayoutTabsEdit from "../_lib/layoutTabsEdit"
|
||||
|
||||
function Layout({children}: {children: React.ReactNode}) {
|
||||
return (
|
||||
<LayoutTabsEdit>
|
||||
{children}
|
||||
</LayoutTabsEdit>
|
||||
);
|
||||
}
|
||||
|
||||
export default Layout;
|
||||
@@ -0,0 +1,34 @@
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Group, Paper, SimpleGrid, Stack, Text, Title } from '@mantine/core';
|
||||
|
||||
|
||||
|
||||
function SejarahDesa() {
|
||||
|
||||
|
||||
return (
|
||||
<Box py={10}>
|
||||
<SimpleGrid cols={{ base: 1, md: 2 }}>
|
||||
<Box>
|
||||
<Paper bg={colors['white-1']} p={'md'}>
|
||||
<Stack>
|
||||
<Title order={3}>Sejarah Desa</Title>
|
||||
<Text fw={"bold"}>Deskripsi Sejarah Desa</Text>
|
||||
<Group>
|
||||
<Button
|
||||
mt={10}
|
||||
bg={colors['blue-button']}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box>
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export default SejarahDesa;
|
||||
@@ -0,0 +1,25 @@
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Paper, Stack } from '@mantine/core';
|
||||
|
||||
function Page() {
|
||||
return (
|
||||
<Paper bg={colors['white-1']} p={'md'} radius={10}>
|
||||
<Stack gap={"22"}>
|
||||
<Box>
|
||||
<Stack gap={'lg'}>
|
||||
<Paper p={"xl"} bg={colors['BG-trans']}>
|
||||
{/* <Box px={{ base: 0, md: 30 }}>
|
||||
<Text ta={"center"} fz={{ base: "h3", md: "h2" }} fw={"bold"} dangerouslySetInnerHTML={{ __html: listDasarHukum.findById.data.judul }} />
|
||||
</Box>
|
||||
<Box px={{ base: 0, md: 30 }}>
|
||||
<Text fz={{ base: "md", md: "h3" }} ta={"justify"} dangerouslySetInnerHTML={{ __html: listDasarHukum.findById.data.content }} />
|
||||
</Box> */}
|
||||
</Paper>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
export default Page;
|
||||
11
src/app/admin/(dashboard)/desa/profile/layout.tsx
Normal file
11
src/app/admin/(dashboard)/desa/profile/layout.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
'use client'
|
||||
|
||||
import LayoutTabsDetail from "./_lib/layoutTabsDetail"
|
||||
|
||||
export default function Layout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<LayoutTabsDetail>
|
||||
{children}
|
||||
</LayoutTabsDetail>
|
||||
)
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
import colors from '@/con/colors';
|
||||
import { Stack, Title, Tabs, TabsList, TabsTab, TabsPanel } from '@mantine/core';
|
||||
import React from 'react';
|
||||
import SejarahDesa from './ui/sejarah_desa/page';
|
||||
import VisiMisiDesa from './ui/visi_misi_desa/page';
|
||||
import LambangDesa from './ui/lambang_desa/page';
|
||||
import MaskotDesa from './ui/maskot_desa/page';
|
||||
import ProfilePerbekel from './ui/profile_perbekel/page';
|
||||
|
||||
function Page() {
|
||||
return (
|
||||
<Stack >
|
||||
<Title order={3}>Profile Desa</Title>
|
||||
<Tabs color={colors['blue-button']} variant='pills' defaultValue={"Sejarah Desa"}>
|
||||
<TabsList p={"xs"} bg={"#BBC8E7FF"}>
|
||||
<TabsTab value="Sejarah Desa">
|
||||
Sejarah Desa
|
||||
</TabsTab>
|
||||
<TabsTab value="Visi Misi Desa">
|
||||
Visi Misi Desa
|
||||
</TabsTab>
|
||||
<TabsTab value="Lambang Desa">
|
||||
Lambang Desa
|
||||
</TabsTab>
|
||||
<TabsTab value="Maskot Desa">
|
||||
Maskot Desa
|
||||
</TabsTab>
|
||||
<TabsTab value="Profile Perbekel">
|
||||
Profile Perbekel
|
||||
</TabsTab>
|
||||
</TabsList>
|
||||
|
||||
<TabsPanel value="Sejarah Desa">
|
||||
<SejarahDesa/>
|
||||
</TabsPanel>
|
||||
<TabsPanel value="Visi Misi Desa">
|
||||
<VisiMisiDesa/>
|
||||
</TabsPanel>
|
||||
<TabsPanel value="Lambang Desa">
|
||||
<LambangDesa/>
|
||||
</TabsPanel>
|
||||
<TabsPanel value="Maskot Desa">
|
||||
<MaskotDesa/>
|
||||
</TabsPanel>
|
||||
<TabsPanel value="Profile Perbekel">
|
||||
<ProfilePerbekel/>
|
||||
</TabsPanel>
|
||||
</Tabs>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
export default Page;
|
||||
134
src/app/admin/(dashboard)/desa/profile/profile-desa/page.tsx
Normal file
134
src/app/admin/(dashboard)/desa/profile/profile-desa/page.tsx
Normal file
@@ -0,0 +1,134 @@
|
||||
'use client'
|
||||
import colors from '@/con/colors';
|
||||
import { Paper, Stack, Grid, GridCol, Title, Button, Box, Text, Center, Image, SimpleGrid } from '@mantine/core';
|
||||
import { IconEdit } from '@tabler/icons-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import React from 'react';
|
||||
|
||||
function Page() {
|
||||
const router = useRouter()
|
||||
return (
|
||||
<Paper bg={colors['white-1']} p={'md'} radius={10}>
|
||||
<Stack gap={"22"}>
|
||||
<Grid>
|
||||
<GridCol span={{ base: 12, md: 11 }}>
|
||||
<Title order={2}>Preview Profile Desa</Title>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 1 }}>
|
||||
<Button bg={colors['blue-button']} onClick={() => router.push('/admin/desa/profile/edit/sejarah_desa')}>
|
||||
<IconEdit size={16} />
|
||||
</Button>
|
||||
</GridCol>
|
||||
</Grid>
|
||||
{/* Sejarah Desa */}
|
||||
<Box>
|
||||
<Stack gap={'lg'}>
|
||||
<Paper p={"xl"} bg={colors['BG-trans']}>
|
||||
<Box pb={30}>
|
||||
<Center>
|
||||
<Image src={"/darmasaba-icon.png"} alt="" w={{ base: 200, md: 300 }} />
|
||||
</Center>
|
||||
<Text c={colors['blue-button']} ta={"center"} fw={"bold"} fz={"2.5rem"}>Sejarah Desa</Text>
|
||||
</Box>
|
||||
<Paper p={"xl"} bg={colors['white-trans-1']} w={{ base: "100%", md: "100%" }}>
|
||||
<Text fz={{ base: "md", md: "h3" }} ta={"justify"}>
|
||||
Test
|
||||
</Text>
|
||||
</Paper>
|
||||
</Paper>
|
||||
</Stack>
|
||||
</Box>
|
||||
{/* Visi Misi Desa */}
|
||||
<Box>
|
||||
<Stack gap={'lg'}>
|
||||
<Paper p={"xl"} bg={colors['BG-trans']}>
|
||||
<Box pb={30}>
|
||||
<Center>
|
||||
<Image src={"/darmasaba-icon.png"} alt="" w={{ base: 200, md: 300 }} />
|
||||
</Center>
|
||||
</Box>
|
||||
<Paper p={"xl"} bg={colors['white-trans-1']} w={{ base: "100%", md: "100%" }}>
|
||||
<Text c={colors['blue-button']} ta={"center"} fw={"bold"} fz={"2.5rem"}>Visi Desa</Text>
|
||||
<Text fz={{ base: "md", md: "h3" }} ta={"justify"}>
|
||||
Test
|
||||
</Text>
|
||||
</Paper>
|
||||
<Paper p={"xl"} bg={colors['white-trans-1']} w={{ base: "100%", md: "100%" }}>
|
||||
<Text c={colors['blue-button']} ta={"center"} fw={"bold"} fz={"2.5rem"}>Misi Desa</Text>
|
||||
<Text fz={{ base: "md", md: "h3" }} ta={"justify"}>
|
||||
Test
|
||||
</Text>
|
||||
</Paper>
|
||||
</Paper>
|
||||
</Stack>
|
||||
</Box>
|
||||
{/* Lambang Desa */}
|
||||
<Box>
|
||||
<Stack gap={'lg'}>
|
||||
<Paper p={"xl"} bg={colors['BG-trans']}>
|
||||
<Box pb={30}>
|
||||
<Center>
|
||||
<Image src={"/darmasaba-icon.png"} alt="" w={{ base: 200, md: 300 }} />
|
||||
</Center>
|
||||
<Text c={colors['blue-button']} ta={"center"} fw={"bold"} fz={"2.5rem"}>Lambang Desa</Text>
|
||||
</Box>
|
||||
<Paper p={"xl"} bg={colors['white-trans-1']} w={{ base: "100%", md: "100%" }}>
|
||||
<Text fz={{ base: "md", md: "h3" }} ta={"justify"}>
|
||||
Test
|
||||
</Text>
|
||||
</Paper>
|
||||
</Paper>
|
||||
</Stack>
|
||||
</Box>
|
||||
{/* Maskot Desa */}
|
||||
<Box>
|
||||
<Stack gap={'lg'}>
|
||||
<Paper p={"xl"} bg={colors['BG-trans']}>
|
||||
<Box pb={30}>
|
||||
<Center>
|
||||
<Image src={"/darmasaba-icon.png"} alt="" w={{ base: 200, md: 300 }} />
|
||||
</Center>
|
||||
<Text c={colors['blue-button']} ta={"center"} fw={"bold"} fz={"2.5rem"}>Maskot Desa</Text>
|
||||
</Box>
|
||||
<Paper p={"xl"} bg={colors['white-trans-1']} w={{ base: "100%", md: "100%" }}>
|
||||
<Text fz={{ base: "md", md: "h3" }} ta={"justify"}>
|
||||
Test
|
||||
</Text>
|
||||
</Paper>
|
||||
<SimpleGrid
|
||||
cols={{
|
||||
base: 1,
|
||||
md: 2,
|
||||
}}
|
||||
>
|
||||
<Center>
|
||||
<Box>
|
||||
<Paper p={"lg"}>
|
||||
<Image src={"/api/img/pohonpudak.png"} alt="" w={{ base: 150, md: 250 }} />
|
||||
<Text ta={"center"} fw={"bold"} c={colors["blue-button"]} fz={{ base: "md", md: "h3" }}>Pohon Pudak</Text>
|
||||
</Paper>
|
||||
</Box>
|
||||
</Center>
|
||||
<Center>
|
||||
<Box>
|
||||
<Paper p={"lg"}>
|
||||
<Image src={"/api/img/bungapudak.png"} alt="" w={{ base: 150, md: 250 }} />
|
||||
<Text ta={"center"} fw={"bold"} c={colors["blue-button"]} fz={{ base: "md", md: "h3" }}>Bunga Pudak</Text>
|
||||
</Paper>
|
||||
</Box>
|
||||
</Center>
|
||||
</SimpleGrid>
|
||||
<Paper p={"xl"} bg={colors['white-trans-1']} w={{ base: "100%", md: "100%" }}>
|
||||
<Text fz={{ base: "md", md: "h3" }} ta={"justify"}>
|
||||
Test
|
||||
</Text>
|
||||
</Paper>
|
||||
</Paper>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
export default Page;
|
||||
@@ -0,0 +1,12 @@
|
||||
import colors from '@/con/colors';
|
||||
import { Paper, Text } from '@mantine/core';
|
||||
|
||||
function Page() {
|
||||
return (
|
||||
<Paper bg={colors['white-1']} p={'md'}>
|
||||
<Text>Test</Text>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
export default Page;
|
||||
@@ -1,17 +0,0 @@
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Paper, Stack, Title } from '@mantine/core';
|
||||
import React from 'react';
|
||||
|
||||
function ListPage() {
|
||||
return (
|
||||
<Box>
|
||||
<Paper bg={colors['white-1']} p={'md'}>
|
||||
<Stack>
|
||||
<Title order={3}>List Sejarah Desa</Title>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export default ListPage;
|
||||
@@ -1,65 +0,0 @@
|
||||
'use client'
|
||||
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
|
||||
import colors from '@/con/colors';
|
||||
import { Box, Button, Group, Paper, SimpleGrid, Stack, Text, Title } from '@mantine/core';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import DesaEditorText from '../../../_com/desaEditorText';
|
||||
import ListPage from './listPage';
|
||||
import { useShallowEffect } from '@mantine/hooks';
|
||||
|
||||
|
||||
function SejarahDesa() {
|
||||
const stateSejarah = useProxy(stateProfileDesa.Sejarah)
|
||||
|
||||
useShallowEffect(() => {
|
||||
if (!stateSejarah.findById.data) {
|
||||
stateSejarah.findById.initialize()
|
||||
}
|
||||
}, [])
|
||||
|
||||
const submit = () => {
|
||||
if (stateSejarah.findById.data?.id && stateSejarah.findById.data.sejarah) {
|
||||
stateSejarah.update.save({
|
||||
id: stateSejarah.findById.data.id,
|
||||
sejarah: stateSejarah.findById.data.sejarah
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Box py={10}>
|
||||
<SimpleGrid cols={{ base: 1, md: 2 }}>
|
||||
<Box>
|
||||
<Paper bg={colors['white-1']} p={'md'}>
|
||||
<Stack>
|
||||
<Title order={3}>Sejarah Desa</Title>
|
||||
<Text fw={"bold"}>Deskripsi Sejarah Desa</Text>
|
||||
<DesaEditorText
|
||||
key={stateSejarah.findById.data?.id ?? 'new'}
|
||||
showSubmit={false}
|
||||
onChange={(val) => {
|
||||
if (stateSejarah.findById.data) {
|
||||
stateSejarah.findById.data.sejarah = val
|
||||
}
|
||||
}}
|
||||
initialContent={stateSejarah.findById.data?.sejarah ?? ""}
|
||||
/>
|
||||
<Group>
|
||||
<Button
|
||||
mt={10}
|
||||
bg={colors['blue-button']}
|
||||
onClick={submit}
|
||||
>
|
||||
Submit
|
||||
</Button>
|
||||
</Group>
|
||||
</Stack>
|
||||
</Paper>
|
||||
</Box>
|
||||
<ListPage />
|
||||
</SimpleGrid>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export default SejarahDesa;
|
||||
@@ -45,7 +45,7 @@ function Page() {
|
||||
<Grid>
|
||||
<GridCol span={{ base: 12, md: 12 }}>
|
||||
<Center>
|
||||
<Image src={"/api/img/darmasaba-icon.png"} w={{ base: 100, md: 150 }} alt='' />
|
||||
<Image src={"/darmasaba-icon.png"} w={{ base: 100, md: 150 }} alt='' />
|
||||
</Center>
|
||||
</GridCol>
|
||||
<GridCol span={{ base: 12, md: 12 }}>
|
||||
@@ -62,7 +62,7 @@ function Page() {
|
||||
<Center>
|
||||
<Image
|
||||
pt={{ base: 0, md: 90 }}
|
||||
src={item.image?.link}
|
||||
src={item.image?.link || "/perbekel.png"}
|
||||
w={{ base: 250, md: 350 }}
|
||||
alt='Foto Profil PPID'
|
||||
onError={(e) => {
|
||||
|
||||
@@ -108,7 +108,7 @@ export const navBar = [
|
||||
{
|
||||
id: "Desa_1",
|
||||
name: "Profile",
|
||||
path: "/admin/desa/profile"
|
||||
path: "/admin/desa/profile/profile-desa"
|
||||
},
|
||||
{
|
||||
id: "Desa_2",
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
|
||||
export default async function profilePerbekelFindById(request: Request) {
|
||||
const url = new URL(request.url);
|
||||
const pathSegments = url.pathname.split('/');
|
||||
const id = pathSegments[pathSegments.length - 1];
|
||||
|
||||
if (!id) {
|
||||
return Response.json({
|
||||
success: false,
|
||||
message: "ID tidak boleh kosong",
|
||||
}, { status: 400 });
|
||||
}
|
||||
|
||||
try {
|
||||
if (typeof id !== 'string') {
|
||||
return Response.json({
|
||||
success: false,
|
||||
message: "ID tidak valid",
|
||||
}, { status: 400 });
|
||||
}
|
||||
|
||||
const data = await prisma.profilPerbekel.findUnique({
|
||||
where: { id },
|
||||
include: {
|
||||
image: true,
|
||||
}
|
||||
});
|
||||
|
||||
if (!data) {
|
||||
return Response.json({
|
||||
success: false,
|
||||
message: "Data tidak ditemukan",
|
||||
}, { status: 404 });
|
||||
}
|
||||
|
||||
return Response.json({
|
||||
success: true,
|
||||
message: "Data berhasil ditemukan",
|
||||
data,
|
||||
}, { status: 200 });
|
||||
} catch (error) {
|
||||
console.error("Error fetching profile Perbekel:", error);
|
||||
return Response.json({
|
||||
success: false,
|
||||
message: "Terjadi kesalahan saat mengambil data profile Perbekel",
|
||||
}, { status: 500 });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import Elysia, { t } from "elysia";
|
||||
import profilePerbekelFindById from "./find-by-id";
|
||||
import profilePerbekelUpdate from "./update";
|
||||
|
||||
const ProfilPerbekel = new Elysia({
|
||||
prefix: "/profileperbekel",
|
||||
tags: ["Desa/Profile"],
|
||||
})
|
||||
.get("/:id", async (context) => {
|
||||
const response = await profilePerbekelFindById(
|
||||
new Request(context.request)
|
||||
);
|
||||
return response;
|
||||
})
|
||||
.put(
|
||||
"/:id",
|
||||
async (context) => {
|
||||
const response = await profilePerbekelUpdate(context);
|
||||
return response;
|
||||
},
|
||||
{
|
||||
body: t.Object({
|
||||
biodata: t.String(),
|
||||
pengalaman: t.String(),
|
||||
pengalamanOrganisasi: t.String(),
|
||||
programUnggulan: t.String(),
|
||||
imageId: t.String(),
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
export default ProfilPerbekel;
|
||||
@@ -1,33 +1,118 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { Context } from "elysia";
|
||||
import path from "path";
|
||||
import fs from "fs/promises";
|
||||
|
||||
type FormCreate = Prisma.ProfilPerbekelGetPayload<{
|
||||
select: {
|
||||
id: true;
|
||||
biodata: true;
|
||||
pengalaman: true;
|
||||
pengalamanOrganisasi: true;
|
||||
programUnggulan: true;
|
||||
}
|
||||
}>
|
||||
type FormUpdate = Prisma.ProfilPerbekelGetPayload<{
|
||||
select: {
|
||||
id: true;
|
||||
biodata: true;
|
||||
pengalaman: true;
|
||||
pengalamanOrganisasi: true;
|
||||
programUnggulan: true;
|
||||
imageId: true;
|
||||
};
|
||||
}>;
|
||||
export default async function profilePerbekelUpdate(context: Context) {
|
||||
const body = context.body as FormCreate;
|
||||
try {
|
||||
const id = context.params?.id as string;
|
||||
const body = (await context.body) as Omit<FormUpdate, "id">;
|
||||
|
||||
await prisma.profilPerbekel.update({
|
||||
where: {
|
||||
id: body.id
|
||||
},
|
||||
const { biodata, pengalaman, pengalamanOrganisasi, programUnggulan, imageId } = body;
|
||||
|
||||
if (!id) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
success: false,
|
||||
message: "ID tidak boleh kosong",
|
||||
}),
|
||||
{
|
||||
status: 400,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const exisitng = await prisma.profilPerbekel.findUnique({
|
||||
where: {
|
||||
id,
|
||||
},
|
||||
include: {
|
||||
image: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!exisitng) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
success: false,
|
||||
message: "Data tidak ditemukan",
|
||||
}),
|
||||
{
|
||||
status: 404,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (exisitng.imageId !== imageId) {
|
||||
const oldImage = exisitng.image;
|
||||
if (oldImage) {
|
||||
try {
|
||||
const filePath = path.join(oldImage.path, oldImage.name);
|
||||
await fs.unlink(filePath);
|
||||
await prisma.fileStorage.delete({
|
||||
where: { id: oldImage.id },
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("Gagal hapus gambar lama:", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const updated = await prisma.profilPerbekel.update({
|
||||
where: {id},
|
||||
data: {
|
||||
biodata: body.biodata,
|
||||
pengalaman: body.pengalaman,
|
||||
pengalamanOrganisasi: body.pengalamanOrganisasi,
|
||||
programUnggulan: body.programUnggulan,
|
||||
biodata,
|
||||
pengalaman,
|
||||
pengalamanOrganisasi,
|
||||
programUnggulan,
|
||||
imageId,
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: "Profile Perbekel Berhasil Diupdate",
|
||||
}
|
||||
}
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
success: true,
|
||||
message: "Data berhasil diperbarui",
|
||||
data: updated,
|
||||
}),
|
||||
{
|
||||
status: 200,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error updating profile Perbekel:", error);
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
success: false,
|
||||
message: "Terjadi kesalahan saat mengupdate profile Perbekel",
|
||||
}),
|
||||
{
|
||||
status: 500,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
import { Context } from "elysia";
|
||||
|
||||
export default async function profileDesaFindById(context: Context) {
|
||||
try {
|
||||
const id = context?.params?.slugs?.[0];
|
||||
|
||||
// If no ID provided, get the first profile
|
||||
if (!id) {
|
||||
const data = await prisma.profileDesa.findFirst();
|
||||
return {
|
||||
success: true,
|
||||
data,
|
||||
};
|
||||
}
|
||||
|
||||
const data = await prisma.profileDesa.findUniqueOrThrow({
|
||||
where: { id },
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Error fetching profileDesa:", error);
|
||||
|
||||
return {
|
||||
success: false,
|
||||
message: error instanceof Error ? error.message : "Unknown error",
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,51 +1,16 @@
|
||||
import Elysia, { t } from "elysia";
|
||||
import lambangDesaUpdate from "./lambangDesa/update";
|
||||
import maskotDesaUpdate from "./maskotDesa/update";
|
||||
import profilePerbekelUpdate from "../profilePerbekel/update";
|
||||
import sejarahDesaUpdate from "./sejarah/update";
|
||||
import visimisiDesaUpdate from "./visimisiDesa/update";
|
||||
import profileDesaFindById from "./find-by-id";
|
||||
import SejarahDesa from "./sejarah";
|
||||
import VisiMisiDesa from "./visi-misi";
|
||||
import LambangDesa from "./lambang-desa";
|
||||
import MaskotDesa from "./maskot-desa";
|
||||
import Elysia from "elysia";
|
||||
|
||||
const ProfileDesa = new Elysia({
|
||||
prefix: "/profile",
|
||||
tags: ["Desa/Profile"]
|
||||
})
|
||||
.get("/find-by-id", profileDesaFindById)
|
||||
.post("/profilePerbekel/update", profilePerbekelUpdate, {
|
||||
body: t.Object({
|
||||
id: t.String(),
|
||||
biodata: t.String(),
|
||||
pengalaman: t.String(),
|
||||
pengalamanOrganisasi: t.String(),
|
||||
programUnggulan: t.String(),
|
||||
})
|
||||
})
|
||||
.post("/visimisiDesa/update", visimisiDesaUpdate, {
|
||||
body: t.Object({
|
||||
id: t.String(),
|
||||
visi: t.String(),
|
||||
misi: t.String(),
|
||||
})
|
||||
})
|
||||
.post("/sejarah/update", sejarahDesaUpdate, {
|
||||
body: t.Object({
|
||||
id: t.String(),
|
||||
sejarah: t.String(),
|
||||
})
|
||||
})
|
||||
.post("/lambangDesa/update", lambangDesaUpdate, {
|
||||
body: t.Object({
|
||||
id: t.String(),
|
||||
lambang: t.String(),
|
||||
})
|
||||
})
|
||||
.post("/maskotDesa/update", maskotDesaUpdate, {
|
||||
body: t.Object({
|
||||
id: t.String(),
|
||||
maskot: t.String(),
|
||||
})
|
||||
prefix: "/profile",
|
||||
tags: ["Desa/Profile"],
|
||||
})
|
||||
.use(SejarahDesa)
|
||||
.use(VisiMisiDesa)
|
||||
.use(LambangDesa)
|
||||
.use(MaskotDesa);
|
||||
|
||||
|
||||
|
||||
export default ProfileDesa
|
||||
export default ProfileDesa;
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
|
||||
export default async function lambangDesaFindById(request: Request) {
|
||||
const url = new URL(request.url);
|
||||
const pathSegments = url.pathname.split("/");
|
||||
const id = pathSegments[pathSegments.length - 1];
|
||||
|
||||
if (!id) {
|
||||
return Response.json(
|
||||
{
|
||||
success: false,
|
||||
message: "ID tidak boleh kosong",
|
||||
},
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
if (typeof id !== "string") {
|
||||
return Response.json(
|
||||
{
|
||||
success: false,
|
||||
message: "ID tidak valid",
|
||||
},
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
const data = await prisma.lambangDesa.findUnique({
|
||||
where: { id },
|
||||
});
|
||||
|
||||
if (!data) {
|
||||
return Response.json(
|
||||
{
|
||||
success: false,
|
||||
message: "Data tidak ditemukan",
|
||||
},
|
||||
{ status: 404 }
|
||||
);
|
||||
}
|
||||
|
||||
return Response.json(
|
||||
{
|
||||
success: true,
|
||||
data,
|
||||
},
|
||||
{ status: 200 }
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("Gagal mengambil data lambang desa:", error);
|
||||
return Response.json(
|
||||
{
|
||||
success: false,
|
||||
message: "Terjadi kesalahan saat mengambil data",
|
||||
},
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import Elysia, { t } from "elysia";
|
||||
|
||||
import lambangDesaFindById from "./find-by-id";
|
||||
import lambangDesaUpdate from "./update";
|
||||
|
||||
const LambangDesa = new Elysia({
|
||||
prefix: "/lambang",
|
||||
tags: ["Desa/Profile"],
|
||||
})
|
||||
.get("/:id", async (context) => {
|
||||
const response = await lambangDesaFindById(new Request(context.request));
|
||||
return response;
|
||||
})
|
||||
.put(
|
||||
"/:id",
|
||||
async (context) => {
|
||||
const response = await lambangDesaUpdate(context);
|
||||
return response;
|
||||
},
|
||||
{
|
||||
body: t.Object({
|
||||
judul: t.String(),
|
||||
deskripsi: t.String(),
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
export default LambangDesa;
|
||||
@@ -0,0 +1,50 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
import { Context } from "elysia";
|
||||
|
||||
export default async function lambangDesaUpdate(context: Context) {
|
||||
try {
|
||||
const id = context.params?.id as string;
|
||||
const body = await context.body as {
|
||||
judul: string;
|
||||
deskripsi: string;
|
||||
};
|
||||
|
||||
if (!id) {
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
message: "ID tidak boleh kosong",
|
||||
}), { status: 400 });
|
||||
}
|
||||
|
||||
const existing = await prisma.lambangDesa.findUnique({
|
||||
where: { id },
|
||||
});
|
||||
|
||||
if (!existing) {
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
message: "Data tidak ditemukan",
|
||||
}), { status: 404 });
|
||||
}
|
||||
|
||||
const updated = await prisma.lambangDesa.update({
|
||||
where: { id },
|
||||
data: {
|
||||
judul: body.judul,
|
||||
deskripsi: body.deskripsi,
|
||||
},
|
||||
});
|
||||
|
||||
return new Response(JSON.stringify({
|
||||
success: true,
|
||||
message: "Berhasil memperbarui data",
|
||||
data: updated,
|
||||
}), { status: 200 });
|
||||
} catch (error) {
|
||||
console.error("Update error:", error);
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
message: "Gagal memperbarui data: " + (error instanceof Error ? error.message : 'Unknown error'),
|
||||
}), { status: 500 });
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { Context } from "elysia";
|
||||
|
||||
type FormCreate = Prisma.ProfileDesaGetPayload<{
|
||||
select: {
|
||||
id: true;
|
||||
lambang: true;
|
||||
}
|
||||
}>
|
||||
|
||||
export default async function lambangDesaUpdate(context: Context) {
|
||||
const body = context.body as FormCreate;
|
||||
|
||||
await prisma.profileDesa.update({
|
||||
where: {
|
||||
id: body.id
|
||||
},
|
||||
data: {
|
||||
lambang: body.lambang,
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: "Profile Desa Berhasil Diupdate",
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
|
||||
export default async function maskotDesaFindById(request: Request){
|
||||
const url = new URL(request.url);
|
||||
const pathSegments = url.pathname.split('/');
|
||||
const id = pathSegments[pathSegments.length - 1];
|
||||
|
||||
if (!id) {
|
||||
return Response.json({
|
||||
success: false,
|
||||
message: "ID tidak boleh kosong",
|
||||
}, {status: 400})
|
||||
}
|
||||
|
||||
try {
|
||||
if (typeof id !== 'string') {
|
||||
return Response.json({
|
||||
success: false,
|
||||
message: "ID tidak valid",
|
||||
}, {status: 400})
|
||||
}
|
||||
|
||||
const data = await prisma.maskotDesa.findUnique({
|
||||
where: { id },
|
||||
include: {
|
||||
images: {
|
||||
include: {
|
||||
image: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if(!data) {
|
||||
return Response.json({
|
||||
success: false,
|
||||
message: "Data tidak ditemukan",
|
||||
}, {status: 404})
|
||||
}
|
||||
|
||||
return Response.json({
|
||||
success: true,
|
||||
message: "Berhasil mengambil data berdasarkan ID",
|
||||
data,
|
||||
}, {status: 200})
|
||||
} catch (error) {
|
||||
console.error("Find by ID error:", error);
|
||||
return Response.json({
|
||||
success: false,
|
||||
message: "Gagal mengambil data: " + (error instanceof Error ? error.message : 'Unknown error'),
|
||||
}, {status: 500})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import maskotDesaUpdate from "./update";
|
||||
import maskotDesaFindById from "./find-by-id";
|
||||
import Elysia, { t } from "elysia";
|
||||
|
||||
const MaskotDesa = new Elysia({
|
||||
prefix: "/maskot",
|
||||
tags: ["Desa/Profile"],
|
||||
})
|
||||
.get("/:id", async (context) => {
|
||||
const response = await maskotDesaFindById(new Request(context.request));
|
||||
return response;
|
||||
})
|
||||
.put(
|
||||
"/:id",
|
||||
async (context) => {
|
||||
const response = await maskotDesaUpdate(context);
|
||||
return response;
|
||||
},
|
||||
{
|
||||
body: t.Object({
|
||||
maskot: t.String(),
|
||||
images: t.Array(
|
||||
t.Object({
|
||||
imageId: t.String(),
|
||||
label: t.String(),
|
||||
})
|
||||
),
|
||||
}),
|
||||
}
|
||||
)
|
||||
export default MaskotDesa;
|
||||
@@ -0,0 +1,78 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
import { Context } from "elysia";
|
||||
|
||||
export default async function maskotDesaUpdate(context: Context) {
|
||||
try {
|
||||
const id = context.params?.id as string;
|
||||
const body = await context.body as {
|
||||
judul: string;
|
||||
deskripsi: string;
|
||||
images: { label: string; imageId: string }[];
|
||||
};
|
||||
|
||||
if (!id) {
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
message: "ID tidak boleh kosong",
|
||||
}), { status: 400 });
|
||||
}
|
||||
|
||||
const existing = await prisma.maskotDesa.findUnique({
|
||||
where: { id },
|
||||
include: { images: { include: { image: true } } }
|
||||
});
|
||||
|
||||
if (!existing) {
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
message: "Data tidak ditemukan",
|
||||
}), { status: 404 });
|
||||
}
|
||||
|
||||
// Hapus semua gambar lama (dan file-nya jika perlu)
|
||||
for (const old of existing.images) {
|
||||
try {
|
||||
await prisma.fileStorage.delete({ where: { id: old.imageId } });
|
||||
// opsional: hapus file dari disk juga kalau kamu simpan file fisik
|
||||
// await fs.unlink(path.join(old.image.path, old.image.name));
|
||||
} catch (error) {
|
||||
console.warn("Gagal hapus gambar lama:", error);
|
||||
}
|
||||
}
|
||||
|
||||
// Update profile & re-create images
|
||||
const updated = await prisma.maskotDesa.update({
|
||||
where: { id },
|
||||
data: {
|
||||
judul: body.judul,
|
||||
deskripsi: body.deskripsi,
|
||||
images: {
|
||||
deleteMany: {},
|
||||
create: body.images.map((img) => ({
|
||||
label: img.label,
|
||||
imageId: img.imageId
|
||||
}))
|
||||
}
|
||||
},
|
||||
include: {
|
||||
images: {
|
||||
include: {
|
||||
image: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return new Response(JSON.stringify({
|
||||
success: true,
|
||||
message: "Data berhasil diperbarui",
|
||||
data: updated,
|
||||
}), { status: 200 });
|
||||
} catch (error) {
|
||||
console.error("Gagal update MaskotDesa:", error);
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
message: "Terjadi kesalahan saat update",
|
||||
}), { status: 500 });
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { Context } from "elysia";
|
||||
|
||||
type FormCreate = Prisma.ProfileDesaGetPayload<{
|
||||
select: {
|
||||
id: true;
|
||||
maskot: true;
|
||||
}
|
||||
}>
|
||||
|
||||
export default async function maskotDesaUpdate(context: Context) {
|
||||
const body = context.body as FormCreate;
|
||||
|
||||
await prisma.profileDesa.update({
|
||||
where: {
|
||||
id: body.id
|
||||
},
|
||||
data: {
|
||||
maskot: body.maskot,
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: "Profile Desa Berhasil Diupdate",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
|
||||
export default async function sejarahDesaFindById(request: Request) {
|
||||
const url = new URL(request.url);
|
||||
const pathSegments = url.pathname.split('/');
|
||||
const id = pathSegments[pathSegments.length - 1];
|
||||
|
||||
if (!id) {
|
||||
return Response.json({
|
||||
success: false,
|
||||
message: "ID tidak boleh kosong",
|
||||
}, {status: 400})
|
||||
}
|
||||
|
||||
try {
|
||||
if (typeof id !== 'string') {
|
||||
return Response.json({
|
||||
success: false,
|
||||
message: "ID tidak valid",
|
||||
}, {status: 400})
|
||||
}
|
||||
|
||||
const data = await prisma.sejarahDesa.findUnique({
|
||||
where: { id },
|
||||
})
|
||||
|
||||
if (!data) {
|
||||
return Response.json({
|
||||
success: false,
|
||||
message: "Data tidak ditemukan",
|
||||
}, {status: 404})
|
||||
}
|
||||
|
||||
return Response.json({
|
||||
success: true,
|
||||
data,
|
||||
}, {status: 200})
|
||||
} catch (error) {
|
||||
console.error("Gagal mengambil data sejarah desa:", error)
|
||||
return Response.json({
|
||||
success: false,
|
||||
message: "Terjadi kesalahan saat mengambil data",
|
||||
}, {status: 500})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import Elysia, { t } from "elysia";
|
||||
import sejarahDesaFindById from "./find-by-id";
|
||||
import sejarahDesaUpdate from "./update";
|
||||
|
||||
const SejarahDesa = new Elysia({
|
||||
prefix: "/sejarah",
|
||||
tags: ["Desa/Profile"],
|
||||
})
|
||||
.get("/:id", async (context) => {
|
||||
const response = await sejarahDesaFindById(new Request(context.request));
|
||||
return response;
|
||||
})
|
||||
.put(
|
||||
"/:id",
|
||||
async (context) => {
|
||||
const response = await sejarahDesaUpdate(context);
|
||||
return response;
|
||||
},
|
||||
{
|
||||
body: t.Object({
|
||||
judul: t.String(),
|
||||
deskripsi: t.String(),
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
export default SejarahDesa;
|
||||
@@ -1,29 +1,50 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { Context } from "elysia";
|
||||
|
||||
type FormCreate = Prisma.ProfileDesaGetPayload<{
|
||||
select: {
|
||||
id: true;
|
||||
sejarah: true;
|
||||
}
|
||||
}>
|
||||
|
||||
export default async function sejarahDesaUpdate(context: Context) {
|
||||
const body = context.body as FormCreate;
|
||||
try {
|
||||
const id = context.params?.id as string;
|
||||
const body = await context.body as {
|
||||
judul: string;
|
||||
deskripsi: string;
|
||||
};
|
||||
|
||||
await prisma.profileDesa.update({
|
||||
where: {
|
||||
id: body.id
|
||||
},
|
||||
data: {
|
||||
sejarah: body.sejarah,
|
||||
if (!id) {
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
message: "ID tidak boleh kosong",
|
||||
}), { status: 400 });
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: "Profile Desa Berhasil Diupdate",
|
||||
const existing = await prisma.sejarahDesa.findUnique({
|
||||
where: { id },
|
||||
});
|
||||
|
||||
if (!existing) {
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
message: "Data tidak ditemukan",
|
||||
}), { status: 404 });
|
||||
}
|
||||
|
||||
const updated = await prisma.sejarahDesa.update({
|
||||
where: { id },
|
||||
data: {
|
||||
judul: body.judul,
|
||||
deskripsi: body.deskripsi,
|
||||
},
|
||||
});
|
||||
|
||||
return new Response(JSON.stringify({
|
||||
success: true,
|
||||
message: "Berhasil memperbarui data",
|
||||
data: updated,
|
||||
}), { status: 200 });
|
||||
} catch (error) {
|
||||
console.error("Update error:", error);
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
message: "Gagal memperbarui data: " + (error instanceof Error ? error.message : 'Unknown error'),
|
||||
}), { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
|
||||
export default async function visiMisiDesaFindById(request: Request) {
|
||||
const url = new URL(request.url);
|
||||
const pathSegments = url.pathname.split('/');
|
||||
const id = pathSegments[pathSegments.length - 1];
|
||||
|
||||
if (!id) {
|
||||
return Response.json({
|
||||
success: false,
|
||||
message: "ID tidak boleh kosong",
|
||||
}, {status: 400})
|
||||
}
|
||||
|
||||
try {
|
||||
if (typeof id !== 'string') {
|
||||
return Response.json({
|
||||
success: false,
|
||||
message: "ID tidak valid",
|
||||
}, {status: 400})
|
||||
}
|
||||
|
||||
const data = await prisma.visiMisiDesa.findUnique({
|
||||
where: { id },
|
||||
})
|
||||
|
||||
if (!data) {
|
||||
return Response.json({
|
||||
success: false,
|
||||
message: "Data tidak ditemukan",
|
||||
}, {status: 404})
|
||||
}
|
||||
|
||||
return Response.json({
|
||||
success: true,
|
||||
message: "Data ditemukan",
|
||||
data: data,
|
||||
}, {status: 200})
|
||||
} catch (error) {
|
||||
console.error("Find by ID error:", error);
|
||||
return Response.json({
|
||||
success: false,
|
||||
message: "Gagal menemukan data: " + (error instanceof Error ? error.message : 'Unknown error'),
|
||||
}, {status: 500})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import Elysia, { t } from "elysia";
|
||||
import visiMisiDesaUpdate from "./update";
|
||||
import visiMisiDesaFindById from "./find-by-id";
|
||||
|
||||
const VisiMisiDesa = new Elysia({
|
||||
prefix: "/visi-misi",
|
||||
tags: ["Desa/Profile"],
|
||||
})
|
||||
.get("/:id", async (context) => {
|
||||
const response = await visiMisiDesaFindById(new Request(context.request));
|
||||
return response;
|
||||
})
|
||||
.put(
|
||||
"/:id",
|
||||
async (context) => {
|
||||
const response = await visiMisiDesaUpdate(context);
|
||||
return response;
|
||||
},
|
||||
{
|
||||
body: t.Object({
|
||||
visi: t.String(),
|
||||
misi: t.String(),
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
export default VisiMisiDesa;
|
||||
@@ -0,0 +1,50 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
import { Context } from "elysia";
|
||||
|
||||
export default async function visiMisiDesaUpdate(context: Context) {
|
||||
try {
|
||||
const id = context.params?.id as string;
|
||||
const body = await context.body as {
|
||||
visi: string;
|
||||
misi: string;
|
||||
};
|
||||
|
||||
if (!id) {
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
message: "ID tidak boleh kosong",
|
||||
}), { status: 400 });
|
||||
}
|
||||
|
||||
const existing = await prisma.visiMisiDesa.findUnique({
|
||||
where: { id },
|
||||
});
|
||||
|
||||
if (!existing) {
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
message: "Data tidak ditemukan",
|
||||
}), { status: 404 });
|
||||
}
|
||||
|
||||
const updated = await prisma.visiMisiDesa.update({
|
||||
where: { id },
|
||||
data: {
|
||||
visi: body.visi,
|
||||
misi: body.misi,
|
||||
},
|
||||
});
|
||||
|
||||
return new Response(JSON.stringify({
|
||||
success: true,
|
||||
message: "Berhasil memperbarui data",
|
||||
data: updated,
|
||||
}), { status: 200 });
|
||||
} catch (error) {
|
||||
console.error("Update error:", error);
|
||||
return new Response(JSON.stringify({
|
||||
success: false,
|
||||
message: "Gagal memperbarui data: " + (error instanceof Error ? error.message : 'Unknown error'),
|
||||
}), { status: 500 });
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import prisma from "@/lib/prisma";
|
||||
import { Prisma } from "@prisma/client";
|
||||
import { Context } from "elysia";
|
||||
|
||||
type FormCreate = Prisma.ProfileDesaGetPayload<{
|
||||
select: {
|
||||
id: true;
|
||||
visi: true;
|
||||
misi: true;
|
||||
}
|
||||
}>
|
||||
export default async function visimisiDesaUpdate(context: Context) {
|
||||
const body = context.body as FormCreate;
|
||||
|
||||
await prisma.profileDesa.update({
|
||||
where: {
|
||||
id: body.id
|
||||
},
|
||||
data: {
|
||||
visi: body.visi,
|
||||
misi: body.misi,
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: "Profile Desa Berhasil Diupdate",
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user